code: func (bk *Backend) CompareAndSwapVal(bucket []string, key string, val []byte, prevVal []byte, ttl time.Duration) error {
  	// Open the bucket to work on the items.
  	b, err := bk.openBucket(bk.flatten(bucket), os.O_CREATE|os.O_RDWR)
  	if err != nil {
  		er := trace.ConvertSystemError(err)
  		if trace.IsNotFound(er) {
  			return trace.CompareFailed("%v/%v did not match expected value", bucket, key)
  		}
  		return trace.Wrap(er)
  	}
  	defer b.Close()
  
  	// Read in existing key. If it does not exist, is expired, or does not
  	// match, return trace.CompareFailed.
  	oldItem, ok := b.getItem(key)
  	if !ok {
  		return trace.CompareFailed("%v/%v did not match expected value", bucket, key)
  	}
  	if bk.isExpired(oldItem) {
  		return trace.CompareFailed("%v/%v did not match expected value", bucket, key)
  	}
  	if bytes.Compare(oldItem.Value, prevVal) != 0 {
  		return trace.CompareFailed("%v/%v did not match expected value", bucket, key)
  	}
  
  	// The compare was successful, update the item.
  	b.updateItem(key, val, ttl)
  
  	return nil
  }
docs: // CompareAndSwapVal compares and swap values in atomic operation