@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); }