[jboss-svn-commits] JBL Code SVN: r17348 - labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Dec 20 19:16:58 EST 2007
Author: mark.little at jboss.com
Date: 2007-12-20 19:16:57 -0500 (Thu, 20 Dec 2007)
New Revision: 17348
Modified:
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseCoordinator.java
Log:
http://jira.jboss.com/jira/browse/JBTM-316
Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseCoordinator.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseCoordinator.java 2007-12-20 20:43:54 UTC (rev 17347)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TwoPhaseCoordinator.java 2007-12-21 00:16:57 UTC (rev 17348)
@@ -210,81 +210,99 @@
{
boolean problem = false;
- /*
- * If we have a synchronization list then we must be top-level.
- */
-
- if (_synchs != null)
+ synchronized (_syncLock)
{
- /*
- * We must always call afterCompletion() methods, so just catch (and
- * log) any exceptions/errors from beforeCompletion() methods.
- *
- * If one of the Syncs throws an error the Record wrapper returns false
- * and we will rollback. Hence we don't then bother to call beforeCompletion
- * on the remaining records (it's not done for rollabcks anyhow).
- *
- * Since Synchronizations may add register other Synchronizations, we can't simply
- * iterate the collection. Instead we work from an ordered copy, which we periodically
- * check for freshness. The addSynchronization method uses _currentRecord to disallow
- * adding records in the part of the array we have already traversed, thus all
- * Synchronization will be called and the (jta only) rules on ordering of interposed
- * Synchronization will be respected.
- */
+ if (!_beforeCalled)
+ {
+ _beforeCalled = true;
+
+ /*
+ * If we have a synchronization list then we must be top-level.
+ */
- int lastIndexProcessed = -1;
- SynchronizationRecord[] copiedSynchs = (SynchronizationRecord[])_synchs.toArray(new SynchronizationRecord[] {});
+ if (_synchs != null)
+ {
+ /*
+ * We must always call afterCompletion() methods, so just catch (and
+ * log) any exceptions/errors from beforeCompletion() methods.
+ *
+ * If one of the Syncs throws an error the Record wrapper returns false
+ * and we will rollback. Hence we don't then bother to call beforeCompletion
+ * on the remaining records (it's not done for rollabcks anyhow).
+ *
+ * Since Synchronizations may add register other Synchronizations, we can't simply
+ * iterate the collection. Instead we work from an ordered copy, which we periodically
+ * check for freshness. The addSynchronization method uses _currentRecord to disallow
+ * adding records in the part of the array we have already traversed, thus all
+ * Synchronization will be called and the (jta only) rules on ordering of interposed
+ * Synchronization will be respected.
+ */
- while( (lastIndexProcessed < _synchs.size()-1) && !problem) {
+ int lastIndexProcessed = -1;
+ SynchronizationRecord[] copiedSynchs = (SynchronizationRecord[])_synchs.toArray(new SynchronizationRecord[] {});
- // if new Synchronization have been registered, refresh our copy of the collection:
- if(copiedSynchs.length != _synchs.size()) {
- copiedSynchs = (SynchronizationRecord[])_synchs.toArray(new SynchronizationRecord[] {});
- }
+ while( (lastIndexProcessed < _synchs.size()-1) && !problem) {
- lastIndexProcessed = lastIndexProcessed+1;
- _currentRecord = copiedSynchs[lastIndexProcessed];
+ // if new Synchronization have been registered, refresh our copy of the collection:
+ if(copiedSynchs.length != _synchs.size()) {
+ copiedSynchs = (SynchronizationRecord[])_synchs.toArray(new SynchronizationRecord[] {});
+ }
- try
- {
- problem = !_currentRecord.beforeCompletion();
+ lastIndexProcessed = lastIndexProcessed+1;
+ _currentRecord = copiedSynchs[lastIndexProcessed];
- // if something goes wrong, we can't just throw the exception, we need to continue to
- // complete the transaction. However, the exception may have interesting information that
- // we want later, so we keep a reference to it as well as logging it.
+ try
+ {
+ problem = !_currentRecord.beforeCompletion();
- }
- catch (Exception ex)
- {
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2", new Object[]
- { _currentRecord }, ex);
- if(_deferredThrowable == null) {
- _deferredThrowable = ex;
+ // if something goes wrong, we can't just throw the exception, we need to continue to
+ // complete the transaction. However, the exception may have interesting information that
+ // we want later, so we keep a reference to it as well as logging it.
+
+ }
+ catch (Exception ex)
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2", new Object[]
+ { _currentRecord }, ex);
+ if(_deferredThrowable == null) {
+ _deferredThrowable = ex;
+ }
+ problem = true;
+ }
+ catch (Error er)
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2", new Object[]
+ { _currentRecord }, er);
+ if(_deferredThrowable == null) {
+ _deferredThrowable = er;
+ }
+ problem = true;
+ }
}
- problem = true;
- }
- catch (Error er)
- {
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2", new Object[]
- { _currentRecord }, er);
- if(_deferredThrowable == null) {
- _deferredThrowable = er;
+
+ if (problem)
+ {
+ if (!preventCommit())
+ {
+ /*
+ * This should not happen. If it does, continue with commit
+ * to tidy-up.
+ */
+
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_1");
+ }
}
- problem = true;
}
}
-
- if (problem)
+ else
{
- if (!preventCommit())
- {
- /*
- * This should not happen. If it does, continue with commit
- * to tidy-up.
- */
-
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_1");
- }
+ /*
+ * beforeCompletions already called. Assume everything is alright
+ * to proceed to commit. The TM instance will flag the outcome. If
+ * it's rolling back, then we'll get an exception. If it's committing
+ * then we'll be blocked until the commit (assuming we're still the
+ * slower thread).
+ */
}
}
@@ -319,51 +337,64 @@
boolean problem = false;
- if (_synchs != null)
+ synchronized (_syncLock)
{
- // afterCompletions should run in reverse order compared to beforeCompletions
- Stack stack = new Stack();
- Iterator iterator = _synchs.iterator();
- while(iterator.hasNext()) {
- stack.push(iterator.next());
- }
-
- iterator = stack.iterator();
-
- /*
- * Regardless of failures, we must tell all synchronizations what
- * happened.
- */
- while(!stack.isEmpty())
+ if (!_afterCalled)
{
- SynchronizationRecord record = (SynchronizationRecord)stack.pop();
+ _afterCalled = true;
- try
+ if (_synchs != null)
{
- if (!record.afterCompletion(myStatus))
+ // afterCompletions should run in reverse order compared to
+ // beforeCompletions
+ Stack stack = new Stack();
+ Iterator iterator = _synchs.iterator();
+ while(iterator.hasNext()) {
+ stack.push(iterator.next());
+ }
+
+ iterator = stack.iterator();
+
+ /*
+ * Regardless of failures, we must tell all synchronizations what
+ * happened.
+ */
+ while(!stack.isEmpty())
{
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4", new Object[]
- { record });
-
- problem = true;
+ SynchronizationRecord record = (SynchronizationRecord)stack.pop();
+
+ try
+ {
+ if (!record.afterCompletion(myStatus))
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4", new Object[]
+ { record });
+
+ problem = true;
+ }
+ }
+ catch (Exception ex)
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4a", new Object[]
+ { record, ex });
+ problem = true;
+ }
+ catch (Error er)
+ {
+ tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4b", new Object[]
+ { record, er });
+ problem = true;
+ }
}
+
+ _synchs = null;
+ _currentRecord = null;
}
- catch (Exception ex)
- {
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4a", new Object[]
- { record, ex });
- problem = true;
- }
- catch (Error er)
- {
- tsLogger.arjLoggerI18N.warn("com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_4b", new Object[]
- { record, er });
- problem = true;
- }
}
-
- _synchs = null;
- _currentRecord = null;
+ else
+ {
+
+ }
}
return !problem;
@@ -372,4 +403,9 @@
private SortedSet _synchs;
private SynchronizationRecord _currentRecord; // the most recently processed Synchronization.
private Throwable _deferredThrowable;
+
+ private Object _syncLock = new Object();
+
+ private boolean _beforeCalled = false;
+ private boolean _afterCalled = false;
}
More information about the jboss-svn-commits
mailing list