[jboss-svn-commits] JBL Code SVN: r16047 - in labs/jbosstm/trunk: 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 Oct 24 07:17:16 EDT 2007


Author: mark.little at jboss.com
Date: 2007-10-24 07:17:15 -0400 (Wed, 24 Oct 2007)
New Revision: 16047

Modified:
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.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/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java
   labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java
   labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.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/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java
   labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java
Log:
http://jira.jboss.com/jira/browse/JBTM-298 and http://jira.jboss.com/jira/browse/JBTM-226

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -64,1249 +64,1247 @@
 
 public class XARecoveryModule implements RecoveryModule
 {
-    // why not in Environment?
+	// why not in Environment?
 
-    public static final String XARecoveryPropertyNamePrefix = "com.arjuna.ats.jta.recovery.XAResourceRecovery";
+	public static final String XARecoveryPropertyNamePrefix = "com.arjuna.ats.jta.recovery.XAResourceRecovery";
 
-    private static final String RECOVER_ALL_NODES = "*";
+	private static final String RECOVER_ALL_NODES = "*";
 
-    public XARecoveryModule()
-    {
-	this(
-		com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryResourceManagerImple.class
-			.getName(), "Local XARecoveryModule");
+	public XARecoveryModule()
+	{
+		this(
+				com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryResourceManagerImple.class
+						.getName(), "Local XARecoveryModule");
 
-	com.arjuna.ats.internal.jta.Implementations.initialise();
-    }
+		com.arjuna.ats.internal.jta.Implementations.initialise();
+	}
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.xafirstpass {0} - first
-         *          pass
-         * @message com.arjuna.ats.internal.jta.recovery.alluids could not get
-         *          all object Uids.
-         * @message com.arjuna.ats.internal.jta.recovery.objstoreerror {0}
-         * @message com.arjuna.ats.internal.jta.recovery.periodicfirstpass {0}
-         *          exception
-         * @message com.arjuna.ats.internal.jta.recovery.info.firstpass {0} -
-         *          first pass
-         */
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.xafirstpass {0} - first
+	 *          pass
+	 * @message com.arjuna.ats.internal.jta.recovery.alluids could not get all
+	 *          object Uids.
+	 * @message com.arjuna.ats.internal.jta.recovery.objstoreerror {0}
+	 * @message com.arjuna.ats.internal.jta.recovery.periodicfirstpass {0}
+	 *          exception
+	 * @message com.arjuna.ats.internal.jta.recovery.info.firstpass {0} - first
+	 *          pass
+	 */
 
-    public void periodicWorkFirstPass ()
-    {
-	if (jtaLogger.loggerI18N.isInfoEnabled())
+	public void periodicWorkFirstPass()
 	{
-	    jtaLogger.loggerI18N.info(
-		    "com.arjuna.ats.internal.jta.recovery.info.firstpass",
-		    new Object[]
-		    { _logName });
-	}
+		if (jtaLogger.loggerI18N.isInfoEnabled())
+		{
+			jtaLogger.loggerI18N.info(
+					"com.arjuna.ats.internal.jta.recovery.info.firstpass",
+					new Object[]
+					{ _logName });
+		}
 
-	_uids = new InputObjectState();
+		_uids = new InputObjectState();
 
-	/*
-         * Scan for resources in the object store.
-         */
+		/*
+		 * Scan for resources in the object store.
+		 */
 
-	try
-	{
-	    if (!_objStore.allObjUids(_recoveryManagerClass.type(), _uids))
-	    {
-		if (jtaLogger.loggerI18N.isWarnEnabled())
+		try
 		{
-		    jtaLogger.loggerI18N
-			    .warn("com.arjuna.ats.internal.jta.recovery.alluids");
+			if (!_objStore.allObjUids(_recoveryManagerClass.type(), _uids))
+			{
+				if (jtaLogger.loggerI18N.isWarnEnabled())
+				{
+					jtaLogger.loggerI18N
+							.warn("com.arjuna.ats.internal.jta.recovery.alluids");
+				}
+			}
 		}
-	    }
+		catch (ObjectStoreException e)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
+			{
+				jtaLogger.loggerI18N
+						.warn(
+								"com.arjuna.ats.internal.jta.recovery.objstoreerror",
+								e);
+			}
+		}
+		catch (Exception e)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
+			{
+				jtaLogger.loggerI18N
+						.warn(
+								"com.arjuna.ats.internal.jta.recovery.periodicfirstpass",
+								new Object[]
+								{ _logName
+										+ ".periodicWorkFirstPass exception " },
+								e);
+			}
+		}
 	}
-	catch (ObjectStoreException e)
-	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N
-			.warn(
-				"com.arjuna.ats.internal.jta.recovery.objstoreerror",
-				e);
-	    }
-	}
-	catch (Exception e)
-	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N
-			.warn(
-				"com.arjuna.ats.internal.jta.recovery.periodicfirstpass",
-				new Object[]
-				{ _logName
-					+ ".periodicWorkFirstPass exception " },
-				e);
-	    }
-	}
-    }
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.periodicsecondpass {0}
-         *          exception
-         * @message com.arjuna.ats.internal.jta.recovery.info.secondpass {0} -
-         *          second pass
-         */
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.periodicsecondpass {0}
+	 *          exception
+	 * @message com.arjuna.ats.internal.jta.recovery.info.secondpass {0} -
+	 *          second pass
+	 */
 
-    public void periodicWorkSecondPass ()
-    {
-	if (jtaLogger.logger.isInfoEnabled())
+	public void periodicWorkSecondPass()
 	{
-	    if (jtaLogger.loggerI18N.isInfoEnabled())
-	    {
-		jtaLogger.loggerI18N.info(
-			"com.arjuna.ats.internal.jta.recovery.info.secondpass",
-			new Object[]
-			{ _logName });
-	    }
-	}
+		if (jtaLogger.logger.isInfoEnabled())
+		{
+			if (jtaLogger.loggerI18N.isInfoEnabled())
+			{
+				jtaLogger.loggerI18N.info(
+						"com.arjuna.ats.internal.jta.recovery.info.secondpass",
+						new Object[]
+						{ _logName });
+			}
+		}
 
-	try
-	{
-	    // do the recovery on anything from the scan in first pass
+		try
+		{
+			// do the recovery on anything from the scan in first pass
 
-	    transactionInitiatedRecovery();
+			transactionInitiatedRecovery();
 
-	    if (jtaLogger.logger.isDebugEnabled())
-	    {
-		jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-			VisibilityLevel.VIS_PUBLIC,
-			FacilityCode.FAC_CRASH_RECOVERY, _logName
-				+ ".transactionInitiatedRecovery completed");
-	    }
+			if (jtaLogger.logger.isDebugEnabled())
+			{
+				jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+						VisibilityLevel.VIS_PUBLIC,
+						FacilityCode.FAC_CRASH_RECOVERY, _logName
+								+ ".transactionInitiatedRecovery completed");
+			}
 
-	    /*
-                 * See the comment about this routine!!
-                 */
+			/*
+			 * See the comment about this routine!!
+			 */
 
-	    resourceInitiatedRecovery();
+			resourceInitiatedRecovery();
 
-	    if (jtaLogger.logger.isDebugEnabled())
-	    {
-		jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-			VisibilityLevel.VIS_PUBLIC,
-			FacilityCode.FAC_CRASH_RECOVERY, _logName
-				+ ".resourceInitiatedRecovery completed");
-	    }
+			if (jtaLogger.logger.isDebugEnabled())
+			{
+				jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+						VisibilityLevel.VIS_PUBLIC,
+						FacilityCode.FAC_CRASH_RECOVERY, _logName
+								+ ".resourceInitiatedRecovery completed");
+			}
+		}
+		catch (Exception e)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
+			{
+				jtaLogger.loggerI18N
+						.warn(
+								"com.arjuna.ats.internal.jta.recovery.periodicsecondpass",
+								new Object[]
+								{ _logName
+										+ ".periodicWorkSecondPass exception " },
+								e);
+			}
+		}
+
+		clearAllFailures();
 	}
-	catch (Exception e)
+
+	public String id()
 	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N
-			.warn(
-				"com.arjuna.ats.internal.jta.recovery.periodicsecondpass",
-				new Object[]
-				{ _logName
-					+ ".periodicWorkSecondPass exception " },
-				e);
-	    }
+		return "XARecoveryModule:" + _recoveryManagerClass;
 	}
 
-	clearAllFailures();
-    }
+	/**
+	 * @param Xid
+	 *            xid The transaction to commit/rollback.
+	 * 
+	 * @return the XAResource than can be used to commit/rollback the specified
+	 *         transaction.
+	 */
 
