private OperationStatus[] batchMutate(BatchOperation<?> batchOp) throws IOException {
    boolean initialized = false;
    batchOp.startRegionOperation();
    try {
      while (!batchOp.isDone()) {
        if (!batchOp.isInReplay()) {
          checkReadOnly();
        }
        checkResources();

        if (!initialized) {
          this.writeRequestsCount.add(batchOp.size());
          // validate and prepare batch for write, for MutationBatchOperation it also calls CP
          // prePut()/preDelete()/preIncrement()/preAppend() hooks
          batchOp.checkAndPrepare();
          initialized = true;
        }
        doMiniBatchMutate(batchOp);
        requestFlushIfNeeded();
      }
    } finally {
      if (rsServices != null && rsServices.getMetrics() != null) {
        rsServices.getMetrics().updateWriteQueryMeter(this, batchOp.size());
      }
      batchOp.closeRegionOperation();
    }
    return batchOp.retCodeDetails;
  }
Perform a batch of mutations.
<p/>
Operations in a batch are stored with highest durability specified of for all operations in a
batch, except for {@link Durability#SKIP_WAL}.
<p/>
This function is called from {@link #batchReplay(WALSplitUtil.MutationReplay[], long)} with
{@link ReplayBatchOperation} instance and {@link #batchMutate(Mutation[])} with
{@link MutationBatchOperation} instance as an argument. As the processing of replay batch and
mutation batch is very similar, lot of code is shared by providing generic methods in base
class {@link BatchOperation}. The logic for this method and
{@link #doMiniBatchMutate(BatchOperation)} is implemented using methods in base class which are
overridden by derived classes to implement special behavior.
@param batchOp contains the list of mutations
@return an array of OperationStatus which internally contains the OperationStatusCode and the
        exceptionMessage if any.
@throws IOException if an IO problem is encountered
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java