code: func (c *cmd) setupLock(client *api.Client, prefix, name string,
  	oneshot bool, wait time.Duration, retry int) (*LockUnlock, error) {
  	// Use the DefaultSemaphoreKey extension, this way if a lock and
  	// semaphore are both used at the same prefix, we will get a conflict
  	// which we can report to the user.
  	key := path.Join(prefix, api.DefaultSemaphoreKey)
  	if c.verbose {
  		c.UI.Info(fmt.Sprintf("Setting up lock at path: %s", key))
  	}
  	opts := api.LockOptions{
  		Key:              key,
  		SessionName:      name,
  		MonitorRetries:   retry,
  		MonitorRetryTime: defaultMonitorRetryTime,
  	}
  	if oneshot {
  		opts.LockTryOnce = true
  		opts.LockWaitTime = wait
  	}
  	l, err := client.LockOpts(&opts)
  	if err != nil {
  		return nil, err
  	}
  	lu := &LockUnlock{
  		lockFn:    l.Lock,
  		unlockFn:  l.Unlock,
  		cleanupFn: l.Destroy,
  		inUseErr:  api.ErrLockInUse,
  		rawOpts:   &opts,
  	}
  	return lu, nil
  }
docs: // setupLock is used to setup a new Lock given the API client, the key prefix to
  // operate on, and an optional session name. If oneshot is true then we will set
  // up for a single attempt at acquisition, using the given wait time. The retry
  // parameter sets how many 500 errors the lock monitor will tolerate before
  // giving up the lock.