/**
   * Do the commit. This is the 2nd phase of the 2-phase protocol.
   *
   * @param transactionState
   * @throws CommitUnsuccessfulException
   */
  void doCommit(final TransactionState transactionState) throws CommitUnsuccessfulException {
    try {
      LOG.trace("Commiting [" + transactionState.getTransactionId() + "]");

      transactionLogger.setStatusForTransaction(
          transactionState.getTransactionId(), TransactionLogger.TransactionStatus.COMMITTED);

      for (HRegionLocation location : transactionState.getParticipatingRegions()) {
        if (transactionState.getRegionsToIngore().contains(location)) {
          continue;
        }
        TransactionalRegionInterface transactionalRegionServer =
            (TransactionalRegionInterface)
                connection.getHRegionConnection(location.getServerAddress());
        transactionalRegionServer.commit(
            location.getRegionInfo().getRegionName(), transactionState.getTransactionId());
      }
    } catch (Exception e) {
      LOG.info(
          "Commit of transaction [" + transactionState.getTransactionId() + "] was unsucsessful",
          e);
      // This happens on a NSRE that is triggered by a split
      try {
        abort(transactionState);
      } catch (Exception abortException) {
        LOG.warn("Exeption durring abort", abortException);
      }
      throw new CommitUnsuccessfulException(e);
    }
    transactionLogger.forgetTransaction(transactionState.getTransactionId());
  }
  /**
   * Abort a s transaction.
   *
   * @param transactionState
   * @throws IOException
   */
  public void abort(final TransactionState transactionState) throws IOException {
    transactionLogger.setStatusForTransaction(
        transactionState.getTransactionId(), TransactionLogger.TransactionStatus.ABORTED);

    for (HRegionLocation location : transactionState.getParticipatingRegions()) {
      if (transactionState.getRegionsToIngore().contains(location)) {
        continue;
      }
      try {
        TransactionalRegionInterface transactionalRegionServer =
            (TransactionalRegionInterface)
                connection.getHRegionConnection(location.getServerAddress());

        transactionalRegionServer.abortTransaction(
            location.getRegionInfo().getRegionName(), transactionState.getTransactionId());
      } catch (UnknownTransactionException e) {
        LOG.info(
            "Got unknown transaciton exception durring abort. Transaction: ["
                + transactionState.getTransactionId()
                + "], region: ["
                + location.getRegionInfo().getRegionNameAsString()
                + "]. Ignoring.");
      } catch (NotServingRegionException e) {
        LOG.info(
            "Got NSRE durring abort. Transaction: ["
                + transactionState.getTransactionId()
                + "], region: ["
                + location.getRegionInfo().getRegionNameAsString()
                + "]. Ignoring.");
      }
    }
    transactionLogger.forgetTransaction(transactionState.getTransactionId());
  }
 @Override
 protected long openScanner() throws IOException {
   if (transactionState.addRegion(location)) {
     ((TransactionalRegionInterface) server)
         .beginTransaction(
             transactionState.getTransactionId(), location.getRegionInfo().getRegionName());
   }
   return ((TransactionalRegionInterface) server)
       .openScanner(
           transactionState.getTransactionId(),
           this.location.getRegionInfo().getRegionName(),
           getScan());
 }
  /**
   * Prepare to commit a transaction.
   *
   * @param transactionState
   * @return commitStatusCode (see {@link TransactionalRegionInterface})
   * @throws IOException
   * @throws CommitUnsuccessfulException
   */
  public int prepareCommit(final TransactionState transactionState)
      throws CommitUnsuccessfulException, IOException {
    boolean allReadOnly = true;
    try {

      for (HRegionLocation location : transactionState.getParticipatingRegions()) {

        TransactionalRegionInterface transactionalRegionServer =
            (TransactionalRegionInterface)
                connection.getHRegionConnection(location.getServerAddress());
        int commitStatus =
            transactionalRegionServer.commitRequest(
                location.getRegionInfo().getRegionName(), transactionState.getTransactionId());
        boolean canCommit = true;
        switch (commitStatus) {
          case TransactionalRegionInterface.COMMIT_OK:
            allReadOnly = false;
            break;
          case TransactionalRegionInterface.COMMIT_OK_READ_ONLY:
            transactionState.addRegionToIgnore(location); // No need to doCommit for read-onlys
            break;
          case TransactionalRegionInterface.COMMIT_UNSUCESSFUL:
            canCommit = false;
            transactionState.addRegionToIgnore(location); // No need to re-abort.
            break;
          default:
            throw new CommitUnsuccessfulException(
                "Unexpected return code from prepareCommit: " + commitStatus);
        }

        if (LOG.isTraceEnabled()) {
          LOG.trace(
              "Region ["
                  + location.getRegionInfo().getRegionNameAsString()
                  + "] votes "
                  + (canCommit ? "to commit" : "to abort")
                  + " transaction "
                  + transactionState.getTransactionId());
        }

        if (!canCommit) {
          LOG.debug("Aborting [" + transactionState.getTransactionId() + "]");
          abort(transactionState);
          return TransactionalRegionInterface.COMMIT_UNSUCESSFUL;
        }
      }
    } catch (Exception e) {
      LOG.debug(
          "Commit of transaction [" + transactionState.getTransactionId() + "] was unsucsessful",
          e);
      // This happens on a NSRE that is triggered by a split
      try {
        abort(transactionState);
      } catch (Exception abortException) {
        LOG.warn("Exeption durring abort", abortException);
      }
      throw new CommitUnsuccessfulException(e);
    }
    return allReadOnly
        ? TransactionalRegionInterface.COMMIT_OK_READ_ONLY
        : TransactionalRegionInterface.COMMIT_OK;
  }