@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { GMUPrepareCommand spc = convert(command, GMUPrepareCommand.class); if (ctx.isOriginLocal()) { spc.setVersion(ctx.getTransactionVersion()); spc.setReadSet(ctx.getReadSet()); } else { ctx.setTransactionVersion(spc.getPrepareVersion()); } wrapEntriesForPrepare(ctx, command); performValidation(ctx, spc); Object retVal = invokeNextInterceptor(ctx, command); if (ctx.isOriginLocal() && command.getModifications().length > 0) { EntryVersion commitVersion = calculateCommitVersion( ctx.getTransactionVersion(), versionGenerator, cll.getWriteOwners(ctx.getCacheTransaction())); ctx.setTransactionVersion(commitVersion); } else { retVal = ctx.getTransactionVersion(); } if (command.isOnePhaseCommit()) { commitContextEntries.commitContextEntries(ctx); } return retVal; }
@Override public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable { GMUCommitCommand gmuCommitCommand = convert(command, GMUCommitCommand.class); if (ctx.isOriginLocal()) { gmuCommitCommand.setCommitVersion(ctx.getTransactionVersion()); } else { ctx.setTransactionVersion(gmuCommitCommand.getCommitVersion()); } transactionCommitManager.commitTransaction( ctx.getCacheTransaction(), gmuCommitCommand.getCommitVersion()); Object retVal = null; try { retVal = invokeNextInterceptor(ctx, command); } catch (Throwable throwable) { // let ignore the exception. we cannot have some nodes applying the write set and another not // another one // receives the rollback and don't applies the write set } finally { transactionCommitManager.awaitUntilCommitted( ctx.getCacheTransaction(), ctx.isOriginLocal() ? null : gmuCommitCommand); } return ctx.isOriginLocal() ? retVal : RequestHandler.DO_NOT_REPLY; }
private void updateTransactionVersion(InvocationContext context) { if (!context.isInTxScope() && !context.isOriginLocal()) { return; } if (context instanceof SingleKeyNonTxInvocationContext) { if (log.isDebugEnabled()) { log.debugf( "Received a SingleKeyNonTxInvocationContext... This should be a single read operation"); } return; } TxInvocationContext txInvocationContext = (TxInvocationContext) context; List<EntryVersion> entryVersionList = new LinkedList<EntryVersion>(); entryVersionList.add(txInvocationContext.getTransactionVersion()); if (log.isTraceEnabled()) { log.tracef( "[%s] Keys read in this command: %s", txInvocationContext.getGlobalTransaction().prettyPrint(), txInvocationContext.getKeysReadInCommand()); } for (InternalGMUCacheEntry internalGMUCacheEntry : txInvocationContext.getKeysReadInCommand().values()) { Object key = internalGMUCacheEntry.getKey(); boolean local = cll.localNodeIsOwner(key); if (log.isTraceEnabled()) { log.tracef( "[%s] Analyze entry [%s]: local?=%s", txInvocationContext.getGlobalTransaction().prettyPrint(), internalGMUCacheEntry, local); } if (txInvocationContext.hasModifications() && !internalGMUCacheEntry.isMostRecent()) { throw new CacheException("Read-Write transaction read an old value and should rollback"); } if (internalGMUCacheEntry.getMaximumTransactionVersion() != null) { entryVersionList.add(internalGMUCacheEntry.getMaximumTransactionVersion()); } txInvocationContext.getCacheTransaction().addReadKey(key); if (local) { txInvocationContext.setAlreadyReadOnThisNode(true); txInvocationContext.addReadFrom(cll.getAddress()); } } if (entryVersionList.size() > 1) { EntryVersion[] txVersionArray = new EntryVersion[entryVersionList.size()]; txInvocationContext.setTransactionVersion( versionGenerator.mergeAndMax(entryVersionList.toArray(txVersionArray))); } }
/** * validates the read set and returns the prepare version from the commit queue * * @param ctx the context * @param command the prepare command * @throws InterruptedException if interrupted */ protected void performValidation(TxInvocationContext ctx, GMUPrepareCommand command) throws InterruptedException { boolean hasToUpdateLocalKeys = hasLocalKeysToUpdate(command.getModifications()); boolean isReadOnly = command.getModifications().length == 0; if (!isReadOnly) { cll.performReadSetValidation(ctx, command); if (hasToUpdateLocalKeys) { transactionCommitManager.prepareTransaction(ctx.getCacheTransaction()); } else { transactionCommitManager.prepareReadOnlyTransaction(ctx.getCacheTransaction()); } } if (log.isDebugEnabled()) { log.debugf( "Transaction %s can commit on this node. Prepare Version is %s", command.getGlobalTransaction().prettyPrint(), ctx.getTransactionVersion()); } }