[jboss-svn-commits] JBL Code SVN: r28982 - in labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP: ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore and 7 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Aug 19 04:57:19 EDT 2009


Author: jhalliday
Date: 2009-08-19 04:57:19 -0400 (Wed, 19 Aug 2009)
New Revision: 28982

Modified:
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java
Log:
Backport JBTM-226 and JBTM-298 to 4.2.3.SP branch.


Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -216,6 +216,9 @@
 
 	public XAResource getNewXAResource (Xid xid)
 	{
+        if(_xidScans == null)
+            resourceInitiatedRecovery();
+
 		if (_xidScans != null)
 		{
 			Enumeration keys = _xidScans.keys();

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -72,7 +72,7 @@
 
 /**
  * @author Mark Little (mark_little at hp.com)
- * @version $Id: XAResourceRecord.java 2342 2006-03-30 13:06:17Z  $
+ * @version $Id: XAResourceRecord.java 2342 2006-03-30 13:06:17Z $
  * @since JTS 1.2.4.
  */
 
@@ -81,9 +81,9 @@
 
 	public static final int XACONNECTION = 0;
 
-	private static final Uid START_XARESOURCE = Uid.minUid() ;
+	private static final Uid START_XARESOURCE = Uid.minUid();
 
-	private static final Uid END_XARESOURCE = Uid.maxUid() ;
+	private static final Uid END_XARESOURCE = Uid.maxUid();
 
 	/**
 	 * The params represent specific parameters we need to recreate the
@@ -215,8 +215,8 @@
 	 *          [com.arjuna.ats.internal.jta.resources.arjunacore.preparenulltx]
 	 *          {0} - null transaction!
 	 * @message com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed
-	 * 			[com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed]
-	 * 			{0} - prepare failed with exception {1}
+	 *          [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed]
+	 *          {0} - prepare failed with exception {1}
 	 */
 
 	public int topLevelPrepare()
@@ -276,8 +276,8 @@
 						.warn(
 								"com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed",
 								new Object[]
-								{ "XAResourceRecord.prepare", XAHelper
-										.printXAErrorCode(e1) });
+								{ "XAResourceRecord.prepare",
+										XAHelper.printXAErrorCode(e1) });
 			}
 
 			/*
@@ -373,6 +373,9 @@
 		}
 		else
 		{
+			if (_theXAResource == null)
+				_theXAResource = getNewXAResource();
+
 			if (_theXAResource != null)
 			{
 				if (_heuristic != TwoPhaseOutcome.FINISH_OK)
@@ -492,6 +495,9 @@
 		}
 		else
 		{
+			if (_theXAResource == null)
+				_theXAResource = getNewXAResource();
+
 			if (_theXAResource != null)
 			{
 				if (_heuristic != TwoPhaseOutcome.FINISH_OK)
@@ -531,7 +537,9 @@
 						{
 						case XAException.XA_HEURHAZ:
 							return TwoPhaseOutcome.HEURISTIC_HAZARD;
-						case XAException.XA_HEURCOM:  // what about forget? OTS doesn't support this code here.
+						case XAException.XA_HEURCOM: // what about forget?
+														// OTS doesn't support
+														// this code here.
 							break;
 						case XAException.XA_HEURRB:
 						case XAException.XA_RBROLLBACK:
@@ -553,8 +561,8 @@
 							return TwoPhaseOutcome.FINISH_ERROR;
 						case XAException.XAER_INVAL:
 						case XAException.XAER_RMFAIL: // resource manager
-													  // failed, did it
-													  // rollback?
+							// failed, did it
+							// rollback?
 							return TwoPhaseOutcome.HEURISTIC_HAZARD;
 						default:
 							return TwoPhaseOutcome.HEURISTIC_HAZARD;
@@ -670,7 +678,7 @@
 					case XAException.XA_HEURMIX:
 						return TwoPhaseOutcome.HEURISTIC_HAZARD;
 					case XAException.XA_HEURCOM:
-						forget() ;
+						forget();
 						break;
 					case XAException.XA_HEURRB:
 					case XAException.XA_RBROLLBACK:
@@ -682,19 +690,19 @@
 					case XAException.XA_RBTIMEOUT:
 					case XAException.XA_RBTRANSIENT:
 					case XAException.XAER_RMERR:
-						forget() ;
+						forget();
 						return TwoPhaseOutcome.FINISH_ERROR;
 					case XAException.XAER_NOTA:
 					case XAException.XAER_PROTO:
 						break;
 					case XAException.XAER_INVAL:
 					case XAException.XAER_RMFAIL: // resource manager failed,
-												  // did it rollback?
+						// did it rollback?
 						return TwoPhaseOutcome.FINISH_ERROR;
-						// 						return TwoPhaseOutcome.HEURISTIC_HAZARD;
+						// return TwoPhaseOutcome.HEURISTIC_HAZARD;
 					default:
 						return TwoPhaseOutcome.FINISH_ERROR;
-					// 						return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
+						// return TwoPhaseOutcome.HEURISTIC_ROLLBACK;
 					}
 				}
 				catch (Exception e2)
@@ -733,7 +741,7 @@
 					"XAResourceRecord.forget for " + _tranID);
 		}
 
-		forget() ;
+		forget();
 
 		removeConnection();
 
@@ -782,11 +790,11 @@
 		toDelete = null;
 	}
 
-    /**
-     * @message com.arjuna.ats.internal.jta.resources.arjunacore.savestate
-     *          [com.arjuna.ats.internal.jta.resources.arjunacore.savestate]
-     *          Could not serialize a Serializable XAResource!
-     */
+	/**
+	 * @message com.arjuna.ats.internal.jta.resources.arjunacore.savestate
+	 *          [com.arjuna.ats.internal.jta.resources.arjunacore.savestate]
+	 *          Could not serialize a Serializable XAResource!
+	 */
 
 	public boolean save_state(OutputObjectState os, int t)
 	{
@@ -815,8 +823,8 @@
 
 				try
 				{
-				    if (_theXAResource instanceof Serializable)
-					shouldSerialize = true;
+					if (_theXAResource instanceof Serializable)
+						shouldSerialize = true;
 
 					ByteArrayOutputStream s = new ByteArrayOutputStream();
 					ObjectOutputStream o = new ObjectOutputStream(s);
@@ -835,19 +843,20 @@
 				}
 				catch (NotSerializableException ex)
 				{
-				    if (!shouldSerialize)
-				    {
-					// have to rely upon XAResource.recover!
+					if (!shouldSerialize)
+					{
+						// have to rely upon XAResource.recover!
 
-					os.packBoolean(false);
-				    }
-				    else
-				    {
-					if (jtaLogger.loggerI18N.isWarnEnabled())
+						os.packBoolean(false);
+					}
+					else
 					{
-					    jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.resources.arjunacore.savestate");
+						if (jtaLogger.loggerI18N.isWarnEnabled())
+						{
+							jtaLogger.loggerI18N
+									.warn("com.arjuna.ats.internal.jta.resources.arjunacore.savestate");
+						}
 					}
-				    }
 				}
 			}
 			else
