[jboss-svn-commits] JBL Code SVN: r26793 - in labs/jbosstm/trunk: ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi and 6 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sun May 31 13:12:43 EDT 2009
Author: mark.little at jboss.com
Date: 2009-05-31 13:12:42 -0400 (Sun, 31 May 2009)
New Revision: 26793
Added:
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi/
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi/XATerminatorExtensions.java
Modified:
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinateTransaction.java
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinationManager.java
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/exceptions/UnexpectedConditionException.java
labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java
labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java
Log:
https://jira.jboss.org/jira/browse/JBTM-560
Added: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi/XATerminatorExtensions.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi/XATerminatorExtensions.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/spi/XATerminatorExtensions.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 2004,
+ *
+ * Arjuna Technologies Ltd, Newcastle upon Tyne, Tyne and Wear, UK.
+ *
+ * $Id: XAResourceErrorHandler.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.internal.jta.resources.spi;
+
+import javax.transaction.xa.Xid;
+
+/**
+ * Extensions to the basic XATerminator spi interface. It is important that
+ * these extensions aren't relied on to drive the normal JCA protocol in case
+ * we're ever embedded in a foreign implementation.
+ *
+ * It would be nice to have these non-XA specific extensions managed by a different
+ * class than the one that deals with the standard XATerminator interface methods,
+ * c.f. JTS/OTS for 2PC and Synchronizations. However, it's a lot easier to just bundle
+ * these together in the same implementation because of the way JCA works. Of course that can
+ * be changed later if necessary and the user(s) won't notice anyway.
+ *
+ * @author marklittle
+ */
+
+public interface XATerminatorExtensions
+{
+ /*
+ * Synchronizations aren't part of XA, so that's why it would be nice to have these
+ * handled by a separate instance, as well as being architecturally symmetrical with
+ * OTS. But it's not a big deal.
+ */
+
+ public boolean beforeCompletion (Xid xid) throws javax.transaction.SystemException;
+
+ /**
+ * Status should be in JTA status values.
+ *
+ * @param xid
+ * @param status
+ * @return
+ * @throws javax.transaction.SystemException
+ */
+
+ public boolean afterCompletion (Xid xid, int status) throws javax.transaction.SystemException;
+}
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinateTransaction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinateTransaction.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinateTransaction.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -89,6 +89,22 @@
*/
public void doForget () throws IllegalStateException;
+ /**
+ * Run beforeCompletion on Synchronizations.
+ *
+ * @return outcome
+ */
+
+ public boolean doBeforeCompletion () throws SystemException;
+
+ /**
+ * Run afterCompletion on Synchronizations.
+ *
+ * @return outcome
+ */
+
+ public boolean doAfterCompletion (int status) throws SystemException;
+
public boolean activated();
public void recover();
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinationManager.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinationManager.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/SubordinationManager.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -144,7 +144,7 @@
}
/**
- * Its rather tricky to figure out if we are running in JTA or JTAX(JTS) mode. We can make a resonable guess
+ * Its rather tricky to figure out if we are running in JTA or JTAX(JTS) mode. We can make a reasonable guess
* based on the transaction manager implementation that is running, but it's going to break if some unknown
* or derived impl comes along. It's therefore safer to use setTxType explicitly in such cases.
*
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -42,401 +42,474 @@
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.arjuna.objectstore.ObjectStore;
import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions;
import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.SubordinateAtomicAction;
+import com.arjuna.ats.jta.exceptions.UnexpectedConditionException;
/**
* The XATerminator implementation.
- *
+ *
* @author mcl
- *
*/
-public class XATerminatorImple implements javax.resource.spi.XATerminator
+public class XATerminatorImple implements javax.resource.spi.XATerminator, XATerminatorExtensions
{
- /**
- * Commit the transaction identified and hence any inflow-associated work.
- *
- * @param xid
- * the transaction to commit
- * @param onePhase
- * whether or not this is a one-phase commit (should only be
- * <code>true</code> if there is a single resource associated
- * with the transaction).
- *
- * @exception XAException
- * thrown if there are any errors, including if the
- * transaction cannot commit and has to roll back.
- */
+ /**
+ * Commit the transaction identified and hence any inflow-associated work.
+ *
+ * @param xid
+ * the transaction to commit
+ * @param onePhase
+ * whether or not this is a one-phase commit (should only be
+ * <code>true</code> if there is a single resource associated
+ * with the transaction).
+ * @exception XAException
+ * thrown if there are any errors, including if the
+ * transaction cannot commit and has to roll back.
+ */
- public void commit(Xid xid, boolean onePhase) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void commit (Xid xid, boolean onePhase) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- if (tx.activated())
- {
- if (onePhase)
- tx.doOnePhaseCommit();
- else
- tx.doCommit();
+ if (tx.activated())
+ {
+ if (onePhase)
+ tx.doOnePhaseCommit();
+ else
+ tx.doCommit();
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- else
- throw new XAException(XAException.XA_RETRY);
- }
- catch(RollbackException e) {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ else
+ throw new XAException(XAException.XA_RETRY);
+ }
+ catch (RollbackException e)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XA_RBROLLBACK);
xaException.initCause(e);
throw xaException;
}
- catch (XAException ex)
- {
- // resource hasn't had a chance to recover yet
+ catch (XAException ex)
+ {
+ // resource hasn't had a chance to recover yet
- if (ex.errorCode != XAException.XA_RETRY)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
+ if (ex.errorCode != XAException.XA_RETRY)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
- throw ex;
- }
- catch (HeuristicRollbackException ex)
- {
+ throw ex;
+ }
+ catch (HeuristicRollbackException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURRB);
xaException.initCause(ex);
- throw xaException;
- }
- catch (HeuristicMixedException ex)
- {
+ throw xaException;
+ }
+ catch (HeuristicMixedException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURMIX);
xaException.initCause(ex);
- throw xaException;
- }
- catch (final HeuristicCommitException ex)
- {
+ throw xaException;
+ }
+ catch (final HeuristicCommitException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURCOM);
xaException.initCause(ex);
- throw xaException;
- }
- catch (final IllegalStateException ex)
+ throw xaException;
+ }
+ catch (final IllegalStateException ex)
{
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XAER_NOTA);
xaException.initCause(ex);
throw xaException;
}
- catch (SystemException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ catch (SystemException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XAER_RMERR);
xaException.initCause(ex);
throw xaException;
- }
- }
+ }
+ }
- /**
- * If the transaction subordinate generated a heuristic, then this operation
- * will be called later once that heuristic has been resolved.
- *
- * @param xid
- * the transaction.
- *
- * @throws XAException
- * if any error happens.
- */
+ /**
+ * If the transaction subordinate generated a heuristic, then this operation
+ * will be called later once that heuristic has been resolved.
+ *
+ * @param xid
+ * the transaction.
+ * @throws XAException
+ * if any error happens.
+ */
- public void forget(Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void forget (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- tx.doForget();
- }
- catch (Exception ex)
- {
+ tx.doForget();
+ }
+ catch (Exception ex)
+ {
XAException xaException = new XAException(XAException.XAER_RMERR);
xaException.initCause(ex);
throw xaException;
- }
- finally
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- }
+ }
+ finally
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ }
- /**
- * Prepare the imported transaction.
- *
- * @param xid
- * the transaction to prepare.
- *
- * @throws XAException
- * thrown if any error occurs, including if the transaction has
- * rolled back.
- *
- * @return either XAResource.XA_OK if the transaction prepared, or
- * XAResource.XA_RDONLY if it was a read-only transaction (and in
- * which case, a second phase message is not expected/required.)
- */
+ /**
+ * Prepare the imported transaction.
+ *
+ * @param xid
+ * the transaction to prepare.
+ * @throws XAException
+ * thrown if any error occurs, including if the transaction has
+ * rolled back.
+ * @return either XAResource.XA_OK if the transaction prepared, or
+ * XAResource.XA_RDONLY if it was a read-only transaction (and in
+ * which case, a second phase message is not expected/required.)
+ */
- public int prepare(Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public int prepare (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- switch (tx.doPrepare())
- {
- case TwoPhaseOutcome.PREPARE_READONLY:
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- return XAResource.XA_RDONLY;
- case TwoPhaseOutcome.PREPARE_NOTOK:
- // the JCA API spec limits what we can do in terms of reporting problems.
- // try to use the exception code and cause to provide info whilst
- // remaining API compliant. JBTM-427.
+ switch (tx.doPrepare())
+ {
+ case TwoPhaseOutcome.PREPARE_READONLY:
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ return XAResource.XA_RDONLY;
+ case TwoPhaseOutcome.PREPARE_NOTOK:
+ // the JCA API spec limits what we can do in terms of reporting
+ // problems.
+ // try to use the exception code and cause to provide info
+ // whilst
+ // remaining API compliant. JBTM-427.
Exception initCause = null;
int xaExceptionCode = XAException.XA_RBROLLBACK;
- try {
+ try
+ {
tx.doRollback();
- } catch(HeuristicCommitException e) {
+ }
+ catch (HeuristicCommitException e)
+ {
initCause = e;
xaExceptionCode = XAException.XAER_RMERR;
- } catch (HeuristicMixedException e) {
+ }
+ catch (HeuristicMixedException e)
+ {
initCause = e;
xaExceptionCode = XAException.XAER_RMERR;
- } catch (SystemException e) {
+ }
+ catch (SystemException e)
+ {
initCause = e;
xaExceptionCode = XAException.XAER_RMERR;
}
- catch (final HeuristicRollbackException e) {
+ catch (final HeuristicRollbackException e)
+ {
initCause = e;
xaExceptionCode = XAException.XAER_RMERR;
}
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(xaExceptionCode);
- if(initCause != null) {
+ if (initCause != null)
+ {
xaException.initCause(initCause);
}
- throw xaException;
- case TwoPhaseOutcome.PREPARE_OK:
- return XAResource.XA_OK;
- case TwoPhaseOutcome.INVALID_TRANSACTION:
- throw new XAException(XAException.XAER_NOTA);
- default:
- throw new XAException(XAException.XA_RBOTHER);
- }
- }
- catch (XAException ex)
- {
- throw ex;
- }
- }
+ throw xaException;
+ case TwoPhaseOutcome.PREPARE_OK:
+ return XAResource.XA_OK;
+ case TwoPhaseOutcome.INVALID_TRANSACTION:
+ throw new XAException(XAException.XAER_NOTA);
+ default:
+ throw new XAException(XAException.XA_RBOTHER);
+ }
+ }
+ catch (XAException ex)
+ {
+ throw ex;
+ }
+ }
- /**
- * Return a list of indoubt transactions. This may include those
- * transactions that are currently in-flight and running 2PC and do not need
- * recovery invoked on them.
- *
- * @param flag
- * either XAResource.TMSTARTRSCAN to indicate the start of a
- * recovery scan, or XAResource.TMENDRSCAN to indicate the end of
- * the recovery scan.
- *
- * @throws XAException
- * thrown if any error occurs.
- *
- * @return a list of potentially indoubt transactions or <code>null</code>.
- */
+ /**
+ * Return a list of indoubt transactions. This may include those
+ * transactions that are currently in-flight and running 2PC and do not need
+ * recovery invoked on them.
+ *
+ * @param flag
+ * either XAResource.TMSTARTRSCAN to indicate the start of a
+ * recovery scan, or XAResource.TMENDRSCAN to indicate the end of
+ * the recovery scan.
+ * @throws XAException
+ * thrown if any error occurs.
+ * @return a list of potentially indoubt transactions or <code>null</code>.
+ */
- public Xid[] recover(int flag) throws XAException
- {
- /*
- * Requires going through the objectstore for the states of imported
- * transactions. Our own crash recovery takes care of transactions
- * imported via CORBA, Web Services etc.
- */
+ public Xid[] recover (int flag) throws XAException
+ {
+ /*
+ * Requires going through the objectstore for the states of imported
+ * transactions. Our own crash recovery takes care of transactions
+ * imported via CORBA, Web Services etc.
+ */
- switch (flag)
- {
- case XAResource.TMSTARTRSCAN: // check the object store
- if (_recoveryStarted)
- throw new XAException(XAException.XAER_PROTO);
- else
- _recoveryStarted = true;
- break;
- case XAResource.TMENDRSCAN: // null op for us
- if (_recoveryStarted)
- _recoveryStarted = false;
- else
- throw new XAException(XAException.XAER_PROTO);
- return null;
- case XAResource.TMNOFLAGS:
- if (_recoveryStarted)
- break;
- default:
- throw new XAException(XAException.XAER_PROTO);
- }
+ switch (flag)
+ {
+ case XAResource.TMSTARTRSCAN: // check the object store
+ if (_recoveryStarted)
+ throw new XAException(XAException.XAER_PROTO);
+ else
+ _recoveryStarted = true;
+ break;
+ case XAResource.TMENDRSCAN: // null op for us
+ if (_recoveryStarted)
+ _recoveryStarted = false;
+ else
+ throw new XAException(XAException.XAER_PROTO);
+ return null;
+ case XAResource.TMNOFLAGS:
+ if (_recoveryStarted)
+ break;
+ default:
+ throw new XAException(XAException.XAER_PROTO);
+ }
- // if we are here, then check the object store
+ // if we are here, then check the object store
- Xid[] indoubt = null;
+ Xid[] indoubt = null;
- try
- {
- ObjectStore objStore = new ObjectStore(TxControl
- .getActionStoreType());
- InputObjectState states = new InputObjectState();
+ try
+ {
+ ObjectStore objStore = new ObjectStore(TxControl
+ .getActionStoreType());
+ InputObjectState states = new InputObjectState();
- // only look in the JCA section of the object store
+ // only look in the JCA section of the object store
- if (objStore.allObjUids(SubordinateAtomicAction.getType(), states)
- && (states.notempty()))
- {
- Stack values = new Stack();
- boolean finished = false;
+ if (objStore.allObjUids(SubordinateAtomicAction.getType(), states)
+ && (states.notempty()))
+ {
+ Stack values = new Stack();
+ boolean finished = false;
- do
- {
- Uid uid = new Uid(Uid.nullUid());
+ do
+ {
+ Uid uid = new Uid(Uid.nullUid());
- try
- {
- uid.unpack(states);
- }
- catch (IOException ex)
- {
- ex.printStackTrace();
+ try
+ {
+ uid.unpack(states);
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
- finished = true;
- }
+ finished = true;
+ }
- if (uid.notEquals(Uid.nullUid()))
- {
- Transaction tx = SubordinationManager.getTransactionImporter()
- .recoverTransaction(uid);
+ if (uid.notEquals(Uid.nullUid()))
+ {
+ Transaction tx = SubordinationManager
+ .getTransactionImporter().recoverTransaction(
+ uid);
- if (tx != null)
- values.push(tx);
- }
- else
- finished = true;
+ if (tx != null)
+ values.push(tx);
+ }
+ else
+ finished = true;
- } while (!finished);
+ }
+ while (!finished);
- if (values.size() > 0)
- {
- int index = 0;
+ if (values.size() > 0)
+ {
+ int index = 0;
- indoubt = new Xid[values.size()];
+ indoubt = new Xid[values.size()];
- while (!values.empty())
- {
- com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple tx = (com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple) values
- .pop();
+ while (!values.empty())
+ {
+ com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple tx = (com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple) values
+ .pop();
- indoubt[index] = tx.baseXid();
- index++;
- }
- }
- }
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
+ indoubt[index] = tx.baseXid();
+ index++;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
- return indoubt;
- }
+ return indoubt;
+ }
- /**
- * Rollback the imported transaction subordinate.
- *
- * @param xid
- * the transaction to roll back.
- *
- * @throws XAException
- * thrown if there are any errors.
- */
+ /**
+ * Rollback the imported transaction subordinate.
+ *
+ * @param xid
+ * the transaction to roll back.
+ * @throws XAException
+ * thrown if there are any errors.
+ */
- public void rollback(Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void rollback (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- if (tx.activated())
- {
- tx.doRollback();
+ if (tx.activated())
+ {
+ tx.doRollback();
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- else
- throw new XAException(XAException.XA_RETRY);
- }
- catch (XAException ex)
- {
- // resource hasn't had a chance to recover yet
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ else
+ throw new XAException(XAException.XA_RETRY);
+ }
+ catch (XAException ex)
+ {
+ // resource hasn't had a chance to recover yet
- if (ex.errorCode != XAException.XA_RETRY)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
+ if (ex.errorCode != XAException.XA_RETRY)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
- throw ex;
- }
- catch (final HeuristicRollbackException ex)
- {
+ throw ex;
+ }
+ catch (final HeuristicRollbackException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURRB);
xaException.initCause(ex);
throw xaException;
- }
- catch (HeuristicCommitException ex)
- {
+ }
+ catch (HeuristicCommitException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURCOM);
xaException.initCause(ex);
throw xaException;
- }
- catch (HeuristicMixedException ex)
- {
+ }
+ catch (HeuristicMixedException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURMIX);
xaException.initCause(ex);
throw xaException;
- }
- catch (final IllegalStateException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ }
+ catch (final IllegalStateException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XAER_NOTA);
xaException.initCause(ex);
throw xaException;
}
- catch (SystemException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ catch (SystemException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
- throw new XAException(XAException.XAER_RMERR);
- }
- }
+ throw new XAException(XAException.XAER_RMERR);
+ }
+ }
+
+ public boolean beforeCompletion (Xid xid) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- private boolean _recoveryStarted = false;
+ if (tx == null)
+ throw new UnexpectedConditionException();
+ return tx.doBeforeCompletion();
+ }
+ catch (final Exception ex)
+ {
+ UnexpectedConditionException e = new UnexpectedConditionException();
+
+ e.initCause(ex);
+
+ throw e;
+ }
+ }
+
+ /*
+ * Remember that status is JTS status.
+ * @see com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions#afterCompletion(javax.transaction.xa.Xid, int)
+ */
+
+ public boolean afterCompletion (Xid xid, int status) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
+
+ if (tx == null)
+ throw new UnexpectedConditionException();
+
+ return tx.doAfterCompletion(status);
+ }
+ catch (final Exception ex)
+ {
+ UnexpectedConditionException e = new UnexpectedConditionException();
+
+ e.initCause(ex);
+
+ throw e;
+ }
+ }
+
+ private boolean _recoveryStarted = false;
+
}
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -129,7 +129,7 @@
// note it's not perfect- async timeout/rollback means there is a race condition in which we
// can still call beforeCompletion on rollbacks, but that's not too bad as skipping it is really
// just an optimization anyhow. JBTM-429
- if ( !(status == ActionStatus.ABORT_ONLY || status == ActionStatus.ABORTING) && super.beforeCompletion())
+ if ( !(status == ActionStatus.ABORT_ONLY || status == ActionStatus.ABORTING) && doBeforeCompletion())
{
int outcome = super.prepare(true);
if(outcome == TwoPhaseOutcome.PREPARE_READONLY) {
@@ -213,33 +213,70 @@
}
public int doOnePhaseCommit ()
- {
- int status = super.status();
+ {
+ int status = super.status();
+
+ // In JTA spec, beforeCompletions are run on commit attempts only, not rollbacks.
+ // We attempt to mimic that here, even though we are outside the scope of the spec.
+ // note it's not perfect- async timeout/rollback means there is a race condition in which we
+ // can still call beforeCompletion on rollbacks, but that's not too bad as skipping it is really
+ // just an optimization anyhow. JBTM-429
- // In JTA spec, beforeCompletions are run on commit attempts only, not rollbacks.
- // We attempt to mimic that here, even though we are outside the scope of the spec.
- // note it's not perfect- async timeout/rollback means there is a race condition in which we
- // can still call beforeCompletion on rollbacks, but that's not too bad as skipping it is really
- // just an optimization anyhow. JBTM-429
- // behaviour relies on java's lazy evaluation of the if clause:
- if (status == ActionStatus.ABORT_ONLY || super.beforeCompletion())
- {
- status = super.End(true);
- }
- else
- {
- status = ActionStatus.ABORTED;
- }
+ if (status == ActionStatus.ABORT_ONLY || doBeforeCompletion())
+ {
+ status = super.End(true);
+ }
+ else
+ {
+ status = ActionStatus.ABORTED;
+ }
- afterCompletion(status);
- return status;
- }
+ afterCompletion(status);
+
+ return status;
+ }
public void doForget ()
{
super.forgetHeuristics();
}
+ public boolean doBeforeCompletion ()
+ {
+ // should not need synchronizing at this level
+
+ if (!_doneBefore)
+ {
+ _beforeOutcome = super.beforeCompletion();
+
+ _doneBefore = true;
+ }
+
+ return _beforeOutcome;
+ }
+
+ public boolean doAfterCompletion (int status)
+ {
+ if (!_doneAfter)
+ {
+ /*
+ * We don't need to convert from JTA status to AC status because
+ * the interpretation of the status is left up to the
+ * Synchronization instance and not the transaction.
+ *
+ * TODO this is a potential problem in the case where we
+ * allow mixtures of Synchronization types in the same transaction
+ * and they expect status values that conflict.
+ */
+
+ _afterOutcome = super.afterCompletion(status);
+
+ _doneAfter = true;
+ }
+
+ return _afterOutcome;
+ }
+
/**
* For crash recovery purposes.
*
@@ -269,4 +306,17 @@
{
return true;
}
+
+ /*
+ * We have these here because it's possible that synchronizations aren't
+ * called explicitly either side of commit/rollback due to JCA API not supporting
+ * them directly. We do though and in which case it's possible that they
+ * can be driven through two routes and we don't want to get into a mess
+ * due to that.
+ */
+
+ private boolean _doneBefore = false;
+ private boolean _beforeOutcome = false;
+ private boolean _doneAfter = false;
+ private boolean _afterOutcome = false;
}
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -309,7 +309,45 @@
throw unexpectedConditionException;
}
}
+
+ public boolean doBeforeCompletion () throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateAtomicAction subAct = (SubordinateAtomicAction) super._theTransaction;
+
+ return subAct.doBeforeCompletion();
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+ UnexpectedConditionException unexpectedConditionException = new UnexpectedConditionException(ex.toString());
+ unexpectedConditionException.initCause(ex);
+
+ throw unexpectedConditionException;
+ }
+ }
+
+ public boolean doAfterCompletion (int status) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateAtomicAction subAct = (SubordinateAtomicAction) super._theTransaction;
+
+ return subAct.doAfterCompletion(status);
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+
+ UnexpectedConditionException unexpectedConditionException = new UnexpectedConditionException(ex.toString());
+ unexpectedConditionException.initCause(ex);
+
+ throw unexpectedConditionException;
+ }
+ }
+
public String toString ()
{
if (super._theTransaction == null)
@@ -350,4 +388,5 @@
{
return true;
}
+
}
Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/exceptions/UnexpectedConditionException.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/exceptions/UnexpectedConditionException.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/jta/exceptions/UnexpectedConditionException.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -54,6 +54,5 @@
{
super(s);
}
-
}
Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -42,328 +42,399 @@
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.arjuna.objectstore.ObjectStore;
import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions;
import com.arjuna.ats.internal.jta.transaction.jts.subordinate.jca.TransactionImple;
import com.arjuna.ats.internal.jta.transaction.jts.subordinate.jca.coordinator.ServerTransaction;
import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinateTransaction;
+import com.arjuna.ats.jta.exceptions.UnexpectedConditionException;
/**
* The XATerminator implementation.
- *
+ *
* @author mcl
- *
*/
-public class XATerminatorImple implements javax.resource.spi.XATerminator
+public class XATerminatorImple implements javax.resource.spi.XATerminator, XATerminatorExtensions
{
- public void commit (Xid xid, boolean onePhase) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void commit (Xid xid, boolean onePhase) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- if (tx.baseXid() != null) // activate failed?
- {
- if (onePhase)
- tx.doOnePhaseCommit();
- else
- tx.doCommit();
+ if (tx.baseXid() != null) // activate failed?
+ {
+ if (onePhase)
+ tx.doOnePhaseCommit();
+ else
+ tx.doCommit();
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- else
- throw new XAException(XAException.XA_RETRY);
- }
- catch(RollbackException e)
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ else
+ throw new XAException(XAException.XA_RETRY);
+ }
+ catch (RollbackException e)
{
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XA_RBROLLBACK);
xaException.initCause(e);
throw xaException;
}
- catch (XAException ex)
- {
- // resource hasn't had a chance to recover yet
+ catch (XAException ex)
+ {
+ // resource hasn't had a chance to recover yet
- if (ex.errorCode != XAException.XA_RETRY)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
+ if (ex.errorCode != XAException.XA_RETRY)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
- throw ex;
- }
- catch (final HeuristicCommitException ex)
- {
+ throw ex;
+ }
+ catch (final HeuristicCommitException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURCOM);
xaException.initCause(ex);
throw xaException;
- }
- catch (HeuristicRollbackException ex)
- {
+ }
+ catch (HeuristicRollbackException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURRB);
xaException.initCause(ex);
throw xaException;
- }
- catch (HeuristicMixedException ex)
- {
+ }
+ catch (HeuristicMixedException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURMIX);
xaException.initCause(ex);
throw xaException;
- }
- catch (final IllegalStateException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ }
+ catch (final IllegalStateException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XAER_NOTA);
xaException.initCause(ex);
throw xaException;
- }
- catch (SystemException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ }
+ catch (SystemException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
XAException xaException = new XAException(XAException.XAER_RMERR);
xaException.initCause(ex);
throw xaException;
- }
- }
+ }
+ }
- public void forget (Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void forget (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- tx.doForget();
- }
- catch (Exception ex)
- {
+ tx.doForget();
+ }
+ catch (Exception ex)
+ {
XAException xaException = new XAException(XAException.XAER_RMERR);
xaException.initCause(ex);
throw xaException;
- }
- finally
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- }
+ }
+ finally
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ }
- public int prepare (Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public int prepare (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- switch (tx.doPrepare())
- {
- case TwoPhaseOutcome.PREPARE_READONLY:
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ switch (tx.doPrepare())
+ {
+ case TwoPhaseOutcome.PREPARE_READONLY:
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
- return XAResource.XA_RDONLY;
- case TwoPhaseOutcome.PREPARE_NOTOK:
- try
- {
- rollback(xid);
- }
- catch (final Throwable ex)
- {
- // if we failed to prepare then rollback should not fail!
- }
+ return XAResource.XA_RDONLY;
+ case TwoPhaseOutcome.PREPARE_NOTOK:
+ try
+ {
+ rollback(xid);
+ }
+ catch (final Throwable ex)
+ {
+ // if we failed to prepare then rollback should not fail!
+ }
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
- throw new XAException(XAException.XA_RBROLLBACK);
- case TwoPhaseOutcome.PREPARE_OK:
- return XAResource.XA_OK;
- case TwoPhaseOutcome.INVALID_TRANSACTION:
- throw new XAException(XAException.XAER_NOTA);
- default:
- throw new XAException(XAException.XA_RBOTHER);
- }
- }
- catch (XAException ex)
- {
- throw ex;
- }
- }
+ throw new XAException(XAException.XA_RBROLLBACK);
+ case TwoPhaseOutcome.PREPARE_OK:
+ return XAResource.XA_OK;
+ case TwoPhaseOutcome.INVALID_TRANSACTION:
+ throw new XAException(XAException.XAER_NOTA);
+ default:
+ throw new XAException(XAException.XA_RBOTHER);
+ }
+ }
+ catch (XAException ex)
+ {
+ throw ex;
+ }
+ }
- public Xid[] recover (int flag) throws XAException
- {
- /*
- * Requires going through the objectstore for the states of imported
- * transactions. Our own crash recovery takes care of transactions imported
- * via CORBA, Web Services etc.
- */
+ public Xid[] recover (int flag) throws XAException
+ {
+ /*
+ * Requires going through the objectstore for the states of imported
+ * transactions. Our own crash recovery takes care of transactions
+ * imported via CORBA, Web Services etc.
+ */
- /*
- * Requires going through the objectstore for the states of imported
- * transactions. Our own crash recovery takes care of transactions imported
- * via CORBA, Web Services etc.
- */
+ /*
+ * Requires going through the objectstore for the states of imported
+ * transactions. Our own crash recovery takes care of transactions
+ * imported via CORBA, Web Services etc.
+ */
- switch (flag)
- {
- case XAResource.TMSTARTRSCAN: // check the object store
- if (_recoveryStarted)
- throw new XAException(XAException.XAER_PROTO);
- else
- _recoveryStarted = true;
- break;
- case XAResource.TMENDRSCAN: // null op for us
- if (_recoveryStarted)
- _recoveryStarted = false;
- else
- throw new XAException(XAException.XAER_PROTO);
- return null;
- case XAResource.TMNOFLAGS:
- if (_recoveryStarted)
- break;
- default:
- throw new XAException(XAException.XAER_PROTO);
- }
+ switch (flag)
+ {
+ case XAResource.TMSTARTRSCAN: // check the object store
+ if (_recoveryStarted)
+ throw new XAException(XAException.XAER_PROTO);
+ else
+ _recoveryStarted = true;
+ break;
+ case XAResource.TMENDRSCAN: // null op for us
+ if (_recoveryStarted)
+ _recoveryStarted = false;
+ else
+ throw new XAException(XAException.XAER_PROTO);
+ return null;
+ case XAResource.TMNOFLAGS:
+ if (_recoveryStarted)
+ break;
+ default:
+ throw new XAException(XAException.XAER_PROTO);
+ }
- // if we are here, then check the object store
+ // if we are here, then check the object store
- Xid[] indoubt = null;
+ Xid[] indoubt = null;
- try
- {
- ObjectStore objStore = new ObjectStore(TxControl.getActionStoreType());
- InputObjectState states = new InputObjectState();
+ try
+ {
+ ObjectStore objStore = new ObjectStore(TxControl
+ .getActionStoreType());
+ InputObjectState states = new InputObjectState();
- // only look in the JCA section of the object store
+ // only look in the JCA section of the object store
- if (objStore.allObjUids(ServerTransaction.getType(), states) && (states.notempty()))
- {
- Stack values = new Stack();
- boolean finished = false;
+ if (objStore.allObjUids(ServerTransaction.getType(), states)
+ && (states.notempty()))
+ {
+ Stack values = new Stack();
+ boolean finished = false;
- do
- {
- Uid uid = new Uid(Uid.nullUid());
+ do
+ {
+ Uid uid = new Uid(Uid.nullUid());
- try
- {
- uid.unpack(states);
- }
- catch (IOException ex)
- {
- ex.printStackTrace();
+ try
+ {
+ uid.unpack(states);
+ }
+ catch (IOException ex)
+ {
+ ex.printStackTrace();
- finished = true;
- }
+ finished = true;
+ }
- if (uid.notEquals(Uid.nullUid()))
- {
- Transaction tx = SubordinationManager.getTransactionImporter().recoverTransaction(uid);
+ if (uid.notEquals(Uid.nullUid()))
+ {
+ Transaction tx = SubordinationManager
+ .getTransactionImporter().recoverTransaction(
+ uid);
- values.push(tx);
- }
- else
- finished = true;
+ values.push(tx);
+ }
+ else
+ finished = true;
- } while (!finished);
+ }
+ while (!finished);
- if (values.size() > 0)
- {
- int index = 0;
+ if (values.size() > 0)
+ {
+ int index = 0;
- indoubt = new Xid[values.size()];
+ indoubt = new Xid[values.size()];
- while (!values.empty())
- {
- TransactionImple id = (TransactionImple) values.pop();
+ while (!values.empty())
+ {
+ TransactionImple id = (TransactionImple) values.pop();
- indoubt[index] = id.baseXid();
+ indoubt[index] = id.baseXid();
- index++;
- }
- }
- }
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
+ index++;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
- return indoubt;
- }
+ return indoubt;
+ }
- public void rollback (Xid xid) throws XAException
- {
- try
- {
- SubordinateTransaction tx = SubordinationManager.getTransactionImporter().getImportedTransaction(xid);
+ public void rollback (Xid xid) throws XAException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
- if (tx == null)
- throw new XAException(XAException.XAER_INVAL);
+ if (tx == null)
+ throw new XAException(XAException.XAER_INVAL);
- if (tx.baseXid() != null)
- {
- tx.doRollback();
+ if (tx.baseXid() != null)
+ {
+ tx.doRollback();
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
- else
- throw new XAException(XAException.XA_RETRY);
- }
- catch (XAException ex)
- {
- // resource hasn't had a chance to recover yet
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
+ else
+ throw new XAException(XAException.XA_RETRY);
+ }
+ catch (XAException ex)
+ {
+ // resource hasn't had a chance to recover yet
- if (ex.errorCode != XAException.XA_RETRY)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
- }
+ if (ex.errorCode != XAException.XA_RETRY)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
+ }
- throw ex;
- }
- catch (HeuristicCommitException ex)
- {
+ throw ex;
+ }
+ catch (HeuristicCommitException ex)
+ {
XAException xaException = new XAException(XAException.XA_HEURCOM);
xaException.initCause(ex);
throw xaException;
- }
- catch (final HeuristicRollbackException ex)
- {
- XAException xaException = new XAException(XAException.XA_HEURRB);
+ }
+ catch (final HeuristicRollbackException ex)
+ {
+ XAException xaException = new XAException(XAException.XA_HEURRB);
xaException.initCause(ex);
throw xaException;
- }
- catch (HeuristicMixedException ex)
- {
- XAException xaException = new XAException(XAException.XA_HEURMIX);
+ }
+ catch (HeuristicMixedException ex)
+ {
+ XAException xaException = new XAException(XAException.XA_HEURMIX);
xaException.initCause(ex);
throw xaException;
- }
- catch (final IllegalStateException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ }
+ catch (final IllegalStateException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
- XAException xaException = new XAException(XAException.XAER_NOTA);
+ XAException xaException = new XAException(XAException.XAER_NOTA);
xaException.initCause(ex);
throw xaException;
- }
- catch (SystemException ex)
- {
- SubordinationManager.getTransactionImporter().removeImportedTransaction(xid);
+ }
+ catch (SystemException ex)
+ {
+ SubordinationManager.getTransactionImporter()
+ .removeImportedTransaction(xid);
- XAException xaException = new XAException(XAException.XAER_RMERR);
+ XAException xaException = new XAException(XAException.XAER_RMERR);
xaException.initCause(ex);
throw xaException;
- }
- }
+ }
+ }
- private boolean _recoveryStarted = false;
+ public boolean beforeCompletion (Xid xid) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
+ if (tx == null)
+ throw new UnexpectedConditionException();
+
+ return tx.doBeforeCompletion();
+ }
+ catch (final Exception ex)
+ {
+ UnexpectedConditionException e = new UnexpectedConditionException();
+
+ e.initCause(ex);
+
+ throw e;
+ }
+ }
+
+ /*
+ * Remember that status is JTS status.
+ * @see com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions#afterCompletion(javax.transaction.xa.Xid, int)
+ */
+
+ public boolean afterCompletion (Xid xid, int status) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateTransaction tx = SubordinationManager
+ .getTransactionImporter().getImportedTransaction(xid);
+
+ if (tx == null)
+ throw new UnexpectedConditionException();
+
+ return tx.doAfterCompletion(status);
+ }
+ catch (final Exception ex)
+ {
+ UnexpectedConditionException e = new UnexpectedConditionException();
+
+ e.initCause(ex);
+
+ throw e;
+ }
+ }
+
+ private boolean _recoveryStarted = false;
+
}
Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -28,6 +28,8 @@
package com.arjuna.ats.internal.jta.transaction.jts.subordinate;
+import javax.transaction.Status;
+
import org.omg.CORBA.SystemException;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicMixed;
@@ -99,9 +101,9 @@
// require registration of synchronization interposed resource as well!
if (stx != null)
- return stx.doPrepare();
- else
- return TwoPhaseOutcome.INVALID_TRANSACTION;
+ return stx.doPrepare();
+ else
+ return TwoPhaseOutcome.INVALID_TRANSACTION;
}
/**
@@ -113,18 +115,18 @@
public int doCommit () throws SystemException
{
ServerTransaction stx = getTransaction();
+ int outcome = ActionStatus.INVALID;
try
{
- if (stx != null)
- return stx.doPhase2Commit();
+ if (stx != null)
+ return stx.doPhase2Commit();
}
- catch (Exception ex)
+ catch (final Exception ex)
{
+ ex.printStackTrace();
}
-
- // TODO error
-
+
return ActionStatus.H_HAZARD;
}
@@ -137,46 +139,48 @@
public int doRollback () throws SystemException
{
ServerTransaction stx = getTransaction();
+ int outcome = ActionStatus.INVALID;
try
{
- if (stx != null)
- return stx.doPhase2Abort();
+ if (stx != null)
+ return stx.doPhase2Abort();
}
- catch (Exception ex)
+ catch (final Exception ex)
{
+ ex.printStackTrace();
}
-
- // TODO error
- return ActionStatus.H_HAZARD;
+ return ActionStatus.H_HAZARD;
}
public int doOnePhaseCommit () throws SystemException
{
// https://jira.jboss.org/jira/browse/JBTM-504
- try
- {
- ServerTransaction stx = getTransaction();
-
- if (stx != null)
- stx.doCommit(true);
- }
- catch (final INVALID_TRANSACTION ex)
- {
- return ActionStatus.INVALID;
- }
- catch (final TRANSACTION_ROLLEDBACK ex)
- {
- return ActionStatus.ABORTED;
- }
- catch (final Exception ex)
- {
- return ActionStatus.H_HAZARD;
- }
-
- return ActionStatus.COMMITTED;
+ try
+ {
+ // TODO check if we should be using TxControl.isBeforeCompletionWhenRollbackOnly in local JTA too.
+
+ ServerTransaction stx = getTransaction();
+
+ if (stx != null)
+ stx.doCommit(true);
+ }
+ catch (final INVALID_TRANSACTION ex)
+ {
+ return ActionStatus.INVALID;
+ }
+ catch (final TRANSACTION_ROLLEDBACK ex)
+ {
+ return ActionStatus.ABORTED;
+ }
+ catch (final Exception ex)
+ {
+ return ActionStatus.H_HAZARD;
+ }
+
+ return ActionStatus.COMMITTED;
}
public void doForget () throws SystemException
@@ -188,11 +192,61 @@
if (stx != null)
stx.doForget();
}
- catch (Exception ex)
+ catch (final Exception ex)
{
+ ex.printStackTrace();
}
}
+ public boolean doBeforeCompletion () throws SystemException
+ {
+ ServerTransaction stx = getTransaction();
+
+ try
+ {
+ if (stx != null)
+ {
+ stx.doBeforeCompletion();
+
+ return true;
+ }
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ return false;
+ }
+
+ public boolean doAfterCompletion (int status) throws SystemException
+ {
+ ServerTransaction stx = getTransaction();
+
+ try
+ {
+ if (stx != null)
+ {
+ /*
+ * Convert from JTA status to OTS status.
+ */
+
+ org.omg.CosTransactions.Status s = ((status == Status.STATUS_COMMITTED) ? org.omg.CosTransactions.Status.StatusCommitted :
+ org.omg.CosTransactions.Status.StatusRolledBack);
+
+ stx.doAfterCompletion(s);
+
+ return true;
+ }
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ return false;
+ }
+
/**
* By default the BasicAction class only allows the termination of a
* transaction if it's the one currently associated with the thread. We
@@ -215,4 +269,17 @@
return (ServerTransaction) sc.getImplHandle();
}
+ /*
+ * We have these here because it's possible that synchronizations aren't
+ * called explicitly either side of commit/rollback due to JCA API not supporting
+ * them directly. We do though and in which case it's possible that they
+ * can be driven through two routes and we don't want to get into a mess
+ * due to that.
+ */
+
+ private boolean _doneBefore = false;
+ private boolean _beforeOutcome = false;
+ private boolean _doneAfter = false;
+ private boolean _afterOutcome = false;
+
}
Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -375,7 +375,45 @@
throw new IllegalStateException(ex);
}
}
+
+ public boolean doBeforeCompletion () throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateAtomicTransaction subAct = (SubordinateAtomicTransaction) super._theTransaction;
+
+ return subAct.doBeforeCompletion();
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+ UnexpectedConditionException unexpectedConditionException = new UnexpectedConditionException(ex.toString());
+ unexpectedConditionException.initCause(ex);
+
+ throw unexpectedConditionException;
+ }
+ }
+
+ public boolean doAfterCompletion (int status) throws javax.transaction.SystemException
+ {
+ try
+ {
+ SubordinateAtomicTransaction subAct = (SubordinateAtomicTransaction) super._theTransaction;
+
+ return subAct.doAfterCompletion(status);
+ }
+ catch (final Exception ex)
+ {
+ ex.printStackTrace();
+
+ UnexpectedConditionException unexpectedConditionException = new UnexpectedConditionException(ex.toString());
+ unexpectedConditionException.initCause(ex);
+
+ throw unexpectedConditionException;
+ }
+ }
+
public String toString ()
{
if (super._theTransaction == null)
Modified: labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java
===================================================================
--- labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java 2009-05-31 11:32:25 UTC (rev 26792)
+++ labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java 2009-05-31 17:12:42 UTC (rev 26793)
@@ -69,8 +69,6 @@
* com.arjuna.ats.jbossatx.jta.jca.unknownwork] Work not registered!
*/
-// what is the timeout period (seconds or milliseconds)?
-
public class XATerminator extends XATerminatorImple implements
JBossXATerminator
{
More information about the jboss-svn-commits
mailing list