@Override
 public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command)
     throws Throwable {
   if (!isTransactional()) {
     log.cannotRespondToCommit(command.getGlobalTransaction(), backupCache.getName());
   } else {
     log.tracef("Committing remote transaction %s", command.getGlobalTransaction());
     completeTransaction(command.getGlobalTransaction(), true);
   }
   return null;
 }
  private void sendCommitCommand(
      TxInvocationContext ctx, CommitCommand command, Collection<Address> preparedOn)
      throws TimeoutException, InterruptedException {
    // we only send the commit command to the nodes that
    Collection<Address> recipients = dm.getAffectedNodes(ctx.getAffectedKeys());

    // By default, use the configured commit sync settings
    boolean syncCommitPhase = configuration.isSyncCommitPhase();
    for (Address a : preparedOn) {
      if (!recipients.contains(a)) {
        // However if we have prepared on some nodes and are now committing on different nodes, make
        // sure we
        // force sync commit so we can respond to prepare resend requests.
        syncCommitPhase = true;
      }
    }

    Map<Address, Response> responses =
        rpcManager.invokeRemotely(recipients, command, syncCommitPhase, true);
    if (!responses.isEmpty()) {
      List<Address> resendTo = new LinkedList<Address>();
      for (Map.Entry<Address, Response> r : responses.entrySet()) {
        if (needToResendPrepare(r.getValue())) resendTo.add(r.getKey());
      }

      if (!resendTo.isEmpty()) {
        log.debugf(
            "Need to resend prepares for %s to %s", command.getGlobalTransaction(), resendTo);
        PrepareCommand pc = buildPrepareCommandForResend(ctx, command);
        rpcManager.invokeRemotely(resendTo, pc, true, true);
      }
    }
  }
 protected PrepareCommand buildPrepareCommandForResend(
     TxInvocationContext ctx, CommitCommand command) {
   // Make sure this is 1-Phase!!
   return cf.buildPrepareCommand(command.getGlobalTransaction(), ctx.getModifications(), true);
 }