@Override
  public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command)
      throws Throwable {
    if (ctx.getCacheTransaction() instanceof RemoteTransaction) {
      // If a commit is received for a transaction that doesn't have its 'lookedUpEntries' populated
      // we know for sure this transaction is 2PC and was received via state transfer but the
      // preceding PrepareCommand
      // was not received by local node because it was executed on the previous key owners. We need
      // to re-prepare
      // the transaction on local node to ensure its locks are acquired and lookedUpEntries is
      // properly populated.
      RemoteTransaction remoteTx = (RemoteTransaction) ctx.getCacheTransaction();
      if (remoteTx.isMissingLookedUpEntries()) {
        remoteTx.setMissingLookedUpEntries(false);

        PrepareCommand prepareCommand;
        if (useVersioning) {
          prepareCommand =
              commandFactory.buildVersionedPrepareCommand(
                  ctx.getGlobalTransaction(), ctx.getModifications(), false);
        } else {
          prepareCommand =
              commandFactory.buildPrepareCommand(
                  ctx.getGlobalTransaction(), ctx.getModifications(), false);
        }
        commandFactory.initializeReplicableCommand(prepareCommand, true);
        prepareCommand.setOrigin(ctx.getOrigin());
        log.tracef(
            "Replaying the transactions received as a result of state transfer %s", prepareCommand);
        prepareCommand.perform(null);
      }
    }

    return handleTxCommand(ctx, command);
  }
 public void applyRemoteTxLog(List<WriteCommand> commands) {
   for (WriteCommand cmd : commands) {
     try {
       // this is a remotely originating tx
       cf.initializeReplicableCommand(cmd, true);
       InvocationContext ctx = icc.createInvocationContext();
       ctx.setFlags(SKIP_REMOTE_LOOKUP, CACHE_MODE_LOCAL, SKIP_SHARED_CACHE_STORE, SKIP_LOCKING);
       interceptorChain.invoke(ctx, cmd);
     } catch (Exception e) {
       log.exceptionWhenReplaying(cmd, e);
     }
   }
 }
 @Override
 public void initializeReplicableCommand(ReplicableCommand command, boolean isRemote) {
   log.tracef("Received command %s", command);
   receivedCommands.add(command);
   if (isRemote) {
     remoteCommandsReceived.incrementAndGet();
     if (toBlock != null && command.getClass().isAssignableFrom(toBlock)) {
       blockTypeCommandsReceived.incrementAndGet();
       try {
         gate.await();
         log.tracef("gate is opened, processing the lock cleanup:  %s", command);
       } catch (InterruptedException e) {
         throw new RuntimeException(e);
       }
     }
   }
   actual.initializeReplicableCommand(command, isRemote);
 }