@@ -879,7 +888,8 @@
 	 *          Exception on attempting to restore XAResource
 	 * @message com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa
 	 *          [com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa]
-	 *          Could not find new XAResource to use for recovering non-serializable XAResource {0}
+	 *          Could not find new XAResource to use for recovering
+	 *          non-serializable XAResource {0}
 	 */
 
 	public boolean restore_state(InputObjectState os, int t)
@@ -926,7 +936,9 @@
 
 						if (jtaLogger.loggerI18N.isWarnEnabled())
 						{
-							jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.resources.arjunacore.restorestate",
+							jtaLogger.loggerI18N
+									.warn(
+											"com.arjuna.ats.internal.jta.resources.arjunacore.restorestate",
 											ex);
 						}
 
@@ -943,9 +955,14 @@
 
 					if (_theXAResource == null)
 					{
-						jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa",
-								new Object[]{_tranID});
+						jtaLogger.loggerI18N
+								.warn(
+										"com.arjuna.ats.internal.jta.resources.arjunacore.norecoveryxa",
+										new Object[]
+										{ _tranID });
 
+						return false;
+
 						//return false;
 					}
 				}
@@ -1142,10 +1159,15 @@
 	protected XAResource _theXAResource;
 
 	private RecoverableXAConnection _recoveryObject;
+
 	private Xid _tranID;
+
 	private boolean _prepared;
+
 	private boolean _valid;
+
 	private int _heuristic;
