use of org.infinispan.commands.tx.TransactionBoundaryCommand in project infinispan by infinispan.
the class TransactionSynchronizerInterceptor method visitCommand.
@Override
public Object visitCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
if (ctx.isOriginLocal() || !(command instanceof TransactionBoundaryCommand)) {
return invokeNext(ctx, command);
}
CompletableFuture<Void> releaseFuture = new CompletableFuture<>();
RemoteTransaction remoteTransaction = ((TxInvocationContext<RemoteTransaction>) ctx).getCacheTransaction();
Object result = asyncInvokeNext(ctx, command, remoteTransaction.enterSynchronizationAsync(releaseFuture));
return makeStage(result).andFinally(ctx, command, (rCtx, rCommand, rv, t) -> {
log.tracef("Completing tx command release future for %s", remoteTransaction);
releaseFuture.complete(null);
});
}
use of org.infinispan.commands.tx.TransactionBoundaryCommand in project infinispan by infinispan.
the class PartitionHandlingManagerImpl method completeTransaction.
private void completeTransaction(final TransactionInfo transactionInfo, CacheTopology cacheTopology) {
List<Address> commitNodes = transactionInfo.getCommitNodes(cacheTopology);
TransactionBoundaryCommand command = transactionInfo.buildCommand(commandsFactory);
command.setTopologyId(cacheTopology.getTopologyId());
CompletionStage<Map<Address, Response>> remoteInvocation = commitNodes != null ? rpcManager.invokeCommand(commitNodes, command, MapResponseCollector.ignoreLeavers(commitNodes.size()), rpcManager.getSyncRpcOptions()) : rpcManager.invokeCommandOnAll(command, MapResponseCollector.ignoreLeavers(), rpcManager.getSyncRpcOptions());
remoteInvocation.whenComplete((responseMap, throwable) -> {
final boolean trace = log.isTraceEnabled();
final GlobalTransaction globalTransaction = transactionInfo.getGlobalTransaction();
if (throwable != null) {
log.failedPartitionHandlingTxCompletion(globalTransaction, throwable);
return;
}
if (trace) {
log.tracef("Future done for transaction %s. Response are %s", globalTransaction, responseMap);
}
for (Response response : responseMap.values()) {
if (response == UnsureResponse.INSTANCE || response == CacheNotFoundResponse.INSTANCE) {
if (trace) {
log.tracef("Topology changed while completing partial transaction %s", globalTransaction);
}
return;
}
}
if (trace) {
log.tracef("Performing cleanup for transaction %s", globalTransaction);
}
lockManager.unlockAll(transactionInfo.getLockedKeys(), globalTransaction);
partialTransactions.remove(globalTransaction);
TxCompletionNotificationCommand completionCommand = commandsFactory.buildTxCompletionNotificationCommand(null, globalTransaction);
// A little bit overkill, but the state transfer can happen during a merge and some nodes can receive the
// transaction that aren't in the original affected nodes.
// no side effects.
rpcManager.sendToAll(completionCommand, DeliverOrder.NONE);
});
}
use of org.infinispan.commands.tx.TransactionBoundaryCommand in project infinispan by infinispan.
the class GlobalTxTable method onTransactionDecision.
private void onTransactionDecision(CacheXid cacheXid, TxState state, boolean commit) {
ComponentRegistry cr = gcr.getNamedComponentRegistry(cacheXid.getCacheName());
if (cr == null) {
// we don't have the cache locally
return;
}
RpcManager rpcManager = cr.getComponent(RpcManager.class);
if (rpcManager == null || state.getOriginator().equals(rpcManager.getAddress())) {
// local
PerCacheTxTable txTable = cr.getComponent(PerCacheTxTable.class);
EmbeddedTransaction tx = txTable.getLocalTx(cacheXid.getXid());
if (tx == null) {
// transaction completed
onTransactionCompleted(cacheXid);
} else {
blockingManager.runBlocking(() -> completeLocal(txTable, cacheXid, tx, commit), cacheXid);
}
} else {
if (commit) {
TransactionBoundaryCommand rpcCommand;
if (cr.getComponent(Configuration.class).transaction().lockingMode() == LockingMode.PESSIMISTIC) {
rpcCommand = cr.getCommandsFactory().buildPrepareCommand(state.getGlobalTransaction(), state.getModifications(), true);
} else {
rpcCommand = cr.getCommandsFactory().buildCommitCommand(state.getGlobalTransaction());
}
rpcCommand.setTopologyId(rpcManager.getTopologyId());
rpcManager.invokeCommandOnAll(rpcCommand, VoidResponseCollector.validOnly(), rpcManager.getSyncRpcOptions()).handle((aVoid, throwable) -> {
// TODO?
TxFunction function = new SetCompletedTransactionFunction(true);
rwMap.eval(cacheXid, function);
return null;
});
} else {
rollbackRemote(cr, cacheXid, state);
}
}
}
use of org.infinispan.commands.tx.TransactionBoundaryCommand in project infinispan by infinispan.
the class TxDistributionInterceptor method handleSecondPhaseCommand.
private Object handleSecondPhaseCommand(TxInvocationContext ctx, TransactionBoundaryCommand command) {
if (shouldInvokeRemoteTxCommand(ctx)) {
Collection<Address> recipients = getCommitNodes(ctx, command);
CompletionStage<Map<Address, Response>> remoteInvocation;
if (recipients != null) {
MapResponseCollector collector = MapResponseCollector.ignoreLeavers(recipients.size());
remoteInvocation = rpcManager.invokeCommand(recipients, command, collector, rpcManager.getSyncRpcOptions());
} else {
MapResponseCollector collector = MapResponseCollector.ignoreLeavers();
remoteInvocation = rpcManager.invokeCommandOnAll(command, collector, rpcManager.getSyncRpcOptions());
}
InvocationStage remoteResponse = asyncValue(remoteInvocation.thenAccept(responses -> checkTxCommandResponses(responses, command, ctx, recipients, null)));
return invokeNextThenApply(ctx, command, remoteResponse::thenReturn);
}
return invokeNext(ctx, command);
}
Aggregations