-    public String id ()
-    {
-	return "XARecoveryModule:" + _recoveryManagerClass;
-    }
+	public XAResource getNewXAResource(Xid xid)
+	{
+		if (_xidScans == null)
+			resourceInitiatedRecovery();
 
-    /**
-         * @param Xid
-         *                xid The transaction to commit/rollback.
-         * 
-         * @return the XAResource than can be used to commit/rollback the
-         *         specified transaction.
-         */
+		if (_xidScans != null)
+		{
+			Enumeration keys = _xidScans.keys();
 
-    public XAResource getNewXAResource (Xid xid)
-    {
-	if (_xidScans != null)
-	{
-	    Enumeration keys = _xidScans.keys();
+			while (keys.hasMoreElements())
+			{
+				XAResource theKey = (XAResource) keys.nextElement();
+				RecoveryXids xids = (RecoveryXids) _xidScans.get(theKey);
 
-	    while (keys.hasMoreElements())
-	    {
-		XAResource theKey = (XAResource) keys.nextElement();
-		RecoveryXids xids = (RecoveryXids) _xidScans.get(theKey);
+				if (xids.contains(xid))
+					return theKey;
+			}
+		}
 
-		if (xids.contains(xid))
-		    return theKey;
-	    }
+		return null;
 	}
 
-	return null;
-    }
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.constfail {0}
+	 * @message com.arjuna.ats.internal.jta.recovery.classloadfail {0} - could
+	 *          not get class name for {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.general Caught exception:
+	 *          {0} for {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.info.loading {0} loading
+	 *          {1}
+	 */
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.constfail {0}
-         * @message com.arjuna.ats.internal.jta.recovery.classloadfail {0} -
-         *          could not get class name for {1}
-         * @message com.arjuna.ats.internal.jta.recovery.general Caught
-         *          exception: {0} for {1}
-         * @message com.arjuna.ats.internal.jta.recovery.info.loading {0}
-         *          loading {1}
-         */
+	protected XARecoveryModule(String recoveryClass, String logName)
+	{
+		_xaRecoverers = new Vector();
+		_logName = logName;
 
-    protected XARecoveryModule(String recoveryClass, String logName)
-    {
-	_xaRecoverers = new Vector();
-	_logName = logName;
+		try
+		{
+			Class c = Thread.currentThread().getContextClassLoader().loadClass(
+					recoveryClass);
 
-	try
-	{
-	    Class c = Thread.currentThread().getContextClassLoader().loadClass(
-		    recoveryClass);
+			_recoveryManagerClass = (XARecoveryResourceManager) c.newInstance();
+		}
+		catch (Exception ex)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
+			{
+				jtaLogger.loggerI18N.warn(
+						"com.arjuna.ats.internal.jta.recovery.constfail", ex);
+			}
 
-	    _recoveryManagerClass = (XARecoveryResourceManager) c.newInstance();
-	}
-	catch (Exception ex)
-	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N.warn(
-			"com.arjuna.ats.internal.jta.recovery.constfail", ex);
-	    }
+			_recoveryManagerClass = null;
+		}
 
-	    _recoveryManagerClass = null;
-	}
+		Properties props = jtaPropertyManager.propertyManager.getProperties();
 
-	Properties props = jtaPropertyManager.propertyManager.getProperties();
+		if (props != null)
+		{
+			Enumeration names = props.propertyNames();
 
-	if (props != null)
-	{
-	    Enumeration names = props.propertyNames();
+			while (names.hasMoreElements())
+			{
+				String propName = (String) names.nextElement();
 
-	    while (names.hasMoreElements())
-	    {
-		String propName = (String) names.nextElement();
+				if (propName
+						.startsWith(XARecoveryModule.XARecoveryPropertyNamePrefix))
+				{
+					/*
+					 * Given the recovery string, create the class it refers to
+					 * and store it.
+					 */
 
-		if (propName
-			.startsWith(XARecoveryModule.XARecoveryPropertyNamePrefix))
-		{
-		    /*
-                         * Given the recovery string, create the class it refers
-                         * to and store it.
-                         */
+					String theClassAndParameter = jtaPropertyManager.propertyManager
+							.getProperty(propName);
 
-		    String theClassAndParameter = jtaPropertyManager.propertyManager
-			    .getProperty(propName);
+					// see if there is a string parameter
 
-		    // see if there is a string parameter
+					int breakPosition = theClassAndParameter
+							.indexOf(BREAKCHARACTER);
 
-		    int breakPosition = theClassAndParameter
-			    .indexOf(BREAKCHARACTER);
+					String theClass = null;
+					String theParameter = null;
 
-		    String theClass = null;
-		    String theParameter = null;
+					if (breakPosition != -1)
+					{
+						theClass = theClassAndParameter.substring(0,
+								breakPosition);
+						theParameter = theClassAndParameter
+								.substring(breakPosition + 1);
+					}
+					else
+					{
+						theClass = theClassAndParameter;
+					}
 
-		    if (breakPosition != -1)
-		    {
-			theClass = theClassAndParameter.substring(0,
-				breakPosition);
-			theParameter = theClassAndParameter
-				.substring(breakPosition + 1);
-		    }
-		    else
-		    {
-			theClass = theClassAndParameter;
-		    }
+					if (jtaLogger.loggerI18N.isInfoEnabled())
+					{
+						if (jtaLogger.loggerI18N.isInfoEnabled())
+						{
+							jtaLogger.loggerI18N
+									.info(
+											"com.arjuna.ats.internal.jta.recovery.info.loading",
+											new Object[]
+											{
+													_logName,
+													(theClass + ((theParameter != null) ? theParameter
+															: "")) });
+						}
+					}
 
-		    if (jtaLogger.loggerI18N.isInfoEnabled())
-		    {
-			if (jtaLogger.loggerI18N.isInfoEnabled())
-			{
-			    jtaLogger.loggerI18N
-				    .info(
-					    "com.arjuna.ats.internal.jta.recovery.info.loading",
-					    new Object[]
-					    {
-						    _logName,
-						    (theClass + ((theParameter != null) ? theParameter
-							    : "")) });
-			}
-		    }
+					if (theClass == null)
+					{
+						if (jtaLogger.loggerI18N.isWarnEnabled())
+						{
+							jtaLogger.loggerI18N
+									.warn(
+											"com.arjuna.ats.internal.jta.recovery.classloadfail",
+											new Object[]
+											{ _logName, propName });
+						}
+					}
+					else
+					{
+						try
+						{
+							Class c = Thread.currentThread()
+									.getContextClassLoader()
+									.loadClass(theClass);
 
-		    if (theClass == null)
-		    {
-			if (jtaLogger.loggerI18N.isWarnEnabled())
-			{
-			    jtaLogger.loggerI18N
-				    .warn(
-					    "com.arjuna.ats.internal.jta.recovery.classloadfail",
-					    new Object[]
-					    { _logName, propName });
-			}
-		    }
-		    else
-		    {
-			try
-			{
-			    Class c = Thread.currentThread()
-				    .getContextClassLoader()
-				    .loadClass(theClass);
+							XAResourceRecovery ri = (XAResourceRecovery) c
+									.newInstance();
 
-			    XAResourceRecovery ri = (XAResourceRecovery) c
-				    .newInstance();
+							if (theParameter != null)
+								ri.initialise(theParameter);
 
-			    if (theParameter != null)
-				ri.initialise(theParameter);
+							_xaRecoverers.addElement(ri);
+						}
+						catch (Exception e)
+						{
+							if (jtaLogger.loggerI18N.isWarnEnabled())
+							{
+								jtaLogger.loggerI18N
+										.warn(
+												"com.arjuna.ats.internal.jta.recovery.general",
+												new Object[]
+												{ e, theClass });
+							}
+						}
+					}
+				}
+				else
+				{
+					if (propName.startsWith(Environment.XA_RECOVERY_NODE))
+					{
+						/*
+						 * Find the node(s) we can recover on behalf of.
+						 */
 
-			    _xaRecoverers.addElement(ri);
+						String name = jtaPropertyManager.propertyManager
+								.getProperty(propName);
+
+						if (_xaRecoveryNodes == null)
+							_xaRecoveryNodes = new Vector();
+
+						_xaRecoveryNodes.addElement(name);
+					}
+				}
 			}
-			catch (Exception e)
+		}
+
+		if ((_xaRecoveryNodes == null) || (_xaRecoveryNodes.size() == 0))
+		{
+			if (jtaLogger.loggerI18N.isInfoEnabled())
 			{
-			    if (jtaLogger.loggerI18N.isWarnEnabled())
-			    {
 				jtaLogger.loggerI18N
-					.warn(
-						"com.arjuna.ats.internal.jta.recovery.general",
-						new Object[]
-						{ e, theClass });
-			    }
+						.info("com.arjuna.ats.internal.jta.recovery.noxanodes");
 			}
-		    }
 		}
-		else
-		{
-		    if (propName.startsWith(Environment.XA_RECOVERY_NODE))
-		    {
-			/*
-                         * Find the node(s) we can recover on behalf of.
-                         */
+	}
 
-			String name = jtaPropertyManager.propertyManager
-				.getProperty(propName);
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.recoveryfailed JTA failed
+	 *          to recovery {0}; got status {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.recoverydelayed JTA
+	 *          recovery delayed for {0}; got status {1} so waiting for
+	 *          coordinator driven recovery
+	 * @message com.arjuna.ats.internal.jta.recovery.recoveryerror Recovery
+	 *          threw:
+	 * @message com.arjuna.ats.internal.jta.recovery.cannotadd Cannot add
+	 *          resource to table: no XID value available.
+	 * @message com.arjuna.ats.internal.jta.recovery.unexpectedrecoveryerror
+	 *          Unexpceted recovery error:
+	 * @message com.arjuna.ats.internal.jta.recovery.noxanodes No XA recovery
+	 *          nodes specified. Will only recover saved states.
+	 */
 
-			if (_xaRecoveryNodes == null)
-			    _xaRecoveryNodes = new Vector();
+	private final boolean transactionInitiatedRecovery()
+	{
+		Uid theUid = new Uid();
 
-			_xaRecoveryNodes.addElement(name);
-		    }
-		}
-	    }
-	}
+		while (theUid.notEquals(Uid.nullUid()))
+		{
+			try
+			{
+				theUid.unpack(_uids);
 
-	if ((_xaRecoveryNodes == null) || (_xaRecoveryNodes.size() == 0))
-	{
-	    if (jtaLogger.loggerI18N.isInfoEnabled())
-	    {
-		jtaLogger.loggerI18N
-			.info("com.arjuna.ats.internal.jta.recovery.noxanodes");
-	    }
-	}
-    }
+				if (theUid.notEquals(Uid.nullUid()))
+				{
+					/*
+					 * Ignore it if it isn't in the store any more. Transaction
+					 * probably recovered it.
+					 */
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.recoveryfailed JTA
-         *          failed to recovery {0}; got status {1}
-         * @message com.arjuna.ats.internal.jta.recovery.recoverydelayed JTA
-         *          recovery delayed for {0}; got status {1} so waiting for
-         *          coordinator driven recovery
-         * @message com.arjuna.ats.internal.jta.recovery.recoveryerror Recovery
-         *          threw:
-         * @message com.arjuna.ats.internal.jta.recovery.cannotadd Cannot add
-         *          resource to table: no XID value available.
-         * @message com.arjuna.ats.internal.jta.recovery.unexpectedrecoveryerror
-         *          Unexpceted recovery error:
-         * @message com.arjuna.ats.internal.jta.recovery.noxanodes No XA
-         *          recovery nodes specified. Will only recover saved states.
-         */
+					if (_objStore.currentState(theUid, _recoveryManagerClass
+							.type()) != ObjectStore.OS_UNKNOWN)
+					{
+						boolean problem = false;
+						XARecoveryResource record = null;
 
-    private final boolean transactionInitiatedRecovery ()
-    {
-	Uid theUid = new Uid();
+						try
+						{
+							record = _recoveryManagerClass.getResource(theUid);
 
-	while (theUid.notEquals(Uid.nullUid()))
-	{
-	    try
-	    {
-		theUid.unpack(_uids);
+							problem = true;
 
-		if (theUid.notEquals(Uid.nullUid()))
-		{
-		    /*
-                         * Ignore it if it isn't in the store any more.
-                         * Transaction probably recovered it.
-                         */
+							switch (record.recoverable())
+							{
+							case XARecoveryResource.RECOVERY_REQUIRED:
+							{
+								if (jtaLogger.logger.isDebugEnabled())
+								{
+									jtaLogger.logger.debug(
+											DebugLevel.FUNCTIONS,
+											VisibilityLevel.VIS_PUBLIC,
+											FacilityCode.FAC_CRASH_RECOVERY,
+											"XARecovery attempting recovery of "
+													+ theUid);
+								}
 
-		    if (_objStore.currentState(theUid, _recoveryManagerClass
-			    .type()) != ObjectStore.OS_UNKNOWN)
-		    {
-			boolean problem = false;
-			XARecoveryResource record = null;
+								int recoveryStatus = record.recover();
 
-			try
-			{
-			    record = _recoveryManagerClass.getResource(theUid);
+								if (recoveryStatus != XARecoveryResource.RECOVERED_OK)
+								{
+									if (recoveryStatus == XARecoveryResource.WAITING_FOR_RECOVERY)
+									{
+										problem = false;
 
-			    problem = true;
+										if (jtaLogger.loggerI18N
+												.isInfoEnabled())
+										{
+											jtaLogger.loggerI18N
+													.info(
+															"com.arjuna.ats.internal.jta.recovery.recoverydelayed",
+															new Object[]
+															{
+																	theUid,
+																	new Integer(
+																			recoveryStatus) });
+										}
+									}
+									else
+									{
+										if (jtaLogger.loggerI18N
+												.isWarnEnabled())
+										{
+											jtaLogger.loggerI18N
+													.warn(
+															"com.arjuna.ats.internal.jta.recovery.recoveryfailed",
+															new Object[]
+															{
+																	theUid,
+																	new Integer(
+																			recoveryStatus) });
+										}
+									}
+								}
+								else
+									problem = false; // resource initiated
+								// recovery not possible
+								// (no distribution).
+							}
+								break;
+							case XARecoveryResource.INFLIGHT_TRANSACTION:
+							{
+								/*
+								 * Transaction was inflight and between us
+								 * noticing it and trying to access the state,
+								 * it finished and removed the state.
+								 */
 
-			    switch (record.recoverable())
-			    {
-			    case XARecoveryResource.RECOVERY_REQUIRED:
-			    {
-				if (jtaLogger.logger.isDebugEnabled())
-				{
-				    jtaLogger.logger.debug(
-					    DebugLevel.FUNCTIONS,
-					    VisibilityLevel.VIS_PUBLIC,
-					    FacilityCode.FAC_CRASH_RECOVERY,
-					    "XARecovery attempting recovery of "
-						    + theUid);
-				}
+								problem = false;
+							}
+								break;
+							case XARecoveryResource.INCOMPLETE_STATE:
+							default:
+							{
+								if (jtaLogger.logger.isDebugEnabled())
+								{
+									jtaLogger.logger.debug(
+											DebugLevel.FUNCTIONS,
+											VisibilityLevel.VIS_PUBLIC,
+											FacilityCode.FAC_CRASH_RECOVERY,
+											"XARecovery " + theUid
+													+ " is non-recoverable");
+								}
+							}
+								break;
+							}
+						}
+						catch (NullPointerException ex)
+						{
+							problem = true;
+						}
+						catch (Throwable e)
+						{
+							problem = true;
 
-				int recoveryStatus = record.recover();
+							if (jtaLogger.loggerI18N.isWarnEnabled())
+							{
+								jtaLogger.loggerI18N
+										.warn(
+												"com.arjuna.ats.internal.jta.recovery.recoveryerror",
+												e);
+							}
+						}
 
-				if (recoveryStatus != XARecoveryResource.RECOVERED_OK)
-				{
-				    if (recoveryStatus == XARecoveryResource.WAITING_FOR_RECOVERY)
-				    {
-					problem = false;
+						if (problem && (record != null))
+						{
+							/*
+							 * Some error occurred which prevented the state of
+							 * the resource from being read from the log. Hence
+							 * we don't have a valid key to use to insert it
+							 * into the list of records to be recovered. Print a
+							 * warning and move on. Force recovery via the
+							 * administration tool. Should be a rare occurrence.
+							 */
 
-					if (jtaLogger.loggerI18N
-						.isInfoEnabled())
-					{
-					    jtaLogger.loggerI18N
-						    .info(
-							    "com.arjuna.ats.internal.jta.recovery.recoverydelayed",
-							    new Object[]
-							    {
-								    theUid,
-								    new Integer(
-									    recoveryStatus) });
+							if (record.getXid() == null)
+							{
+								if (jtaLogger.loggerI18N.isWarnEnabled())
+								{
+									jtaLogger.loggerI18N
+											.warn("com.arjuna.ats.internal.jta.recovery.cannotadd");
+								}
+							}
+							else
+							{
+								addFailure(record.getXid(), record.get_uid());
+							}
+						}
 					}
-				    }
-				    else
-				    {
-					if (jtaLogger.loggerI18N
-						.isWarnEnabled())
-					{
-					    jtaLogger.loggerI18N
-						    .warn(
-							    "com.arjuna.ats.internal.jta.recovery.recoveryfailed",
-							    new Object[]
-							    {
-								    theUid,
-								    new Integer(
-									    recoveryStatus) });
-					}
-				    }
 				}
-				else
-				    problem = false; // resource initiated
-				// recovery not possible
-				// (no distribution).
-			    }
-				break;
-			    case XARecoveryResource.INFLIGHT_TRANSACTION:
-			    {
-				/*
-                                 * Transaction was inflight and between us
-                                 * noticing it and trying to access the state,
-                                 * it finished and removed the state.
-                                 */
-
-				problem = false;
-			    }
-				break;
-			    case XARecoveryResource.INCOMPLETE_STATE:
-			    default:
-			    {
-				if (jtaLogger.logger.isDebugEnabled())
-				{
-				    jtaLogger.logger.debug(
-					    DebugLevel.FUNCTIONS,
-					    VisibilityLevel.VIS_PUBLIC,
-					    FacilityCode.FAC_CRASH_RECOVERY,
-					    "XARecovery " + theUid
-						    + " is non-recoverable");
-				}
-			    }
-				break;
-			    }
 			}
-			catch (NullPointerException ex)
+			catch (IOException e)
 			{
-			    problem = true;
+				theUid = Uid.nullUid();
 			}
 			catch (Throwable e)
 			{
-			    problem = true;
-
-			    if (jtaLogger.loggerI18N.isWarnEnabled())
-			    {
-				jtaLogger.loggerI18N
-					.warn(
-						"com.arjuna.ats.internal.jta.recovery.recoveryerror",
-						e);
-			    }
+				if (jtaLogger.loggerI18N.isWarnEnabled())
+				{
+					jtaLogger.loggerI18N
+							.warn(
+									"com.arjuna.ats.internal.jta.recovery.unexpectedrecoveryerror",
+									e);
+				}
 			}
+		}
 
-			if (problem && (record != null))
+		return true;
+	}
+
+	/**
+	 * Now check for any outstanding transactions. If we didn't fail to recover
+	 * them, then roll them back - if they'd got through prepare we would have
+	 * an entry within the object store.
+	 * 
+	 * Rely upon _xaRecoverers being set up properly (via properties).
+	 * 
+	 * We cannot just remember the XAResourceRecords we used (if any) to cache
+	 * the JDBC connection information and use that since we may never have had
+	 * any such records!
+	 * 
+	 * IMPORTANT: resourceInitiatedRecovery may rollback transactions which are
+	 * inflight: just because we have no entry for a transaction in the object
+	 * store does not mean it does not exist - it may be *about* to write its
+	 * intentions list. To try to reduce this probability we remember potential
+	 * rollback-ees at this scan, and wait for the next scan before actually
+	 * rolling them back.
+	 * 
+	 * Note we cannot use the method that works with Transactions and
+	 * TransactionalObjects, of checking with original process that created the
+	 * transaction, because we don't know which process it was.
+	 * 
+	 * @message com.arjuna.ats.internal.jta.recovery.getxaresource Caught:
+	 */
+
+	private final boolean resourceInitiatedRecovery()
+	{
+		/*
+		 * Now any additional connections we may need to create. Relies upon
+		 * information provided by the application.
+		 */
+
+		if (_xaRecoverers.size() > 0)
+		{
+			for (int i = 0; i < _xaRecoverers.size(); i++)
 			{
-			    /*
-                                 * Some error occurred which prevented the state
-                                 * of the resource from being read from the log.
-                                 * Hence we don't have a valid key to use to
-                                 * insert it into the list of records to be
-                                 * recovered. Print a warning and move on. Force
-                                 * recovery via the administration tool. Should
-                                 * be a rare occurrence.
-                                 */
+				XAResource resource = null;
 
-			    if (record.getXid() == null)
-			    {
-				if (jtaLogger.loggerI18N.isWarnEnabled())
+				try
 				{
-				    jtaLogger.loggerI18N
-					    .warn("com.arjuna.ats.internal.jta.recovery.cannotadd");
+					XAResourceRecovery ri = (XAResourceRecovery) _xaRecoverers
+							.elementAt(i);
+
+					while (ri.hasMoreResources())
+					{
+						try
+						{
+							resource = ri.getXAResource();
+
+							xaRecovery(resource);
+						}
+						catch (Exception exp)
+						{
+							if (jtaLogger.loggerI18N.isWarnEnabled())
+							{
+								jtaLogger.loggerI18N
+										.warn(
+												"com.arjuna.ats.internal.jta.recovery.getxaresource",
+												exp);
+							}
+						}
+					}
 				}
-			    }
-			    else
-			    {
-				addFailure(record.getXid(), record.get_uid());
-			    }
+				catch (Exception ex)
+				{
+					if (jtaLogger.loggerI18N.isWarnEnabled())
+					{
+						jtaLogger.loggerI18N
+								.warn(
+										"com.arjuna.ats.internal.jta.recovery.getxaresource",
+										ex);
+					}
+				}
 			}
-		    }
 		}
-	    }
-	    catch (IOException e)
-	    {
-		theUid = Uid.nullUid();
-	    }
-	    catch (Throwable e)
-	    {
-		if (jtaLogger.loggerI18N.isWarnEnabled())
-		{
-		    jtaLogger.loggerI18N
-			    .warn(
-				    "com.arjuna.ats.internal.jta.recovery.unexpectedrecoveryerror",
-				    e);
-		}
-	    }
+
+		return true;
 	}
 
-	return true;
-    }
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.xarecovery1 {0} got XA
+	 *          exception {1}, {2}
+	 * @message com.arjuna.ats.internal.jta.recovery.xarecovery2 {0} got
+	 *          exception {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.failedtorecover {0} -
+	 *          failed to recover XAResource.
+	 * @message com.arjuna.ats.internal.jta.recovery.forgetfailed {0} - forget
+	 *          threw: {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.generalrecoveryerror {0} -
+	 *          caught {1}
+	 * @message com.arjuna.ats.internal.jta.recovery.info.rollingback Rolling
+	 *          back {0}
+	 * @message com.arjuna.ats.internal.jta.recovery.info.notrollback Told not
+	 *          to rollback {0}
+	 */
 
-    /**
-         * Now check for any outstanding transactions. If we didn't fail to
-         * recover them, then roll them back - if they'd got through prepare we
-         * would have an entry within the object store.
-         * 
-         * Rely upon _xaRecoverers being set up properly (via properties).
-         * 
-         * We cannot just remember the XAResourceRecords we used (if any) to
-         * cache the JDBC connection information and use that since we may never
-         * have had any such records!
-         * 
-         * IMPORTANT: resourceInitiatedRecovery may rollback transactions which
-         * are inflight: just because we have no entry for a transaction in the
-         * object store does not mean it does not exist - it may be *about* to
-         * write its intentions list. To try to reduce this probability we
-         * remember potential rollback-ees at this scan, and wait for the next
-         * scan before actually rolling them back.
-         * 
-         * Note we cannot use the method that works with Transactions and
-         * TransactionalObjects, of checking with original process that created
-         * the transaction, because we don't know which process it was.
-         * 
-         * @message com.arjuna.ats.internal.jta.recovery.getxaresource Caught:
-         */
-
-    private final boolean resourceInitiatedRecovery ()
-    {
-	/*
-         * Now any additional connections we may need to create. Relies upon
-         * information provided by the application.
-         */
-
-	if (_xaRecoverers.size() > 0)
+	private final boolean xaRecovery(XAResource xares)
 	{
-	    for (int i = 0; i < _xaRecoverers.size(); i++)
-	    {
-		XAResource resource = null;
+		if (jtaLogger.logger.isDebugEnabled())
+		{
+			jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+					VisibilityLevel.VIS_PUBLIC,
+					FacilityCode.FAC_CRASH_RECOVERY, "xarecovery of " + xares);
+		}
 
 		try
 		{
-		    XAResourceRecovery ri = (XAResourceRecovery) _xaRecoverers
-			    .elementAt(i);
+			Xid[] trans = null;
 
-		    while (ri.hasMoreResources())
-		    {
 			try
 			{
-			    resource = ri.getXAResource();
+				trans = xares.recover(XAResource.TMSTARTRSCAN);
 
-			    xaRecovery(resource);
+				if (jtaLogger.loggerI18N.isDebugEnabled())
+				{
+					jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+							VisibilityLevel.VIS_PUBLIC,
+							FacilityCode.FAC_CRASH_RECOVERY, "Found "
+									+ ((trans != null) ? trans.length : 0)
+									+ " xids in doubt");
+				}
 			}
-			catch (Exception exp)
+			catch (XAException e)
 			{
-			    if (jtaLogger.loggerI18N.isWarnEnabled())
-			    {
-				jtaLogger.loggerI18N
-					.warn(
-						"com.arjuna.ats.internal.jta.recovery.getxaresource",
-						exp);
-			    }
-			}
-		    }
-		}
-		catch (Exception ex)
-		{
-		    if (jtaLogger.loggerI18N.isWarnEnabled())
-		    {
-			jtaLogger.loggerI18N
-				.warn(
-					"com.arjuna.ats.internal.jta.recovery.getxaresource",
-					ex);
-		    }
-		}
-	    }
-	}
+				if (jtaLogger.loggerI18N.isWarnEnabled())
+				{
+					jtaLogger.loggerI18N.warn(
+							"com.arjuna.ats.internal.jta.recovery.xarecovery1",
+							new Object[]
+							{ _logName + ".xaRecovery ", e,
+									XAHelper.printXAErrorCode(e) });
+				}
 
-	return true;
-    }
+				try
+				{
+					xares.recover(XAResource.TMENDRSCAN);
+				}
+				catch (Exception e1)
+				{
+				}
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.xarecovery1 {0} got XA
-         *          exception {1}, {2}
-         * @message com.arjuna.ats.internal.jta.recovery.xarecovery2 {0} got
-         *          exception {1}
-         * @message com.arjuna.ats.internal.jta.recovery.failedtorecover {0} -
-         *          failed to recover XAResource.
-         * @message com.arjuna.ats.internal.jta.recovery.forgetfailed {0} -
-         *          forget threw: {1}
-         * @message com.arjuna.ats.internal.jta.recovery.generalrecoveryerror
-         *          {0} - caught {1}
-         * @message com.arjuna.ats.internal.jta.recovery.info.rollingback
-         *          Rolling back {0}
-         * @message com.arjuna.ats.internal.jta.recovery.info.notrollback Told
-         *          not to rollback {0}
-         */
+				return false;
+			}
 
-    private final boolean xaRecovery (XAResource xares)
-    {
-	if (jtaLogger.logger.isDebugEnabled())
-	{
-	    jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-		    VisibilityLevel.VIS_PUBLIC,
-		    FacilityCode.FAC_CRASH_RECOVERY, "xarecovery of " + xares);
-	}
+			RecoveryXids xidsToRecover = null;
 
-	try
-	{
-	    Xid[] trans = null;
+			if (_xidScans == null)
+				_xidScans = new Hashtable();
+			else
+			{
+				xidsToRecover = (RecoveryXids) _xidScans.get(xares);
 
-	    try
-	    {
-		trans = xares.recover(XAResource.TMSTARTRSCAN);
+				if (xidsToRecover == null)
+				{
+					java.util.Enumeration elements = _xidScans.elements();
+					boolean found = false;
 
-		if (jtaLogger.loggerI18N.isDebugEnabled())
-		{
-		    jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-			    VisibilityLevel.VIS_PUBLIC,
-			    FacilityCode.FAC_CRASH_RECOVERY, "Found "
-				    + ((trans != null) ? trans.length : 0)
-				    + " xids in doubt");
-		}
-	    }
-	    catch (XAException e)
-	    {
-		if (jtaLogger.loggerI18N.isWarnEnabled())
-		{
-		    jtaLogger.loggerI18N.warn(
-			    "com.arjuna.ats.internal.jta.recovery.xarecovery1",
-			    new Object[]
-			    { _logName + ".xaRecovery ", e,
-				    XAHelper.printXAErrorCode(e) });
-		}
+					while (elements.hasMoreElements())
+					{
+						xidsToRecover = (RecoveryXids) elements.nextElement();
 
-		try
-		{
-		    xares.recover(XAResource.TMENDRSCAN);
-		}
-		catch (Exception e1)
-		{
-		}
+						if (xidsToRecover.isSameRM(xares))
+						{
+							found = true;
 
-		return false;
-	    }
+							break;
+						}
+					}
 
-	    RecoveryXids xidsToRecover = null;
+					if (!found)
+						xidsToRecover = null;
+				}
+			}
 
-	    if (_xidScans == null)
-		_xidScans = new Hashtable();
-	    else
-	    {
-		xidsToRecover = (RecoveryXids) _xidScans.get(xares);
-
-		if (xidsToRecover == null)
-		{
-		    java.util.Enumeration elements = _xidScans.elements();
-		    boolean found = false;
-
-		    while (elements.hasMoreElements())
-		    {
-			xidsToRecover = (RecoveryXids) elements.nextElement();
-
-			if (xidsToRecover.isSameRM(xares))
+			if (xidsToRecover == null)
 			{
-			    found = true;
+				xidsToRecover = new RecoveryXids(xares);
 
-			    break;
+				_xidScans.put(xares, xidsToRecover);
 			}
-		    }
 
-		    if (!found)
-			xidsToRecover = null;
-		}
-	    }
+			xidsToRecover.nextScan(trans);
 
-	    if (xidsToRecover == null)
-	    {
-		xidsToRecover = new RecoveryXids(xares);
+			Object[] xids = xidsToRecover.toRecover();
 
-		_xidScans.put(xares, xidsToRecover);
-	    }
+			if (xids != null)
+			{
+				if (jtaLogger.loggerI18N.isDebugEnabled())
+				{
+					jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+							VisibilityLevel.VIS_PUBLIC,
+							FacilityCode.FAC_CRASH_RECOVERY, "Have "
+									+ xids.length
+									+ " Xids to recover on this pass.");
+				}
 
-	    xidsToRecover.nextScan(trans);
+				for (int j = 0; j < xids.length; j++)
+				{
+					boolean doForget = false;
 
-	    Object[] xids = xidsToRecover.toRecover();
+					/*
+					 * Check if in failure list.
+					 */
 
-	    if (xids != null)
-	    {
-		if (jtaLogger.loggerI18N.isDebugEnabled())
-		{
-		    jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-			    VisibilityLevel.VIS_PUBLIC,
-			    FacilityCode.FAC_CRASH_RECOVERY, "Have "
-				    + xids.length
-				    + " Xids to recover on this pass.");
-		}
+					Uid recordUid = null;
+					boolean foundTransaction = false;
 
-		for (int j = 0; j < xids.length; j++)
-		{
-		    boolean doForget = false;
+					do
+					{
+						// is the xid known to be one that couldn't be recovered
 
-		    /*
-                         * Check if in failure list.
-                         */
+						recordUid = previousFailure((Xid) xids[j]);
 
-		    Uid recordUid = null;
-		    boolean foundTransaction = false;
+						if ((recordUid == null) && (foundTransaction))
+							break; // end
+						// of
+						// recovery
+						// for
+						// this
+						// transaction
 
-		    do
-		    {
-			// is the xid known to be one that couldn't be recovered
+						if (recordUid == null)
+						{
+							/*
+							 * It wasn't an xid that we couldn't recover, so the
+							 * RM knows about it, but we don't. Therefore it may
+							 * have to be rolled back.
+							 */
 
-			recordUid = previousFailure((Xid) xids[j]);
+							if (jtaLogger.loggerI18N.isDebugEnabled())
+							{
+								jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+										VisibilityLevel.VIS_PUBLIC,
+										FacilityCode.FAC_CRASH_RECOVERY,
+										"Checking node name of "
+												+ ((Xid) xids[j]));
+							}
 
-			if ((recordUid == null) && (foundTransaction))
-			    break; // end
-			// of
-			// recovery
-			// for
-			// this
-			// transaction
+							String nodeName = XAUtils
+									.getXANodeName((Xid) xids[j]);
+							boolean doRecovery = false;
 
-			if (recordUid == null)
-			{
-			    /*
-                                 * It wasn't an xid that we couldn't recover, so
-                                 * the RM knows about it, but we don't.
-                                 * Therefore it may have to be rolled back.
-                                 */
+							if (jtaLogger.loggerI18N.isDebugEnabled())
+							{
+								jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
+										VisibilityLevel.VIS_PUBLIC,
+										FacilityCode.FAC_CRASH_RECOVERY,
+										"Node name is " + nodeName);
+							}
 
-			    if (jtaLogger.loggerI18N.isDebugEnabled())
-			    {
-				jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-					VisibilityLevel.VIS_PUBLIC,
-					FacilityCode.FAC_CRASH_RECOVERY,
-					"Checking node name of "
-						+ ((Xid) xids[j]));
-			    }
+							/*
+							 * If there is no node name but we have been told to
+							 * recover everything, then we can roll it back.
+							 */
 
-			    String nodeName = XAUtils
-				    .getXANodeName((Xid) xids[j]);
-			    boolean doRecovery = false;
+							if ((nodeName == null)
+									&& (_xaRecoveryNodes != null)
+									&& (_xaRecoveryNodes
+											.contains(RECOVER_ALL_NODES)))
+							{
+								if (jtaLogger.loggerI18N.isDebugEnabled())
+								{
+									jtaLogger.logger.debug(
+											DebugLevel.FUNCTIONS,
+											VisibilityLevel.VIS_PUBLIC,
+											FacilityCode.FAC_CRASH_RECOVERY,
+											"Will recover this Xid (a)");
+								}
 
-			    if (jtaLogger.loggerI18N.isDebugEnabled())
-			    {
-				jtaLogger.logger.debug(DebugLevel.FUNCTIONS,
-					VisibilityLevel.VIS_PUBLIC,
-					FacilityCode.FAC_CRASH_RECOVERY,
-					"Node name is " + nodeName);
-			    }
+								doRecovery = true;
+							}
+							else
+							{
+								if (nodeName != null)
+								{
+									/*
+									 * Check that the node name is in our
+									 * recovery set or that we have been told to
+									 * recover everything.
+									 */
 
-			    /*
-                                 * If there is no node name but we have been
-                                 * told to recover everything, then we can roll
-                                 * it back.
-                                 */
+									if (_xaRecoveryNodes != null)
+									{
+										if (_xaRecoveryNodes
+												.contains(RECOVER_ALL_NODES)
+												|| _xaRecoveryNodes
+														.contains(nodeName))
+										{
+											if (jtaLogger.loggerI18N
+													.isDebugEnabled())
+											{
+												jtaLogger.logger
+														.debug(
+																DebugLevel.FUNCTIONS,
+																VisibilityLevel.VIS_PUBLIC,
+																FacilityCode.FAC_CRASH_RECOVERY,
+																"Will recover this Xid (b)");
+											}
 
-			    if ((nodeName == null)
-				    && (_xaRecoveryNodes != null)
-				    && (_xaRecoveryNodes
-					    .contains(RECOVER_ALL_NODES)))
-			    {
-				if (jtaLogger.loggerI18N.isDebugEnabled())
-				{
-				    jtaLogger.logger.debug(
-					    DebugLevel.FUNCTIONS,
-					    VisibilityLevel.VIS_PUBLIC,
-					    FacilityCode.FAC_CRASH_RECOVERY,
-					    "Will recover this Xid (a)");
-				}
+											doRecovery = true;
+										}
+										else
+										{
+											if (jtaLogger.loggerI18N
+													.isDebugEnabled())
+											{
+												jtaLogger.logger
+														.debug(
+																DebugLevel.FUNCTIONS,
+																VisibilityLevel.VIS_PUBLIC,
+																FacilityCode.FAC_CRASH_RECOVERY,
+																"Will not recover this Xid (a)");
+											}
+										}
+									}
+									else
+									{
+										if (jtaLogger.loggerI18N
+												.isDebugEnabled())
+										{
+											jtaLogger.logger
+													.debug(
+															DebugLevel.FUNCTIONS,
+															VisibilityLevel.VIS_PUBLIC,
+															FacilityCode.FAC_CRASH_RECOVERY,
+															"Will not recover this Xid (b)");
+										}
+									}
+								}
+								else
+								{
+									if (jtaLogger.loggerI18N.isDebugEnabled())
+									{
+										jtaLogger.logger
+												.debug(
+														DebugLevel.FUNCTIONS,
+														VisibilityLevel.VIS_PUBLIC,
+														FacilityCode.FAC_CRASH_RECOVERY,
+														"Will not recover this Xid");
+									}
+								}
+							}
 
-				doRecovery = true;
-			    }
-			    else
-			    {
-				if (nodeName != null)
-				{
-				    /*
-                                         * Check that the node name is in our
-                                         * recovery set or that we have been
-                                         * told to recover everything.
-                                         */
+							try
+							{
+								if (doRecovery)
+								{
+									if (jtaLogger.loggerI18N.isInfoEnabled())
+									{
+										jtaLogger.loggerI18N
+												.info(
+														"com.arjuna.ats.internal.jta.recovery.info.rollingback",
+														new Object[]
+														{ XAHelper
+																.xidToString((Xid) xids[j]) });
+									}
 
-				    if (_xaRecoveryNodes != null)
-				    {
-					if (_xaRecoveryNodes
-						.contains(RECOVER_ALL_NODES)
-						|| _xaRecoveryNodes
-							.contains(nodeName))
-					{
-					    if (jtaLogger.loggerI18N
-						    .isDebugEnabled())
-					    {
-						jtaLogger.logger
-							.debug(
-								DebugLevel.FUNCTIONS,
-								VisibilityLevel.VIS_PUBLIC,
-								FacilityCode.FAC_CRASH_RECOVERY,
-								"Will recover this Xid (b)");
-					    }
+									if (!transactionLog((Xid) xids[j]))
+										xares.rollback((Xid) xids[j]);
+									else
+									{
+										/*
+										 * Ignore it as the transaction system
+										 * will recovery it eventually.
+										 */
+									}
+								}
+								else
+								{
+									if (jtaLogger.loggerI18N.isInfoEnabled())
+									{
+										jtaLogger.loggerI18N
+												.info(
+														"com.arjuna.ats.internal.jta.recovery.info.notrollback",
+														new Object[]
+														{ XAHelper
+																.xidToString((Xid) xids[j]) });
+									}
+								}
+							}
+							catch (XAException e1)
+							{
+								e1.printStackTrace();
 
-					    doRecovery = true;
-					}
-					else
-					{
-					    if (jtaLogger.loggerI18N
-						    .isDebugEnabled())
-					    {
-						jtaLogger.logger
-							.debug(
-								DebugLevel.FUNCTIONS,
-								VisibilityLevel.VIS_PUBLIC,
-								FacilityCode.FAC_CRASH_RECOVERY,
-								"Will not recover this Xid (a)");
-					    }
-					}
-				    }
-				    else
-				    {
-					if (jtaLogger.loggerI18N
-						.isDebugEnabled())
-					{
-					    jtaLogger.logger
-						    .debug(
-							    DebugLevel.FUNCTIONS,
-							    VisibilityLevel.VIS_PUBLIC,
-							    FacilityCode.FAC_CRASH_RECOVERY,
-							    "Will not recover this Xid (b)");
-					}
-				    }
-				}
-				else
-				{
-				    if (jtaLogger.loggerI18N.isDebugEnabled())
-				    {
-					jtaLogger.logger
-						.debug(
-							DebugLevel.FUNCTIONS,
-							VisibilityLevel.VIS_PUBLIC,
-							FacilityCode.FAC_CRASH_RECOVERY,
-							"Will not recover this Xid");
-				    }
-				}
-			    }
+								switch (e1.errorCode)
+								{
+								case XAException.XAER_RMERR:
+									break;
+								case XAException.XA_HEURHAZ:
+								case XAException.XA_HEURCOM:
+								case XAException.XA_HEURMIX:
+								case XAException.XA_HEURRB:
+								case XAException.XA_RBROLLBACK:
+								{
+									if (!doForget) // already done?
+										doForget = true;
+								}
+									break;
+								default:
+									break;
+								}
+							}
+							catch (Exception e2)
+							{
+								if (jtaLogger.loggerI18N.isWarnEnabled())
+								{
+									jtaLogger.loggerI18N
+											.warn(
+													"com.arjuna.ats.internal.jta.recovery.xarecovery2",
+													new Object[]
+													{
+															_logName
+																	+ ".xaRecovery ",
+															e2 });
+								}
+							}
+						}
+						else
+						{
+							foundTransaction = true;
 
-			    try
-			    {
-				if (doRecovery)
-				{
-				    if (jtaLogger.loggerI18N.isInfoEnabled())
-				    {
-					jtaLogger.loggerI18N
-						.info(
-							"com.arjuna.ats.internal.jta.recovery.info.rollingback",
-							new Object[]
-							{ XAHelper
-								.xidToString((Xid) xids[j]) });
-				    }
+							/*
+							 * In the failures list so it may be that we just
+							 * need another XAResource to be able to recover
+							 * this.
+							 */
 
-				    if (!transactionLog((Xid) xids[j]))
-					xares.rollback((Xid) xids[j]);
-				    else
-				    {
-					/*
-                                         * Ignore it as the transaction system
-                                         * will recovery it eventually.
-                                         */
-				    }
-				}
-				else
-				{
-				    if (jtaLogger.loggerI18N.isInfoEnabled())
-				    {
-					jtaLogger.loggerI18N
-						.info(
-							"com.arjuna.ats.internal.jta.recovery.info.notrollback",
-							new Object[]
-							{ XAHelper
-								.xidToString((Xid) xids[j]) });
-				    }
-				}
-			    }
-			    catch (XAException e1)
-			    {
-				e1.printStackTrace();
+							XARecoveryResource record = _recoveryManagerClass
+									.getResource(recordUid, xares);
+							int recoveryStatus = record.recover();
 
-				switch (e1.errorCode)
-				{
-				case XAException.XAER_RMERR:
-				    break;
-				case XAException.XA_HEURHAZ:
-				case XAException.XA_HEURCOM:
-				case XAException.XA_HEURMIX:
-				case XAException.XA_HEURRB:
-				case XAException.XA_RBROLLBACK:
-				{
-				    if (!doForget) // already done?
-					doForget = true;
-				}
-				    break;
-				default:
-				    break;
-				}
-			    }
-			    catch (Exception e2)
-			    {
-				if (jtaLogger.loggerI18N.isWarnEnabled())
-				{
-				    jtaLogger.loggerI18N
-					    .warn(
-						    "com.arjuna.ats.internal.jta.recovery.xarecovery2",
-						    new Object[]
-						    {
-							    _logName
-								    + ".xaRecovery ",
-							    e2 });
-				}
-			    }
-			}
-			else
-			{
-			    foundTransaction = true;
+							if (recoveryStatus != XARecoveryResource.RECOVERED_OK)
+							{
+								if (jtaLogger.loggerI18N.isWarnEnabled())
+								{
+									jtaLogger.loggerI18N
+											.warn(
+													"com.arjuna.ats.internal.jta.recovery.failedtorecover",
+													new Object[]
+													{
+															_logName
+																	+ ".xaRecovery ",
+															new Integer(
+																	recoveryStatus) });
+								}
+							}
 
-			    /*
-                                 * In the failures list so it may be that we
-                                 * just need another XAResource to be able to
-                                 * recover this.
-                                 */
+							removeFailure(record.getXid(), record.get_uid());
+						}
 
-			    XARecoveryResource record = _recoveryManagerClass
-				    .getResource(recordUid, xares);
-			    int recoveryStatus = record.recover();
+						if (doForget)
+						{
+							try
+							{
+								xares.forget((Xid) xids[j]);
+							}
+							catch (Exception e)
+							{
+								if (jtaLogger.loggerI18N.isWarnEnabled())
+								{
+									jtaLogger.loggerI18N
+											.warn(
+													"com.arjuna.ats.internal.jta.recovery.forgetfailed",
+													new Object[]
+													{ _logName + ".xaRecovery",
+															e });
+								}
+							}
+						}
 
-			    if (recoveryStatus != XARecoveryResource.RECOVERED_OK)
-			    {
-				if (jtaLogger.loggerI18N.isWarnEnabled())
-				{
-				    jtaLogger.loggerI18N
-					    .warn(
-						    "com.arjuna.ats.internal.jta.recovery.failedtorecover",
-						    new Object[]
-						    {
-							    _logName
-								    + ".xaRecovery ",
-							    new Integer(
-								    recoveryStatus) });
+					} while (recordUid != null);
 				}
-			    }
-
-			    removeFailure(record.getXid(), record.get_uid());
 			}
-
-			if (doForget)
+		}
+		catch (Exception e)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
 			{
-			    try
-			    {
-				xares.forget((Xid) xids[j]);
-			    }
-			    catch (Exception e)
-			    {
-				if (jtaLogger.loggerI18N.isWarnEnabled())
-				{
-				    jtaLogger.loggerI18N
-					    .warn(
-						    "com.arjuna.ats.internal.jta.recovery.forgetfailed",
-						    new Object[]
-						    { _logName + ".xaRecovery",
-							    e });
-				}
-			    }
+				jtaLogger.loggerI18N
+						.warn(
+								"com.arjuna.ats.internal.jta.recovery.generalrecoveryerror",
+								new Object[]
+								{ _logName + ".xaRecovery", e });
 			}
 
-		    }
-		    while (recordUid != null);
+			e.printStackTrace();
 		}
-	    }
-	}
-	catch (Exception e)
-	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N
-			.warn(
-				"com.arjuna.ats.internal.jta.recovery.generalrecoveryerror",
-				new Object[]
-				{ _logName + ".xaRecovery", e });
-	    }
 
-	    e.printStackTrace();
+		try
+		{
+			if (xares != null)
+				xares.recover(XAResource.TMENDRSCAN);
+		}
+		catch (XAException e)
+		{
+			if (jtaLogger.loggerI18N.isWarnEnabled())
+			{
+				jtaLogger.loggerI18N.warn(
+						"com.arjuna.ats.internal.jta.recovery.xarecovery1",
+						new Object[]
+						{ _logName + ".xaRecovery", e,
+								XAHelper.printXAErrorCode(e) });
+			}
+		}
+
+		return true;
 	}
 
