@Override
 public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command)
     throws Throwable {
   if (ctx.isOriginLocal()
       && !isMaster()
       && (ctx.hasModifications() || command.hasModifications())) {
     throw new IllegalStateException(
         "Write transaction not allowed in Passive Replication, in backup node");
   }
   return invokeNextInterceptor(ctx, command);
 }
    @Override
    public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command)
        throws Throwable {
      boolean isTransactional = isTransactional();
      if (isTransactional) {

        // Sanity check -- if the remote tx doesn't have modifications, it never should have been
        // propagated!
        if (!command.hasModifications()) {
          throw new IllegalStateException("TxInvocationContext has no modifications!");
        }

        replayModificationsInTransaction(command, command.isOnePhaseCommit());
      } else {
        replayModifications(command);
      }
      return null;
    }
  @Override
  public CompletableFuture<Void> visitPrepareCommand(
      TxInvocationContext ctx, PrepareCommand command) throws Throwable {
    GlobalTransaction globalTransaction = command.getGlobalTransaction();
    if (trace) {
      log.tracef(
          "Visit Prepare command %s. Is it local?. Transaction is %s",
          command, ctx.isOriginLocal(), globalTransaction.globalId());
    }
    initStatsIfNecessary(ctx);
    cacheStatisticManager.onPrepareCommand(globalTransaction, ctx.isOriginLocal());
    if (command.hasModifications()) {
      cacheStatisticManager.markAsWriteTransaction(globalTransaction, ctx.isOriginLocal());
    }

    long start = timeService.time();
    return ctx.onReturn(
        (rCtx, rCommand, rv, throwable) -> {
          if (throwable != null) {
            processWriteException(rCtx, globalTransaction, throwable);
          } else {
            long end = timeService.time();
            updateTime(
                PREPARE_EXECUTION_TIME,
                NUM_PREPARE_COMMAND,
                start,
                end,
                globalTransaction,
                rCtx.isOriginLocal());
          }

          if (((PrepareCommand) rCommand).isOnePhaseCommit()) {
            boolean local = rCtx.isOriginLocal();
            boolean success = throwable == null;
            cacheStatisticManager.setTransactionOutcome(
                success, globalTransaction, rCtx.isOriginLocal());
            cacheStatisticManager.terminateTransaction(globalTransaction, local, !local);
          }
          return null;
        });
  }
 /**
  * total order condition: only commits when it is remote context and the prepare has the flag 1PC
  * set
  *
  * @param command the prepare command
  * @param ctx the invocation context
  * @return true if the modification should be committed, false otherwise
  */
 protected boolean shouldCommitDuringPrepare(PrepareCommand command, TxInvocationContext ctx) {
   boolean isTotalOrder = cacheConfiguration.transaction().transactionProtocol().isTotalOrder();
   return isTotalOrder
       ? command.isOnePhaseCommit() && (!ctx.isOriginLocal() || !command.hasModifications())
       : command.isOnePhaseCommit();
 }