private Object broadcastInvalidateForPrepare(InvocationContext rCtx, VisitableCommand rCommand, Object rv) throws Throwable { log.tracef( "Entering InvalidationInterceptor's prepare phase. Ctx flags are empty" ); // fetch the modifications before the transaction is committed (and thus removed from the txTable) TxInvocationContext txCtx = (TxInvocationContext) rCtx; if ( shouldInvokeRemoteTxCommand( txCtx ) ) { if ( txCtx.getTransaction() == null ) { throw new IllegalStateException( "We must have an associated transaction" ); } PrepareCommand prepareCmd = (PrepareCommand) rCommand; List<WriteCommand> mods = Arrays.asList( prepareCmd.getModifications() ); CompletionStage<Void> completion = broadcastInvalidateForPrepare(mods, txCtx); if (completion != null) { return asyncValue(completion); } else { return rv; } } else { log.tracef( "Nothing to invalidate - no modifications in the transaction." ); } return rv; }
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { if (!ctx.isOriginLocal()) { log.debugf("Received remote prepare for transaction %s", command.getGlobalTransaction()); numberPrepares.incrementAndGet(); } return invokeNextInterceptor(ctx, command); }
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) { if (command.isOnePhaseCommit()) { return invokeNextThenAccept(ctx, command, commitModificationsToIndex); } else { return invokeNext(ctx, command); } }
@Override public Object 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 invokeNextAndFinally(ctx, command, (rCtx, rCommand, rv, t) -> { if (t != null) { processWriteException(rCtx, globalTransaction, t); } 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 = t == null; cacheStatisticManager.setTransactionOutcome(success, globalTransaction, rCtx.isOriginLocal()); cacheStatisticManager.terminateTransaction(globalTransaction, local, !local); } }); }
/** * Commits a remote 1PC transaction that is already in MARK_COMMIT state */ public int onePhaseCommitRemoteTransaction(GlobalTransaction gtx, List<WriteCommand> modifications) { RpcManager rpcManager = cache.getRpcManager(); CommandsFactory factory = cache.getComponentRegistry().getCommandsFactory(); try { //only pessimistic tx are committed in 1PC and it doesn't use versions. PrepareCommand command = factory.buildPrepareCommand(gtx, modifications, true); CompletionStage<Void> cs = rpcManager.invokeCommandOnAll(command, validOnly(), rpcManager.getSyncRpcOptions()); factory.initializeReplicableCommand(command, false); command.invokeAsync().join(); cs.toCompletableFuture().join(); forgetTransaction(gtx, rpcManager, factory); return loggingCompleted(true) == Status.OK ? XAResource.XA_OK : XAException.XAER_RMERR; } catch (Throwable throwable) { //transaction should commit but we still can have exceptions (timeouts or similar) return XAException.XAER_RMERR; } }
PrepareCommand c11 = new PrepareCommand(cacheName, gtx, true, c5, c6, c8, c10); marshallAndAssertEquality(c11);
private boolean isUpdatingKeyWithValue(VisitableCommand command, Object key, Object value) { if (command instanceof PutKeyValueCommand) { return key.equals(((PutKeyValueCommand) command).getKey()) && value.equals(((PutKeyValueCommand) command).getValue()); } else if (command instanceof RemoveCommand) { return key.equals(((RemoveCommand) command).getKey()); } else if (command instanceof ClearCommand) { return true; } else if (command instanceof WriteOnlyManyEntriesCommand) { InternalCacheValue icv = (InternalCacheValue) ((WriteOnlyManyEntriesCommand) command).getArguments().get(key); return Objects.equals(icv.getValue(), value); } else if (command instanceof PrepareCommand) { for (WriteCommand writeCommand : ((PrepareCommand) command).getModifications()) { if (isUpdatingKeyWithValue(writeCommand, key, value)) { return true; } } } return false; }
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { return invokeNextAndFinally(ctx, command, (rCtx, rCommand, rv, t) -> { seen(command.getGlobalTransaction(), rCtx.isOriginLocal()); }); }
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { if (ctx.isOriginLocal()) { // We can't wait to commit phase to remove the entry locally (invalidations are processed in 1pc // on remote nodes, so only local case matters here). The problem is that while the entry is locked // reads still can take place and we can read outdated collection after reading updated entity // owning this collection from DB; when this happens, the version lock on entity cannot protect // us against concurrent modification of the collection. Therefore, we need to remove the entry // here (even without lock!) and let possible update happen in commit phase. for (WriteCommand wc : command.getModifications()) { for (Object key : wc.getAffectedKeys()) { dataContainer.remove(key); } } } else { for (WriteCommand wc : command.getModifications()) { Collection<?> keys = wc.getAffectedKeys(); if (log.isTraceEnabled()) { log.tracef("Invalidating keys %s with lock owner %s", keys, ctx.getLockOwner()); } for (Object key : keys ) { putFromLoadValidator.beginInvalidatingKey(ctx.getLockOwner(), key); } } } return invokeNext(ctx, command); }
recipientSizeStat = NUM_NODES_PREPARE; commandSizeStat = PREPARE_COMMAND_SIZE; globalTransaction = ((PrepareCommand) command).getGlobalTransaction(); } else if (command instanceof RollbackCommand) { durationStat = SYNC_ROLLBACK_TIME;
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand cmd) throws Throwable { try { // first pass up chain return invokeNextInterceptor(ctx, cmd); } finally { if (!ctx.isOriginLocal() || watchLocal) { logCommand(cmd); for (WriteCommand mod : cmd.getModifications()) logCommand(mod); } } }
final WriteCommand[] writeCommands = command.getModifications(); final Object[] stateBeforePrepare = new Object[writeCommands.length];