-	try
+	/**
+	 * Is there a log file for this transaction?
+	 * 
+	 * @param Xid
+	 *            xid the transaction to check.
+	 * 
+	 * @return <code>boolean</code>true if there is a log file,
+	 *         <code>false</code> if there isn't.
+	 * 
+	 * @message com.arjuna.ats.internal.jta.recovery.notaxid {0} not an Arjuna
+	 *          XID
+	 */
+
+	private final boolean transactionLog(Xid xid)
 	{
-	    if (xares != null)
-		xares.recover(XAResource.TMENDRSCAN);
-	}
-	catch (XAException e)
-	{
-	    if (jtaLogger.loggerI18N.isWarnEnabled())
-	    {
-		jtaLogger.loggerI18N.warn(
-			"com.arjuna.ats.internal.jta.recovery.xarecovery1",
-			new Object[]
-			{ _logName + ".xaRecovery", e,
-				XAHelper.printXAErrorCode(e) });
-	    }
-	}
+		if (_transactionStore == null)
+		{
+			_transactionStore = TxControl.getStore();
+		}
 
-	return true;
-    }
+		XidImple theXid = new XidImple(xid);
+		Uid u = com.arjuna.ats.internal.arjuna.utils.XATxConverter
+				.getUid(theXid.getXID());
 
