public void commit(Xid xid, boolean isOnePhase) throws XAException { // always call prepare() - even if this is just a 1PC! if (isOnePhase) prepare(xid); if (trace) log.trace("committing TransactionXaAdapter: " + globalTx); try { LocalTxInvocationContext ctx = icc.createTxInvocationContext(); ctx.setXaCache(this); if (configuration.isOnePhaseCommit()) { checkMarkedForRollback(); if (trace) log.trace("Doing an 1PC prepare call on the interceptor chain"); PrepareCommand command = commandsFactory.buildPrepareCommand(globalTx, modifications, true); try { invoker.invoke(ctx, command); } catch (Throwable e) { log.error("Error while processing 1PC PrepareCommand", e); throw new XAException(XAException.XAER_RMERR); } } else { CommitCommand commitCommand = commandsFactory.buildCommitCommand(globalTx); try { invoker.invoke(ctx, commitCommand); } catch (Throwable e) { log.error("Error while processing 1PC PrepareCommand", e); throw new XAException(XAException.XAER_RMERR); } } } finally { txTable.removeLocalTransaction(transaction); this.modifications = null; } }
public void rollback(Xid xid) throws XAException { RollbackCommand rollbackCommand = commandsFactory.buildRollbackCommand(globalTx); LocalTxInvocationContext ctx = icc.createTxInvocationContext(); ctx.setXaCache(this); try { invoker.invoke(ctx, rollbackCommand); } catch (Throwable e) { log.error("Exception while rollback", e); throw new XAException(XAException.XA_HEURHAZ); } finally { txTable.removeLocalTransaction(transaction); this.modifications = null; } }
@Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { Object retVal = invokeNextInterceptor(ctx, command); boolean sync = isSynchronous(ctx); if (shouldInvokeRemoteTxCommand(ctx)) { int newCacheViewId = -1; stateTransferLock.waitForStateTransferToEnd(ctx, command, newCacheViewId); if (command.isOnePhaseCommit()) flushL1Caches(ctx); // if we are one-phase, don't block on this future. Collection<Address> recipients = dm.getAffectedNodes(ctx.getAffectedKeys()); prepareOnAffectedNodes(ctx, command, recipients, sync); ((LocalTxInvocationContext) ctx).remoteLocksAcquired(recipients); } else if (isL1CacheEnabled && command.isOnePhaseCommit() && !ctx.isOriginLocal() && !ctx.getLockedKeys().isEmpty()) { // We fall into this block if we are a remote node, happen to be the primary data owner and // have locked keys. // it is still our responsibility to invalidate L1 caches in the cluster. flushL1Caches(ctx); } return retVal; }
@Override public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable { Object retVal = invokeNextInterceptor(ctx, command); if (ctx.isOriginLocal()) { // unlock will happen async as it is a best effort boolean sync = !command.isUnlock(); ((LocalTxInvocationContext) ctx).remoteLocksAcquired(rpcManager.getTransport().getMembers()); rpcManager.invokeRemotely(null, command, rpcManager.getDefaultRpcOptions(sync)); } return retVal; }
@Override public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable { if (ctx.isOriginLocal()) { int newCacheViewId = -1; stateTransferLock.waitForStateTransferToEnd(ctx, command, newCacheViewId); final Collection<Address> affectedNodes = dm.getAffectedNodes(command.getKeys()); ((LocalTxInvocationContext) ctx).remoteLocksAcquired(affectedNodes); rpcManager.invokeRemotely(affectedNodes, command, true, true); } return invokeNextInterceptor(ctx, command); }
public int prepare(Xid xid) throws XAException { checkMarkedForRollback(); if (configuration.isOnePhaseCommit()) { if (trace) log.trace("Received prepare for tx: " + xid + " . Skipping call as 1PC will be used."); return XA_OK; } PrepareCommand prepareCommand = commandsFactory.buildPrepareCommand( globalTx, modifications, configuration.isOnePhaseCommit()); if (trace) log.trace("Sending prepare command through the chain: " + prepareCommand); LocalTxInvocationContext ctx = icc.createTxInvocationContext(); ctx.setXaCache(this); try { invoker.invoke(ctx, prepareCommand); return XA_OK; } catch (Throwable e) { log.error("Error while processing PrepareCommand", e); throw new XAException(XAException.XAER_RMERR); } }
Map<Integer, Set<K>> contextToMap(LocalTxInvocationContext ctx, ConsistentHash hash) { Map<Integer, Set<K>> contextMap = new HashMap<>(); ctx.getLookedUpEntries() .forEach( (k, v) -> { Integer segment = hash.getSegment(k); Set<K> innerSet = contextMap.get(segment); if (innerSet == null) { innerSet = new HashSet<K>(); contextMap.put(segment, innerSet); } innerSet.add((K) k); }); return contextMap; }