+
 	private TransactionImple _theTransaction;
 
 	private static boolean _rollbackOptimization = false;

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -43,127 +43,156 @@
 {
 
 	/**
-	 * Create a subordinate transaction associated with the
-	 * global transaction inflow. No timeout is associated with the
-	 * transaction.
+	 * Create a subordinate transaction associated with the global transaction
+	 * inflow. No timeout is associated with the transaction.
 	 * 
-	 * @param xid the global transaction.
+	 * @param xid
+	 *            the global transaction.
 	 * 
 	 * @return the subordinate transaction.
 	 * 
-	 * @throws XAException thrown if there are any errors.
+	 * @throws XAException
+	 *             thrown if there are any errors.
 	 */
-	
-	public static TransactionImple importTransaction (Xid xid) throws XAException
+
+	public static TransactionImple importTransaction(Xid xid)
+			throws XAException
 	{
 		return importTransaction(xid, 0);
 	}
-	
+
 	/**
-	 * Create a subordinate transaction associated with the
-	 * global transaction inflow and having a specified timeout.
+	 * Create a subordinate transaction associated with the global transaction
+	 * inflow and having a specified timeout.
 	 * 
-	 * @param xid the global transaction.
-	 * @param timeout the timeout associated with the global transaction.
+	 * @param xid
+	 *            the global transaction.
+	 * @param timeout
+	 *            the timeout associated with the global transaction.
 	 * 
 	 * @return the subordinate transaction.
 	 * 
-	 * @throws XAException thrown if there are any errors.
+	 * @throws XAException
+	 *             thrown if there are any errors.
 	 */
-	
-	public static TransactionImple importTransaction (Xid xid, int timeout) throws XAException
+
+	public static TransactionImple importTransaction(Xid xid, int timeout)
+			throws XAException
 	{
 		if (xid == null)
 			throw new IllegalArgumentException();
-		
+
 		/*
 		 * Check to see if we haven't already imported this thing.
 		 */
-		
+
 		TransactionImple imported = getImportedTransaction(xid);
-		
+
 		if (imported == null)
-		{	
+		{
 			imported = new TransactionImple(timeout, xid);
-			
+
 			_transactions.put(new XidImple(xid), imported);
 		}
-		
+
 		return imported;
 	}
-	
+
 	/**
 	 * Used to recover an imported transaction.
 	 * 
-	 * @param actId the state to recover.
+	 * @param actId
+	 *            the state to recover.
 	 * @return the recovered transaction object.
 	 * @throws XAException
 	 */
-	
-	public static TransactionImple recoverTransaction (Uid actId) throws XAException
+
+	public static TransactionImple recoverTransaction(Uid actId)
+			throws XAException
 	{
 		if (actId == null)
 			throw new IllegalArgumentException();
-		
+
 		TransactionImple recovered = new TransactionImple(actId);
 
 		/*
-		 * Is the transaction already in the list? This may be the case
-		 * because we scan the object store periodically and may get Uids to
-		 * recover for transactions that are progressing normally, i.e., do
-		 * not need recovery. In which case, we need to ignore them.
+		 * Is the transaction already in the list? This may be the case because
+		 * we scan the object store periodically and may get Uids to recover for
+		 * transactions that are progressing normally, i.e., do not need
+		 * recovery. In which case, we need to ignore them.
 		 */
-		
-		TransactionImple tx = (TransactionImple) _transactions.get(recovered.baseXid());
-		
+
+		TransactionImple tx = (TransactionImple) _transactions.get(recovered
+				.baseXid());
+
 		if (tx == null)
 		{
 			_transactions.put(recovered.baseXid(), recovered);
-		
+
 			recovered.recordTransaction();
-			
+
 			return recovered;
 		}
 		else
+		{
 			return tx;
+		}
 	}
-	
+
 	/**
-	 * Get the subordinate (imported) transaction associated with the
-	 * global transaction.
+	 * Get the subordinate (imported) transaction associated with the global
+	 * transaction.
 	 * 
-	 * @param xid the global transaction.
+	 * @param xid
+	 *            the global transaction.
 	 * 
-	 * @return the subordinate transaction or <code>null</code> if there
-	 * is none.
+	 * @return the subordinate transaction or <code>null</code> if there is
+	 *         none.
 	 * 
-	 * @throws XAException thrown if there are any errors.
+	 * @throws XAException
+	 *             thrown if there are any errors.
 	 */
-	
-	public static TransactionImple getImportedTransaction (Xid xid) throws XAException
+
+	public static TransactionImple getImportedTransaction(Xid xid)
+			throws XAException
 	{
 		if (xid == null)
 			throw new IllegalArgumentException();
-		
-		return (TransactionImple) _transactions.get(new XidImple(xid));
+
+		TransactionImple tx = (TransactionImple) _transactions
+				.get(new XidImple(xid));
+
+		if (tx == null)
+			return null;
+
+		if (!tx.activated())
+		{
+			tx.recover();
+
+			return tx;
+		}
+		else
+			return tx;
 	}
-	
+
 	/**
 	 * Remove the subordinate (imported) transaction.
 	 * 
-	 * @param xid the global transactin.
+	 * @param xid
+	 *            the global transactin.
 	 * 
-	 * @throws XAException thrown if there are any errors.
+	 * @throws XAException
+	 *             thrown if there are any errors.
 	 */
-	
-	public static void removeImportedTransaction (Xid xid) throws XAException
+
+	public static void removeImportedTransaction(Xid xid) throws XAException
 	{
 		if (xid == null)
 			throw new IllegalArgumentException();
-		
+
 		_transactions.remove(new XidImple(xid));
 	}
-	
+
 	private static HashMap _transactions = new HashMap();
-	
+
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -50,26 +50,27 @@
  * The XATerminator implementation.
  *
  * @author mcl
- *
+ * 
  */
 
 public class XATerminatorImple implements javax.resource.spi.XATerminator
 {
 
 	/**
-	 * Commit the transaction identified and hence any inflow-associated
-	 * work.
+	 * 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).
+	 * @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.
+	 * @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
+	public void commit(Xid xid, boolean onePhase) throws XAException
 	{
 		try
 		{
@@ -78,12 +79,17 @@
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
 
-			if (onePhase)
-				tx.doOnePhaseCommit();
+			if (tx.activated())
+			{
+				if (onePhase)
+					tx.doOnePhaseCommit();
+				else
+					tx.doCommit();
+
+				TxImporter.removeImportedTransaction(xid);
+			}
 			else
-				tx.doCommit();
-
-			TxImporter.removeImportedTransaction(xid);
+				throw new XAException(XAException.XA_RETRY);
 		}
         catch(RollbackException e) {
             TxImporter.removeImportedTransaction(xid);
@@ -93,8 +99,13 @@
         }
 		catch (XAException ex)
 		{
-			TxImporter.removeImportedTransaction(xid);
+			// resource hasn't had a chance to recover yet
 
+			if (ex.errorCode != XAException.XA_RETRY)
+			{
+				TxImporter.removeImportedTransaction(xid);
+			}
+
 			throw ex;
 		}
 		catch (HeuristicRollbackException ex)
@@ -114,16 +125,16 @@
 	}
 
 	/**
-	 * If the transaction subordinate generated a heuristic, then
-	 * this operation will be called later once that heuristic has been
-	 * resolved.
+	 * If the transaction subordinate generated a heuristic, then this operation
+	 * will be called later once that heuristic has been resolved.
 	 *
-	 * @param xid the transaction.
+	 * @param xid
+	 *            the transaction.
 	 *
-	 * @throws XAException if any error happens.
+	 * @throws XAException
+	 *             if any error happens.
 	 */
-
-	public void forget (Xid xid) throws XAException
+	public void forget(Xid xid) throws XAException
 	{
 		try
 		{
@@ -147,17 +158,18 @@
 	/**
 	 * Prepare the imported transaction.
 	 *
-	 * @param xid the transaction to prepare.
+	 * @param xid
+	 *            the transaction to prepare.
 	 *
-	 * @throws XAException thrown if any error occurs, including if the
-	 * transaction has rolled back.
+	 * @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.)
+	 *         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
+	public int prepare(Xid xid) throws XAException
 	{
 		try
 		{
@@ -174,7 +186,7 @@
 			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
-                // ramining API compliant.  JBTM-427.
+                // remaining API compliant.  JBTM-427.
                 Exception initCause = null;
                 int xaExceptionCode = XAException.XA_RBROLLBACK;
                 try {
@@ -195,6 +207,7 @@
                     xaException.initCause(initCause);
                 }
 				throw xaException;
+
 			case TwoPhaseOutcome.PREPARE_OK:
 				return XAResource.XA_OK;
 			default:
@@ -209,24 +222,25 @@
 
 	/**
 	 * 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.
+	 * 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.
+	 * @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.
+	 * @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
+	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.
+		 * transactions. Our own crash recovery takes care of transactions
+		 * imported via CORBA, Web Services etc.
 		 */
 
 		switch (flag)
@@ -256,11 +270,11 @@
 
 		try
 		{
-			ObjectStore objStore = new ObjectStore(TxControl.getActionStoreType());
+			ObjectStore objStore = new ObjectStore(TxControl
+					.getActionStoreType());
 			InputObjectState states = new InputObjectState();
 
 			// only look in the JCA section of the object store
-
 			if (objStore.allObjUids(SubordinateAtomicAction.getType(), states) && (states.notempty()))
 			{
 				Stack values = new Stack();
@@ -284,7 +298,6 @@
 					if (uid.notEquals(Uid.nullUid()))
 					{
 						TransactionImple tx = TxImporter.recoverTransaction(uid);
-
 						if (tx != null)
 							values.push(tx);
 					}
@@ -320,12 +333,13 @@
 	/**
 	 * Rollback the imported transaction subordinate.
 	 *
-	 * @param xid the transaction to roll back.
+	 * @param xid
+	 *            the transaction to roll back.
 	 *
-	 * @throws XAException thrown if there are any errors.
+	 * @throws XAException
+	 *             thrown if there are any errors.
 	 */
-
-	public void rollback (Xid xid) throws XAException
+	public void rollback(Xid xid) throws XAException
 	{
 		try
 		{
@@ -334,14 +348,24 @@
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
 
-			tx.doRollback();
+			if (tx.activated())
+			{
+				tx.doRollback();
 
-			TxImporter.removeImportedTransaction(xid);
+				TxImporter.removeImportedTransaction(xid);
+			}
+			else
+				throw new XAException(XAException.XA_RETRY);
 		}
 		catch (XAException ex)
 		{
-			TxImporter.removeImportedTransaction(xid);
+			// resource hasn't had a chance to recover yet
 
+			if (ex.errorCode != XAException.XA_RETRY)
+			{
+				TxImporter.removeImportedTransaction(xid);
+			}
+
 			throw ex;
 		}
 		catch (HeuristicCommitException ex)

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -115,8 +115,6 @@
 	 *         logs in the transaction object store.
 	 */
 
-	// TODO crash recovery!!!!
-
 	public String type ()
 	{
 		return "/StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction/SubordinateAtomicAction";
@@ -270,5 +268,5 @@
     public boolean activated ()
     {
     	return true;
-    }
+    }	
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -335,14 +335,13 @@
 		throw new IllegalStateException();
 	}
 
-    /**
+	/**
 	 * Because of recovery, it is possible that a transaction may not be able to
 	 * activate itself from the log initially, forcing us to retry later.
-	 *
+	 * 
 	 * @return <code>true</code> if the transaction was activated, <code>false</code>
 	 * otherwise.
 	 */
-
     public boolean activated ()
     {
     	return true;

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -53,13 +53,15 @@
 	public SubordinateAtomicAction ()
 	{
 		super();  // does start for us
+
+		_activated = true;
 	}
 
 	public SubordinateAtomicAction (Uid actId)
 	{
 		super(actId);
 		
-		activate(); // if this fails, we'll retry later.
+		_activated = activate(); // if this fails, we'll retry later.
 	}
 	
 	public SubordinateAtomicAction (int timeout, Xid xid)
@@ -67,6 +69,7 @@
 		super(timeout); // implicit start (done in base class)
 		
 		_theXid = new XidImple(xid);
+		_activated = true;
 	}
 	
 	/**
@@ -133,7 +136,12 @@
 		
 		return super.restore_state(os, t);
 	}
-	
+
+    public boolean activated ()
+    {
+    	return _activated;
+    }
+
 	private Xid _theXid;
-	
+    private boolean _activated;
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -124,5 +124,33 @@
 	{
 		return ((SubordinateAtomicAction) _theTransaction).getXid();
 	}
+
+	/**
+	 * Has the transaction been activated successfully? If not, we wait
+	 * and try again later.
+	 */
 	
+    public boolean activated ()
+    {
+    	return ((SubordinateAtomicAction) _theTransaction).activated();
+    }
+
+    /**
+     * Force this transaction to try to recover itself again.
+     */
+    
+    public void recover ()
+    {
+		Uid actId = _theTransaction.get_uid();
+
+		/*
+		 * Get a new subordinate instance. This will force activate to
+		 * be called again. Calling _theTransaction.activate should work,
+		 * but this is cleaner and guarantees the instance is in the right
+		 * state for recovery. Performance should not be an issue during
+		 * recovery either.
+		 */
+		
+		_theTransaction = new SubordinateAtomicAction(actId);
+    }
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -128,7 +128,24 @@
 		if (xid == null)
 			throw new IllegalArgumentException();
 		
-		return (TransactionImple) _transactions.get(new XidImple(xid));
+		TransactionImple tx = (TransactionImple) _transactions.get(new XidImple(xid));
+		
+		if (tx == null)
+			return null;
+
+		if (tx.baseXid() == null)
+		{
+			/*
+			 * Try recovery again. If it fails we'll throw a RETRY to the caller who
+			 * should try again later.
+			 */
+			
+			tx.getControlWrapper().getImple().getImplHandle().activate();
+
+			return tx;
+		}
+		else
+			return tx;
 	}
 
 	/**

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -69,17 +69,27 @@
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
 			
-			if (onePhase)
-				tx.doOnePhaseCommit();
+			if (tx.baseXid() != null)  // activate failed?
+			{
+				if (onePhase)
+					tx.doOnePhaseCommit();
+				else
+					tx.doCommit();
+				
+				TxImporter.removeImportedTransaction(xid);
+			}
 			else
-				tx.doCommit();
-			
-			TxImporter.removeImportedTransaction(xid);
+				throw new XAException(XAException.XA_RETRY);
 		}
 		catch (XAException ex)
 		{
-			TxImporter.removeImportedTransaction(xid);
+			// resource hasn't had a chance to recover yet
 			
+			if (ex.errorCode != XAException.XA_RETRY)
+			{
+				TxImporter.removeImportedTransaction(xid);
+			}
+
 			throw ex;
 		}
 		catch (HeuristicRollbackException ex)
@@ -265,14 +275,24 @@
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
 
-			tx.doRollback();
-			
-			TxImporter.removeImportedTransaction(xid);
+			if (tx.baseXid() != null)
+			{
+				tx.doRollback();
+				
+				TxImporter.removeImportedTransaction(xid);
+			}
+			else
+				throw new XAException(XAException.XA_RETRY);
 		}
 		catch (XAException ex)
 		{
-			TxImporter.removeImportedTransaction(xid);
+			// resource hasn't had a chance to recover yet
 			
+			if (ex.errorCode != XAException.XA_RETRY)
+			{
+				TxImporter.removeImportedTransaction(xid);
+			}
+
 			throw ex;
 		}
 		catch (HeuristicCommitException ex)

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -115,12 +115,10 @@
 		try
 		{
 			if (stx != null)
-				return stx.doPhase2Commit(false);  // TODO why not doCommit?
-//				return doOnePhaseCommit();
+				return stx.doPhase2Commit(false);
 		}
 		catch (Exception ex)
 		{
-//			ex.printStackTrace();
 		}
 		
 		// TODO error
@@ -145,7 +143,6 @@
 		}
 		catch (Exception ex)
 		{
-//			ex.printStackTrace();
 		}
 			
 		// TODO error

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -379,7 +379,7 @@
 					+ super._theTransaction.get_uid() + " >";
 		}
 	}
-
+	
 	protected void commitAndDisassociate ()
 			throws javax.transaction.RollbackException,
 			javax.transaction.HeuristicMixedException,

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -70,7 +70,10 @@
 	{
 		super(actId);
 		
-		activate();  // if this fails we'll retry recovery periodically.
+		if (!activate())  // if this fails we'll retry recovery periodically.\
+		{
+			_theXid = null; // should be the case anyway if activate fails, but ...
+		}
 	}
 	
 	public final Xid getXid ()

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java	2009-08-19 07:41:34 UTC (rev 28981)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_SP/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java	2009-08-19 08:57:19 UTC (rev 28982)
@@ -73,6 +73,8 @@
  *          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