-    /**
-         * Is there a log file for this transaction?
-         * 
-         * @param Xid
-         *                xid the transaction to check.
-         * 
-         * @return <code>boolean</code>true if there is a log file,
-         *         <code>false</code> if there isn't.
-         * 
-         * @message com.arjuna.ats.internal.jta.recovery.notaxid {0} not an
-         *          Arjuna XID
-         */
+		if (!u.equals(Uid.nullUid()))
+		{
+			try
+			{
+				if (_transactionStore.currentState(u, _transactionType) != ObjectStore.OS_UNKNOWN)
+				{
+					return true;
+				}
+			}
+			catch (Exception ex)
+			{
+				ex.printStackTrace();
+			}
+		}
+		else
+		{
+			if (jtaLogger.logger.isInfoEnabled())
+			{
+				jtaLogger.loggerI18N.info(
+						"com.arjuna.ats.internal.jta.recovery.notaxid",
+						new Object[]
+						{ xid });
+			}
+		}
 
-    private final boolean transactionLog (Xid xid)
-    {
-	if (_transactionStore == null)
-	{
-	    _transactionStore = TxControl.getStore();
+		return false;
 	}
 
-	XidImple theXid = new XidImple(xid);
-	Uid u = com.arjuna.ats.internal.arjuna.utils.XATxConverter
-		.getUid(theXid.getXID());
+	/**
+	 * Is the Xid is in the failure list, i.e., the list of those transactions
+	 * we couldn't recover, possibly because of transient failures. If so,
+	 * return the uid of (one of) the records and remove it from the list.
+	 */
 
-	if (!u.equals(Uid.nullUid()))
+	private final Uid previousFailure(Xid xid)
 	{
-	    try
-	    {
-		if (_transactionStore.currentState(u, _transactionType) != ObjectStore.OS_UNKNOWN)
+		if (_failures == null)
 		{
-		    return true;
+			return null;
 		}
-	    }
-	    catch (Exception ex)
-	    {
-		ex.printStackTrace();
-	    }
-	}
-	else
-	{
-	    if (jtaLogger.logger.isInfoEnabled())
-	    {
-		jtaLogger.loggerI18N.info(
-			"com.arjuna.ats.internal.jta.recovery.notaxid",
-			new Object[]
-			{ xid });
-	    }
-	}
 
-	return false;
-    }
+		Enumeration e = _failures.keys();
 
