code: func (s *MemoryStore) Batch(cb func(*Batch) error) error {
  	defer metrics.StartTimer(batchLatencyTimer)()
  	s.updateLock.Lock()
  
  	batch := Batch{
  		store: s,
  	}
  	batch.newTx()
  
  	if err := cb(&batch); err != nil {
  		batch.tx.memDBTx.Abort()
  		s.updateLock.Unlock()
  		return err
  	}
  
  	err := batch.commit()
  	s.updateLock.Unlock()
  	return err
  }
docs: // Batch performs one or more transactions that allow reads and writes
  // It invokes a callback that is passed a Batch object. The callback may
  // call batch.Update for each change it wants to make as part of the
  // batch. The changes in the batch may be split over multiple
  // transactions if necessary to keep transactions below the size limit.
  // Batch holds a lock over the state, but will yield this lock every
  // it creates a new transaction to allow other writers to proceed.
  // Thus, unrelated changes to the state may occur between calls to
  // batch.Update.
  //
  // This method allows the caller to iterate over a data set and apply
  // changes in sequence without holding the store write lock for an
  // excessive time, or producing a transaction that exceeds the maximum
  // size.
  //
  // If Batch returns an error, no guarantees are made about how many updates
  // were committed successfully.