[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