-    /**
-         * Is the Xid is in the failure list, i.e., the list of those
-         * transactions we couldn't recover, possibly because of transient
-         * failures. If so, return the uid of (one of) the records and remove it
-         * from the list.
-         */
+		while (e.hasMoreElements())
+		{
+			Xid theXid = (Xid) e.nextElement();
 
-    private final Uid previousFailure (Xid xid)
-    {
-	if (_failures == null)
-	{
-	    return null;
-	}
+			if (XAHelper.sameXID(xid, theXid))
+			{
+				// remove uid from failure list
+				Vector failureItem = (Vector) _failures.get(theXid);
+				Uid u = (Uid) failureItem.remove(0);
 
-	Enumeration e = _failures.keys();
+				if (failureItem.size() == 0)
+					_failures.remove(theXid);
 
-	while (e.hasMoreElements())
-	{
-	    Xid theXid = (Xid) e.nextElement();
+				return u;
+			}
+		}
 
-	    if (XAHelper.sameXID(xid, theXid))
-	    {
-		// remove uid from failure list
-		Vector failureItem = (Vector) _failures.get(theXid);
-		Uid u = (Uid) failureItem.remove(0);
+		// not present in the failures list.
 
-		if (failureItem.size() == 0)
-		    _failures.remove(theXid);
-
-		return u;
-	    }
+		return null;
 	}
 
-	// not present in the failures list.
+	/* methods to manipulate the failure list */
 
-	return null;
-    }
+	/**
+	 * Add record to failure list
+	 */
 
