/** Same comment as for {@link #prepare(javax.transaction.xa.Xid)} applies for commit. */ public void commit(Xid externalXid, boolean isOnePhase) throws XAException { Xid xid = convertXid(externalXid); LocalXaTransaction localTransaction = getLocalTransactionAndValidate(xid); if (trace) log.tracef( "Committing transaction %s. One phase? %s", localTransaction.getGlobalTransaction(), isOnePhase); if (isOnePhase && !configuration.isOnePhaseCommit()) { // isOnePhase being true means that we're the only participant in the distributed transaction // and TM does the // 1PC optimization. We run a 2PC though, as running only 1PC has a high chance of leaving the // cluster in // inconsistent state. try { txCoordinator.prepare(localTransaction); txCoordinator.commit(localTransaction, false); } catch (XAException e) { if (trace) log.tracef("Couldn't commit 1PC transaction %s, trying to rollback.", localTransaction); try { rollback(xid); throw new XAException(XAException.XA_HEURRB); // this is a heuristic rollback } catch (XAException e1) { log.couldNotRollbackPrepared1PcTransaction(localTransaction, e1); // inform the TM that a resource manager error has occurred in the transaction branch // (XAER_RMERR). throw new XAException(XAException.XAER_RMERR); } } } else { txCoordinator.commit(localTransaction, configuration.isOnePhaseCommit()); } forgetSuccessfullyCompletedTransaction(recoveryManager, xid, localTransaction); }
@BeforeMethod public void setUp() { txTable = new XaTransactionTable(); TransactionFactory gtf = new TransactionFactory(); globalTransaction = gtf.newGlobalTransaction(null, false); localTx = new LocalXaTransaction(new DummyTransaction(null), globalTransaction); xid = new DummyXid(); localTx.setXid(xid); txTable.addLocalTransactionMapping(localTx); configuration = new Configuration(); TransactionCoordinator txCoordinator = new TransactionCoordinator(); txCoordinator.init(null, null, null, null, configuration); xaAdapter = new TransactionXaAdapter(localTx, txTable, configuration, null, null, txCoordinator); }
/** Same comment as for {@link #prepare(javax.transaction.xa.Xid)} applies for commit. */ public void rollback(Xid externalXid) throws XAException { Xid xid = convertXid(externalXid); LocalXaTransaction localTransaction1 = getLocalTransactionAndValidateImpl(xid, txTable); localTransaction.markForRollback( true); // ISPN-879 : make sure that locks are no longer associated to this transactions txCoordinator.rollback(localTransaction1); forgetSuccessfullyCompletedTransaction(recoveryManager, xid, localTransaction1); }
@Override public void beforeCompletion() { log.tracef("beforeCompletion called for %s", localTransaction); try { txCoordinator.prepare(localTransaction); } catch (XAException e) { throw new CacheException( "Could not prepare. ", e); // todo shall we just swallow this exception? } }
/** * This can be call for any transaction object. See Section 3.4.6 (Resource Sharing) from JTA spec * v1.1. */ public int prepare(Xid externalXid) throws XAException { Xid xid = convertXid(externalXid); LocalXaTransaction localTransaction = getLocalTransactionAndValidate(xid); if (!configuration.isOnePhaseCommit()) { return txCoordinator.prepare(localTransaction); } else { if (trace) log.tracef("Skipping prepare as we're configured to run 1PC. Xid=%s", externalXid); return XA_OK; } }
@Override public void afterCompletion(int status) { if (log.isTraceEnabled()) { log.tracef("afterCompletion(%s) called for %s.", status, localTransaction); } if (status == Status.STATUS_COMMITTED) { try { txCoordinator.commit(localTransaction, false); } catch (XAException e) { throw new CacheException("Could not commit.", e); } if (!isGMU) { releaseLocksForCompletedTransaction(localTransaction); } } else if (status == Status.STATUS_ROLLEDBACK) { try { txCoordinator.rollback(localTransaction); } catch (XAException e) { throw new CacheException("Could not commit.", e); } } else { throw new IllegalArgumentException("Unknown status: " + status); } }