-    /* methods to manipulate the failure list */
+	private void addFailure(Xid xid, Uid uid)
+	{
+		if (_failures == null)
+			_failures = new Hashtable();
 
-    /**
-         * Add record to failure list
-         */
+		Vector failureItem = (Vector) _failures.get(xid);
 
-    private void addFailure (Xid xid, Uid uid)
-    {
-	if (_failures == null)
-	    _failures = new Hashtable();
+		if (failureItem == null)
+		{
+			failureItem = new Vector();
 
-	Vector failureItem = (Vector) _failures.get(xid);
+			_failures.put(xid, failureItem);
+		}
 
-	if (failureItem == null)
-	{
-	    failureItem = new Vector();
-
-	    _failures.put(xid, failureItem);
+		failureItem.addElement(uid);
 	}
 
-	failureItem.addElement(uid);
-    }
+	/**
+	 * @message com.arjuna.ats.internal.jta.recovery.removefailed {0} - could
+	 *          not remove record for {1}
+	 */
 
-    /**
-         * @message com.arjuna.ats.internal.jta.recovery.removefailed {0} -
-         *          could not remove record for {1}
-         */
+	/* remove record uid from failure list */
+	private void removeFailure(Xid xid, Uid uid)
+	{
+		// find the failure item for this xid
+		Vector failureItem = (Vector) _failures.get(xid);
 
-    /* remove record uid from failure list */
-    private void removeFailure (Xid xid, Uid uid)
-    {
-	// find the failure item for this xid
-	Vector failureItem = (Vector) _failures.get(xid);
+		if (failureItem == null)
+		{
+			/*
+			 * if (jtaLogger.loggerI18N.isWarnEnabled()) {
+			 * jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.recovery.removefailed",
+			 * new Object[] { _logName, xid}); }
+			 */
 
-	if (failureItem == null)
-	{
-	    /*
-                 * if (jtaLogger.loggerI18N.isWarnEnabled()) {
-                 * jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.recovery.removefailed",
-                 * new Object[] { _logName, xid}); }
-                 */
+			/*
+			 * Already removed via previousFailure.
+			 */
+		}
+		else
+		{
+			// remove this record from the item
+			failureItem.remove(uid);
 
-	    /*
-                 * Already removed via previousFailure.
-                 */
+			// if that was the last one, remove the item altogether
+			if (failureItem.size() == 0)
+				_failures.remove(xid);
+		}
 	}
-	else
-	{
-	    // remove this record from the item
-	    failureItem.remove(uid);
 
-	    // if that was the last one, remove the item altogether
-	    if (failureItem.size() == 0)
-		_failures.remove(xid);
+	private void clearAllFailures()
+	{
+		if (_failures != null)
+			_failures.clear();
 	}
-    }
 
-    private void clearAllFailures ()
-    {
-	if (_failures != null)
-	    _failures.clear();
-    }
+	private ObjectStore _objStore = new ObjectStore();
 
-    private ObjectStore _objStore = new ObjectStore();
+	private InputObjectState _uids = new InputObjectState();
 
-    private InputObjectState _uids = new InputObjectState();
+	private Vector _xaRecoverers = null;
 
-    private Vector _xaRecoverers = null;
+	private Hashtable _failures = null;
 
-    private Hashtable _failures = null;
+	private Vector _xaRecoveryNodes = null;
 
-    private Vector _xaRecoveryNodes = null;
+	private Hashtable _xidScans = null;
 
-    private Hashtable _xidScans = null;
+	private XARecoveryResourceManager _recoveryManagerClass = null;
 
-    private XARecoveryResourceManager _recoveryManagerClass = null;
+	private String _logName = null;
 
-    private String _logName = null;
+	// 'type' within the Object Store for AtomicActions.
+	private String _transactionType = new AtomicAction().type();
 
-    // 'type' within the Object Store for AtomicActions.
-    private String _transactionType = new AtomicAction().type();
+	// Reference to the Object Store.
+	private static ObjectStore _transactionStore = null;
 
-    // Reference to the Object Store.
-    private static ObjectStore _transactionStore = null;
+	private static int _backoffPeriod = 0;
 
-    private static int _backoffPeriod = 0;
+	private static final int XA_BACKOFF_PERIOD = 20000; // backoff in
 
-    private static final int XA_BACKOFF_PERIOD = 20000; // backoff in
+	// milliseconds
 
-    // milliseconds
+	private static final char BREAKCHARACTER = ';'; // delimiter for xaconnrecov
+	// property
 
-    private static final char BREAKCHARACTER = ';'; // delimiter for
-    // xaconnrecov
-    // property
+	static
+	{
+		String env = jtaPropertyManager.propertyManager
+				.getProperty(com.arjuna.ats.jta.common.Environment.XA_BACKOFF_PERIOD);
 
-    static
-    {
-	String env = jtaPropertyManager.propertyManager
-		.getProperty(com.arjuna.ats.jta.common.Environment.XA_BACKOFF_PERIOD);
+		XARecoveryModule._backoffPeriod = XA_BACKOFF_PERIOD;
 
-	XARecoveryModule._backoffPeriod = XA_BACKOFF_PERIOD;
+		if (env != null)
+		{
+			try
+			{
+				Integer i = new Integer(env);
 
-	if (env != null)
-	{
-	    try
-	    {
-		Integer i = new Integer(env);
-
-		XARecoveryModule._backoffPeriod = i.intValue();
-	    }
-	    catch (Exception e)
-	    {
-		throw new ExceptionInInitializerError(e);
-	    }
+				XARecoveryModule._backoffPeriod = i.intValue();
+			}
+			catch (Exception e)
+			{
+				throw new ExceptionInInitializerError(e);
+			}
+		}
 	}
-    }
 
 }

Modified: labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/resources/arjunacore/XAResourceRecord.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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,10 +276,10 @@
 						.warn(
 								"com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed",
 								new Object[]
-								{ "XAResourceRecord.prepare", XAHelper
-										.printXAErrorCode(e1) });
+								{ "XAResourceRecord.prepare",
+										XAHelper.printXAErrorCode(e1) });
 			}
-			
+
 			/*
 			 * XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
 			 * XAER_PROTO.
@@ -288,9 +288,10 @@
 			if (_rollbackOptimization) // won't have rollback called on it
 				removeConnection();
 
-			if ((e1.errorCode == XAException.XAER_RMERR) || (e1.errorCode == XAException.XAER_RMFAIL))
+			if ((e1.errorCode == XAException.XAER_RMERR)
+					|| (e1.errorCode == XAException.XAER_RMFAIL))
 				return TwoPhaseOutcome.HEURISTIC_HAZARD;
-			
+
 			return TwoPhaseOutcome.PREPARE_NOTOK;
 		}
 		catch (Exception e2)
@@ -358,6 +359,9 @@
 		}
 		else
 		{
+			if (_theXAResource == null)
+				_theXAResource = getNewXAResource();
+
 			if (_theXAResource != null)
 			{
 				if (_heuristic != TwoPhaseOutcome.FINISH_OK)
@@ -477,6 +481,9 @@
 		}
 		else
 		{
+			if (_theXAResource == null)
+				_theXAResource = getNewXAResource();
+
 			if (_theXAResource != null)
 			{
 				if (_heuristic != TwoPhaseOutcome.FINISH_OK)
@@ -511,12 +518,14 @@
 						 * XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
 						 * XAER_PROTO.
 						 */
-					
+
 						switch (e1.errorCode)
 						{
 						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:
@@ -538,8 +547,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;
@@ -627,7 +636,7 @@
 					 * TODO in Oracle the end is not needed. Is this common
 					 * across other RMs?
 					 */
-					
+
 					if (endAssociation())
 					{
 						_theXAResource.end(_tranID, XAResource.TMSUCCESS);
@@ -655,7 +664,7 @@
 					case XAException.XA_HEURMIX:
 						return TwoPhaseOutcome.HEURISTIC_HAZARD;
 					case XAException.XA_HEURCOM:
-						forget() ;
+						forget();
 						break;
 					case XAException.XA_HEURRB:
 					case XAException.XA_RBROLLBACK:
@@ -667,19 +676,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)
@@ -718,13 +727,13 @@
 					"XAResourceRecord.forget for " + _tranID);
 		}
 
-		forget() ;
+		forget();
 
 		removeConnection();
 
 		return true;
 	}
-	
+
 	private void forget()
 	{
 		if ((_theXAResource != null) && (_tranID != null))
@@ -767,11 +776,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)
 	{
@@ -800,8 +809,8 @@
 
 				try
 				{
-				    if (_theXAResource instanceof Serializable)
-					shouldSerialize = true;
+					if (_theXAResource instanceof Serializable)
+						shouldSerialize = true;
 
 					ByteArrayOutputStream s = new ByteArrayOutputStream();
 					ObjectOutputStream o = new ObjectOutputStream(s);
@@ -820,19 +829,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
@@ -864,7 +874,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)
@@ -911,10 +922,12 @@
 
 						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);
 						}
-						
+
 						return false;
 					}
 				}
@@ -925,11 +938,16 @@
 					 */
 
 					_theXAResource = getNewXAResource();
-					
+
 					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;
 					}
 				}
 			}
@@ -1112,7 +1130,7 @@
 			if (_theTransaction.getXAResourceState(_theXAResource) == TxInfo.NOT_ASSOCIATED)
 			{
 				// end has been called so we don't need to do it again!
-				
+
 				doEnd = false;
 			}
 		}
@@ -1125,10 +1143,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/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/TxImporter.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -53,45 +53,57 @@
  * 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
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			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 (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)
@@ -105,30 +117,31 @@
 		catch (SystemException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw new XAException(XAException.XAER_RMERR);
 		}
 	}
-	
+
 	/**
-	 * 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
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			tx.doForget();
 		}
 		catch (Exception ex)
@@ -140,38 +153,43 @@
 			TxImporter.removeImportedTransaction(xid);
 		}
 	}
-	
+
 	/**
 	 * 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
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			switch (tx.doPrepare())
 			{
 			case TwoPhaseOutcome.PREPARE_READONLY:
 				TxImporter.removeImportedTransaction(xid);
-				
-				return XAResource.XA_RDONLY;				
+
+				return XAResource.XA_RDONLY;
 			case TwoPhaseOutcome.PREPARE_NOTOK:
-				TxImporter.removeImportedTransaction(xid);  // TODO check if rollback is going to be called first
-				
+				TxImporter.removeImportedTransaction(xid); // TODO check if
+															// rollback is going
+															// to be called
+															// first
+
 				throw new XAException(XAException.XA_RBROLLBACK);
 			case TwoPhaseOutcome.PREPARE_OK:
 				return XAResource.XA_OK;
@@ -184,29 +202,31 @@
 			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.
+	 * 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)
 		{
 		case XAResource.TMSTARTRSCAN: // check the object store
@@ -227,23 +247,25 @@
 		default:
 			throw new XAException(XAException.XAER_PROTO);
 		}
-		
+
 		// if we are here, then check the object store
-		
+
 		Xid[] indoubt = null;
-		
+
 		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()))
+
+			if (objStore.allObjUids(SubordinateAtomicAction.getType(), states)
+					&& (states.notempty()))
 			{
 				Stack values = new Stack();
 				boolean finished = false;
-				
+
 				do
 				{
 					Uid uid = new Uid(Uid.nullUid());
@@ -258,29 +280,31 @@
 
 						finished = true;
 					}
-					
+
 					if (uid.notEquals(Uid.nullUid()))
 					{
-						TransactionImple tx = TxImporter.recoverTransaction(uid);
-						
+						TransactionImple tx = TxImporter
+								.recoverTransaction(uid);
+
 						if (tx != null)
 							values.push(tx);
 					}
 					else
 						finished = true;
-					
+
 				} while (!finished);
-				
+
 				if (values.size() > 0)
 				{
 					int index = 0;
 
 					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();
-						
+						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++;
 					}
@@ -291,35 +315,47 @@
 		{
 			ex.printStackTrace();
 		}
-			
+
 		return indoubt;
 	}
 
 	/**
 	 * 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
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
-			tx.doRollback();
-			
-			TxImporter.removeImportedTransaction(xid);
+
+			if (tx.activated())
+			{
+				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)
@@ -333,11 +369,11 @@
 		catch (SystemException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw new XAException(XAException.XAER_RMERR);
 		}
 	}
-	
+
 	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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -115,8 +115,6 @@
 	 *         logs in the transaction object store.
 	 */
 
-	// TODO crash recovery!!!!
-	
 	public String type ()
 	{
 		return "/StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction/SubordinateAtomicAction";
@@ -232,5 +230,9 @@
 	{
 		return false;
 	}
-	
+
+    public boolean activated ()
+    {
+    	return true;
+    }	
 }

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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -334,5 +334,17 @@
 
 		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/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/SubordinateAtomicAction.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/jca/TransactionImple.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/TxImporter.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/jca/XATerminatorImple.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -45,6 +45,7 @@
 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.transaction.arjunacore.jca.TxImporter;
 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.jta.utils.XAHelper;
@@ -69,17 +70,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 +276,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/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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/SubordinateAtomicTransaction.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/TransactionImple.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -379,7 +379,7 @@
 					+ super._theTransaction.get_uid() + " >";
 		}
 	}
-
+	
 	protected void commitAndDisassociate ()
 			throws javax.transaction.RollbackException,
 			javax.transaction.HeuristicMixedException,

Modified: labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/subordinate/jca/coordinator/ServerTransaction.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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/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	2007-10-24 10:44:57 UTC (rev 16046)
+++ labs/jbosstm/trunk/atsintegration/classes/com/arjuna/ats/internal/jbossatx/jta/jca/XATerminator.java	2007-10-24 11:17:15 UTC (rev 16047)
@@ -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