[jboss-svn-commits] JBL Code SVN: r36866 - 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
Mon Mar 28 09:02:04 EDT 2011
Author: jhalliday
Date: 2011-03-28 09:02:03 -0400 (Mon, 28 Mar 2011)
New Revision: 36866
Modified:
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
Log:
performance tweak for exception usage in BasicAction.prepare JBTM-831
Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java 2011-03-28 10:37:17 UTC (rev 36865)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java 2011-03-28 13:02:03 UTC (rev 36866)
@@ -51,7 +51,7 @@
/**
* BasicAction does most of the work of an atomic action, but does not manage
* thread scoping. This is the responsibility of any derived classes.
- *
+ *
* @author Mark Little (mark at arjuna.com)
* @version $Id: BasicAction.java 2342 2006-03-30 13:06:17Z $
* @since JTS 1.0.
@@ -60,92 +60,92 @@
public class BasicAction extends StateManager
{
- public BasicAction ()
- {
- super(ObjectType.NEITHER);
+ public BasicAction ()
+ {
+ super(ObjectType.NEITHER);
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::BasicAction()");
}
- pendingList = null;
- preparedList = null;
- readonlyList = null;
- failedList = null;
- heuristicList = null;
+ pendingList = null;
+ preparedList = null;
+ readonlyList = null;
+ failedList = null;
+ heuristicList = null;
- currentHierarchy = null;
- participantStore = null;
- savedIntentionList = false;
+ currentHierarchy = null;
+ participantStore = null;
+ savedIntentionList = false;
- actionStatus = ActionStatus.CREATED;
- actionType = ActionType.NESTED;
+ actionStatus = ActionStatus.CREATED;
+ actionType = ActionType.NESTED;
- parentAction = null;
- recordBeingHandled = null;
+ parentAction = null;
+ recordBeingHandled = null;
- heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
- _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
+ heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+ _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
- _childThreads = null;
- _childActions = null;
- }
+ _childThreads = null;
+ _childActions = null;
+ }
- /**
- * BasicAction constructor with a Uid. This constructor is for recreating an
- * BasicAction, typically during crash recovery.
- */
+ /**
+ * BasicAction constructor with a Uid. This constructor is for recreating an
+ * BasicAction, typically during crash recovery.
+ */
- public BasicAction (Uid objUid)
- {
- super(objUid, ObjectType.NEITHER);
+ public BasicAction (Uid objUid)
+ {
+ super(objUid, ObjectType.NEITHER);
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::BasicAction("
+ objUid + ")");
}
- pendingList = null;
- preparedList = null;
- readonlyList = null;
- failedList = null;
- heuristicList = null;
+ pendingList = null;
+ preparedList = null;
+ readonlyList = null;
+ failedList = null;
+ heuristicList = null;
- currentHierarchy = null;
- participantStore = null;
- savedIntentionList = false;
+ currentHierarchy = null;
+ participantStore = null;
+ savedIntentionList = false;
- actionStatus = ActionStatus.CREATED;
- actionType = ActionType.NESTED;
+ actionStatus = ActionStatus.CREATED;
+ actionType = ActionType.NESTED;
- parentAction = null;
- recordBeingHandled = null;
+ parentAction = null;
+ recordBeingHandled = null;
- heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
- _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
+ heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+ _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
- _childThreads = null;
- _childActions = null;
- }
+ _childThreads = null;
+ _childActions = null;
+ }
- /**
- * BasicAction destructor. Under normal circumstances we do very little.
- * However there exists the possibility that this action is being deleted
- * while still running (user forgot to commit/abort) - in which case we do
- * an abort for him and mark all our parents as unable to commit.
- * Additionally due to scoping we may not be the current action - but in
- * that case the current action must be one of our nested actions so by
- * applying abort to it we should end up at ourselves!
- */
+ /**
+ * BasicAction destructor. Under normal circumstances we do very little.
+ * However there exists the possibility that this action is being deleted
+ * while still running (user forgot to commit/abort) - in which case we do
+ * an abort for him and mark all our parents as unable to commit.
+ * Additionally due to scoping we may not be the current action - but in
+ * that case the current action must be one of our nested actions so by
+ * applying abort to it we should end up at ourselves!
+ */
- public void finalize ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public void finalize ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::finalize()");
}
- if ((actionStatus == ActionStatus.RUNNING)
- || (actionStatus == ActionStatus.ABORT_ONLY)) {
+ if ((actionStatus == ActionStatus.RUNNING)
+ || (actionStatus == ActionStatus.ABORT_ONLY)) {
/* If current action is one of my children there's an error */
BasicAction currentAct = BasicAction.Current();
@@ -187,547 +187,547 @@
Abort();
}
- else
- {
- if (actionStatus == ActionStatus.PREPARED)
- Thread.yield();
- }
+ else
+ {
+ if (actionStatus == ActionStatus.PREPARED)
+ Thread.yield();
+ }
- pendingList = null;
- preparedList = null;
- readonlyList = null;
- failedList = null;
- heuristicList = null;
+ pendingList = null;
+ preparedList = null;
+ readonlyList = null;
+ failedList = null;
+ heuristicList = null;
- participantStore = null;
- currentHierarchy = null;
+ participantStore = null;
+ currentHierarchy = null;
- _checkedAction = null;
+ _checkedAction = null;
- if (_childThreads != null)
- {
- _childThreads.clear();
- _childThreads = null;
- }
+ if (_childThreads != null)
+ {
+ _childThreads.clear();
+ _childThreads = null;
+ }
- if (_childActions != null)
- {
- _childActions.clear();
- _childActions = null;
- }
- }
+ if (_childActions != null)
+ {
+ _childActions.clear();
+ _childActions = null;
+ }
+ }
- /**
- * Return the action hierarchy for this transaction.
- */
+ /**
+ * Return the action hierarchy for this transaction.
+ */
- public final synchronized ActionHierarchy getHierarchy ()
- {
- return currentHierarchy;
- }
+ public final synchronized ActionHierarchy getHierarchy ()
+ {
+ return currentHierarchy;
+ }
- /**
- * Force the only outcome for the transaction to be to rollback. Only
- * possible if this transaction has not (or is not) terminated.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Force the only outcome for the transaction to be to rollback. Only
+ * possible if this transaction has not (or is not) terminated.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean preventCommit ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public final boolean preventCommit ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::preventCommit( " + this + ")");
}
-
- boolean res = false;
- // if (lockMutex())
- {
- /*
- * If we are active then change status. Otherwise it may be an error so check status.
- */
-
- if (actionStatus == ActionStatus.RUNNING)
- actionStatus = ActionStatus.ABORT_ONLY;
+ boolean res = false;
- /*
- * Since the reason to call this method is to make sure the transaction
- * only aborts, check the status now and if it has aborted or will abort then
- * we'll consider it a success.
- */
-
- res = ((actionStatus == ActionStatus.ABORT_ONLY) || (actionStatus == ActionStatus.ABORTED) || (actionStatus == ActionStatus.ABORTING));
+ // if (lockMutex())
+ {
+ /*
+ * If we are active then change status. Otherwise it may be an error so check status.
+ */
- // unlockMutex();
- }
+ if (actionStatus == ActionStatus.RUNNING)
+ actionStatus = ActionStatus.ABORT_ONLY;
- return res;
- }
+ /*
+ * Since the reason to call this method is to make sure the transaction
+ * only aborts, check the status now and if it has aborted or will abort then
+ * we'll consider it a success.
+ */
- /**
- * @return the number of threads associated with this transaction.
- */
+ res = ((actionStatus == ActionStatus.ABORT_ONLY) || (actionStatus == ActionStatus.ABORTED) || (actionStatus == ActionStatus.ABORTING));
- public final int activeThreads ()
- {
- if (_childThreads != null)
- return _childThreads.size();
- else
- return 0;
- }
+ // unlockMutex();
+ }
- /**
- * Add a record to the atomic action. This function returns AR_ADDED if the
- * record is added. AR_REJECTED if the record cannot be added because the
- * action is past the prepare phase, and IGNORED otherwise.
- *
- * @return <code>AddOutcome</code> indicating outcome.
- */
+ return res;
+ }
- public final synchronized int add (AbstractRecord A)
- {
- int result = AddOutcome.AR_REJECTED;
+ /**
+ * @return the number of threads associated with this transaction.
+ */
- criticalStart();
+ public final int activeThreads ()
+ {
+ if (_childThreads != null)
+ return _childThreads.size();
+ else
+ return 0;
+ }
- if ((actionStatus <= ActionStatus.ABORTING)
- && ((recordBeingHandled == null) || !(recordBeingHandled.equals(A))))
- {
- if (pendingList == null)
- pendingList = new RecordList();
+ /**
+ * Add a record to the atomic action. This function returns AR_ADDED if the
+ * record is added. AR_REJECTED if the record cannot be added because the
+ * action is past the prepare phase, and IGNORED otherwise.
+ *
+ * @return <code>AddOutcome</code> indicating outcome.
+ */
- result = (pendingList.insert(A) ? AddOutcome.AR_ADDED
- : AddOutcome.AR_DUPLICATE);
- }
+ public final synchronized int add (AbstractRecord A)
+ {
+ int result = AddOutcome.AR_REJECTED;
- criticalEnd();
+ criticalStart();
- return result;
- }
+ if ((actionStatus <= ActionStatus.ABORTING)
+ && ((recordBeingHandled == null) || !(recordBeingHandled.equals(A))))
+ {
+ if (pendingList == null)
+ pendingList = new RecordList();
- /**
- * @return the depth of the current transaction hierarchy.
- */
+ result = (pendingList.insert(A) ? AddOutcome.AR_ADDED
+ : AddOutcome.AR_DUPLICATE);
+ }
- public final synchronized int hierarchyDepth ()
- {
- if (currentHierarchy != null)
- return currentHierarchy.depth();
- else
- return 0; /* should never happen */
- }
+ criticalEnd();
- /**
- * boolean function that checks whether the Uid passed as an argument is the
- * Uid for an ancestor of the current atomic action.
- *
- * @return <code>true</code> if the parameter represents an ancestor,
- * <code>false</code> otherwise.
- */
+ return result;
+ }
- public final boolean isAncestor (Uid ancestor)
- {
- boolean res = false;
+ /**
+ * @return the depth of the current transaction hierarchy.
+ */
- if (get_uid().equals(ancestor)) /* actions are their own ancestors */
- res = true;
- else
- {
- if ((parentAction != null) && (actionType != ActionType.TOP_LEVEL))
- res = parentAction.isAncestor(ancestor);
- }
+ public final synchronized int hierarchyDepth ()
+ {
+ if (currentHierarchy != null)
+ return currentHierarchy.depth();
+ else
+ return 0; /* should never happen */
+ }
- return res;
- }
+ /**
+ * boolean function that checks whether the Uid passed as an argument is the
+ * Uid for an ancestor of the current atomic action.
+ *
+ * @return <code>true</code> if the parameter represents an ancestor,
+ * <code>false</code> otherwise.
+ */
- /**
- * @return a reference to the parent BasicAction
- */
+ public final boolean isAncestor (Uid ancestor)
+ {
+ boolean res = false;
- public final BasicAction parent ()
- {
- if (actionType == ActionType.NESTED)
- return parentAction;
- else
- return null;
- }
+ if (get_uid().equals(ancestor)) /* actions are their own ancestors */
+ res = true;
+ else
+ {
+ if ((parentAction != null) && (actionType != ActionType.TOP_LEVEL))
+ res = parentAction.isAncestor(ancestor);
+ }
- public final int typeOfAction ()
- {
- return actionType;
- }
+ return res;
+ }
- /**
- * @return the status of the BasicAction
- */
+ /**
+ * @return a reference to the parent BasicAction
+ */
- public final int status ()
- {
- int s = ActionStatus.INVALID;
+ public final BasicAction parent ()
+ {
+ if (actionType == ActionType.NESTED)
+ return parentAction;
+ else
+ return null;
+ }
- // if (tryLockMutex())
- {
- s = actionStatus;
+ public final int typeOfAction ()
+ {
+ return actionType;
+ }
- // unlockMutex();
- }
+ /**
+ * @return the status of the BasicAction
+ */
- return s;
- }
+ public final int status ()
+ {
+ int s = ActionStatus.INVALID;
- /**
- * Set up an object store and assign it to the participantStore variable.
- *
- * @return the object store implementation to use.
- * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
- */
+ // if (tryLockMutex())
+ {
+ s = actionStatus;
- public ParticipantStore getStore ()
- {
- if (participantStore == null)
- {
- participantStore = StoreManager.getParticipantStore();
- }
+ // unlockMutex();
+ }
- return participantStore;
- }
+ return s;
+ }
- /**
- * The following function returns the Uid of the top-level atomic action. If
- * this is the top-level transaction then it is equivalent to calling
- * get_uid().
- *
- * @return the top-level transaction's <code>Uid</code>.
- */
+ /**
+ * Set up an object store and assign it to the participantStore variable.
+ *
+ * @return the object store implementation to use.
+ * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
+ */
- public final Uid topLevelActionUid ()
- {
- BasicAction root = this;
+ public ParticipantStore getStore ()
+ {
+ if (participantStore == null)
+ {
+ participantStore = StoreManager.getParticipantStore();
+ }
- while (root.parent() != null)
- root = root.parent();
+ return participantStore;
+ }
- return root.get_uid();
- }
+ /**
+ * The following function returns the Uid of the top-level atomic action. If
+ * this is the top-level transaction then it is equivalent to calling
+ * get_uid().
+ *
+ * @return the top-level transaction's <code>Uid</code>.
+ */
- /**
- * @return a reference to the top-level transaction. If this is the
- * top-level transaction then a reference to itself will be
- * returned.
- */
+ public final Uid topLevelActionUid ()
+ {
+ BasicAction root = this;
- public final BasicAction topLevelAction ()
- {
- BasicAction root = this;
+ while (root.parent() != null)
+ root = root.parent();
- while (root.parent() != null)
- root = root.parent();
+ return root.get_uid();
+ }
- return root;
- }
+ /**
+ * @return a reference to the top-level transaction. If this is the
+ * top-level transaction then a reference to itself will be
+ * returned.
+ */
- /**
- * Overloaded version of activate -- sets up the store, performs read_state
- * followed by restore_state. The store root is <code>null</code>.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ public final BasicAction topLevelAction ()
+ {
+ BasicAction root = this;
- public boolean activate ()
- {
- return activate(null);
- }
+ while (root.parent() != null)
+ root = root.parent();
- /**
- * Overloaded version of activate -- sets up the store, performs read_state
- * followed by restore_state. The root of the object store to use is
- * specified in the <code>root</code> parameter.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ return root;
+ }
- public boolean activate (String root)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ /**
+ * Overloaded version of activate -- sets up the store, performs read_state
+ * followed by restore_state. The store root is <code>null</code>.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean activate ()
+ {
+ return activate(null);
+ }
+
+ /**
+ * Overloaded version of activate -- sets up the store, performs read_state
+ * followed by restore_state. The root of the object store to use is
+ * specified in the <code>root</code> parameter.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean activate (String root)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::activate() for action-id "
+ get_uid());
}
- boolean restored = false;
+ boolean restored = false;
- // Set up store
- ParticipantStore aaStore = getStore();
+ // Set up store
+ ParticipantStore aaStore = getStore();
- if (aaStore == null)
- return false;
+ if (aaStore == null)
+ return false;
- try
- {
- // Read object state
+ try
+ {
+ // Read object state
- InputObjectState oState = aaStore.read_committed(getSavingUid(), type());
+ InputObjectState oState = aaStore.read_committed(getSavingUid(), type());
- if (oState != null)
- {
- synchronized (this)
- {
- restored = restore_state(oState, ObjectType.ANDPERSISTENT);
- }
+ if (oState != null)
+ {
+ synchronized (this)
+ {
+ restored = restore_state(oState, ObjectType.ANDPERSISTENT);
+ }
- oState = null;
- }
- else {
+ oState = null;
+ }
+ else {
tsLogger.i18NLogger.warn_coordinator_BasicAction_5(get_uid(), type());
restored = false;
}
- return restored;
- }
- catch (ObjectStoreException e)
- {
- tsLogger.logger.warn(e);
+ return restored;
+ }
+ catch (ObjectStoreException e)
+ {
+ tsLogger.logger.warn(e);
- return false;
- }
- }
+ return false;
+ }
+ }
- /**
- * This operation deactivates a persistent object. It behaves in a similar
- * manner to the activate operation, but has an extra argument which defines
- * whether the object's state should be committed or written as a shadow.
- *
- * The root of the object store is <code>null</code>. It is assumed that
- * this is being called during a transaction commit.
- *
- * @return <code>true</code> on success, <code>false</code> otherwise.
- */
+ /**
+ * This operation deactivates a persistent object. It behaves in a similar
+ * manner to the activate operation, but has an extra argument which defines
+ * whether the object's state should be committed or written as a shadow.
+ *
+ * The root of the object store is <code>null</code>. It is assumed that
+ * this is being called during a transaction commit.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
- public boolean deactivate ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public boolean deactivate ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::deactivate() for action-id "
+ get_uid());
}
- boolean deactivated = false;
+ boolean deactivated = false;
- // Set up store
- ParticipantStore aaStore = getStore();
+ // Set up store
+ ParticipantStore aaStore = getStore();
- if (aaStore == null)
- return false;
+ if (aaStore == null)
+ return false;
- try
- {
- // Write object state
- OutputObjectState oState = new OutputObjectState();
+ try
+ {
+ // Write object state
+ OutputObjectState oState = new OutputObjectState();
- if (save_state(oState, ObjectType.ANDPERSISTENT))
- {
- deactivated = aaStore.write_committed(getSavingUid(), type(), oState);
+ if (save_state(oState, ObjectType.ANDPERSISTENT))
+ {
+ deactivated = aaStore.write_committed(getSavingUid(), type(), oState);
- oState = null;
- }
- else
- {
- deactivated = false;
- }
+ oState = null;
+ }
+ else
+ {
+ deactivated = false;
+ }
- /** If we failed to deactivate then output warning * */
- if (!deactivated) {
+ /** If we failed to deactivate then output warning * */
+ if (!deactivated) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_5a(get_uid(), type());
}
- }
- catch (ObjectStoreException e)
- {
- tsLogger.logger.warn(e);
+ }
+ catch (ObjectStoreException e)
+ {
+ tsLogger.logger.warn(e);
- deactivated = false;
- }
+ deactivated = false;
+ }
- return deactivated;
- }
+ return deactivated;
+ }
- /**
- * Add the current thread to the list of threads associated with this
- * transaction.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Add the current thread to the list of threads associated with this
+ * transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean addChildThread () // current thread
- {
- return addChildThread(Thread.currentThread());
- }
+ public final boolean addChildThread () // current thread
+ {
+ return addChildThread(Thread.currentThread());
+ }
- /**
- * Add the specified thread to the list of threads associated with this
- * transaction.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Add the specified thread to the list of threads associated with this
+ * transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean addChildThread (Thread t)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public final boolean addChildThread (Thread t)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::addChildThread () action "+get_uid()+" adding "+t);
}
- if (t == null)
- return false;
+ if (t == null)
+ return false;
- boolean result = false;
+ boolean result = false;
- criticalStart();
+ criticalStart();
- synchronized (this)
- {
- if (actionStatus <= ActionStatus.ABORTING)
- {
- if (_childThreads == null)
- _childThreads = new Hashtable();
+ synchronized (this)
+ {
+ if (actionStatus <= ActionStatus.ABORTING)
+ {
+ if (_childThreads == null)
+ _childThreads = new Hashtable();
- _childThreads.put(ThreadUtil.getThreadId(t), t); // makes sure so we don't get
- // duplicates
+ _childThreads.put(ThreadUtil.getThreadId(t), t); // makes sure so we don't get
+ // duplicates
- result = true;
- }
- }
+ result = true;
+ }
+ }
- criticalEnd();
+ criticalEnd();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::addChildThread () action "+get_uid()+" adding "+t+" result = "+result);
}
- return result;
- }
+ return result;
+ }
- /*
- * Can be done at any time (Is this correct?)
- */
+ /*
+ * Can be done at any time (Is this correct?)
+ */
- /**
- * Remove a child thread. The current thread is removed.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Remove a child thread. The current thread is removed.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean removeChildThread () // current thread
- {
- return removeChildThread(ThreadUtil.getThreadId());
- }
+ public final boolean removeChildThread () // current thread
+ {
+ return removeChildThread(ThreadUtil.getThreadId());
+ }
- /**
- * Remove the specified thread from the transaction.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Remove the specified thread from the transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean removeChildThread (String threadId)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public final boolean removeChildThread (String threadId)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::removeChildThread () action "+get_uid()+" removing "+threadId);
}
- if (threadId == null)
- return false;
+ if (threadId == null)
+ return false;
- boolean result = false;
+ boolean result = false;
- criticalStart();
+ criticalStart();
- synchronized (this)
- {
- if (_childThreads != null)
- {
- _childThreads.remove(threadId);
- result = true;
- }
- }
+ synchronized (this)
+ {
+ if (_childThreads != null)
+ {
+ _childThreads.remove(threadId);
+ result = true;
+ }
+ }
- criticalEnd();
+ criticalEnd();
- if (tsLogger.logger.isTraceEnabled())
- {
- tsLogger.logger.trace("BasicAction::removeChildThread () action "+get_uid()+" removing "+threadId+" result = "+result);
- }
+ if (tsLogger.logger.isTraceEnabled())
+ {
+ tsLogger.logger.trace("BasicAction::removeChildThread () action "+get_uid()+" removing "+threadId+" result = "+result);
+ }
- return result;
- }
+ return result;
+ }
- /**
- * Add a new child action to the atomic action.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * Add a new child action to the atomic action.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean addChildAction (BasicAction act)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public final boolean addChildAction (BasicAction act)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::addAction () action "+get_uid()+" adding "+((act != null) ? act.get_uid() : Uid.nullUid()));
}
- if (act == null)
- return false;
+ if (act == null)
+ return false;
- boolean result = false;
+ boolean result = false;
- criticalStart();
+ criticalStart();
- synchronized (this)
- {
- /*
- * Must be <= as we sometimes need to do processing during commit
- * phase.
- */
+ synchronized (this)
+ {
+ /*
+ * Must be <= as we sometimes need to do processing during commit
+ * phase.
+ */
- if (actionStatus <= ActionStatus.ABORTING)
- {
- if (_childActions == null)
- _childActions = new Hashtable();
+ if (actionStatus <= ActionStatus.ABORTING)
+ {
+ if (_childActions == null)
+ _childActions = new Hashtable();
- _childActions.put(act, act);
- result = true;
- }
- }
+ _childActions.put(act, act);
+ result = true;
+ }
+ }
- criticalEnd();
+ criticalEnd();
- if (tsLogger.logger.isTraceEnabled())
- {
+ if (tsLogger.logger.isTraceEnabled())
+ {
tsLogger.logger.trace("BasicAction::addChildAction () action "+get_uid()+" adding "+act.get_uid()+" result = "+result);
- }
+ }
- return result;
- }
+ return result;
+ }
- /*
- * Can be done at any time (Is this correct?)
- */
+ /*
+ * Can be done at any time (Is this correct?)
+ */
- /**
+ /**
* Redefined version of save_state and restore_state from StateManager.
- *
+ *
* Normal operation (no crashes):
- *
+ *
* BasicAction.save_state is called after a successful prepare. This causes
* and BasicAction object to be saved in the object store. This object
* contains primarily the "intentions list" of the BasicAction. After
* successfully completing phase 2 of the commit protocol, the BasicAction
* object is deleted from the store.
- *
+ *
* Failure cases:
- *
+ *
* If a server crashes after successfully preparing, then upon recovery the
* action must be resolved (either committed or aborted) depending upon
* whether the co-ordinating atomic action committed or aborted. Upon server
@@ -735,468 +735,468 @@
* in the object store and attempts to activate the BasicAction object of
* the co-ordinating action. If this is successful then the SAA is committed
* else aborted.
- *
+ *
* If, when processing phase 2 of the commit protocol, the co-ordinator
* experiences a failure to commit from one of the records then the
* BasicAction object is NOT deleted. It is rewritten when a new state which
* contains a list of the records that failed during phase 2 commit. This
* list is called the "failedList".
- *
+ *
* The crash recovery manager will detect local BasicAction objects in
* addition to SAA objects in the objectstore. An attempt will be made to
* commit these actions. If the action contained a call to a now dead
* server, this action can never be resolved and the AA object can never be
* removed. However, if the action is purely local then after the processing
* is complete the removed by crash recovery.
- *
+ *
* @return <code>true</code> if successful, <code>false</code>
* otherwise.
*/
-
+
public boolean save_state (OutputObjectState os, int ot)
{
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::save_state ()");
}
-
- try
- {
- packHeader(os, new Header(get_uid(), Utility.getProcessUid()));
- }
- catch (IOException e)
- {
- return false;
- }
-
- /*
- * In a presumed abort scenario, this routine is called: a) After a
- * successful prepare - to save the intentions list. b) After a failure
- * during phase 2 of commit - to overwrite the intentions list by the
- * failedList.
- *
- * If we're using presumed nothing, then it could be called: a) Whenever
- * a participant is registered.
- */
-
- RecordList listToSave = null;
- boolean res = true;
-
- /*
- * If we have a failedList then we are re-writing a BasicAction object
- * after a failure during phase 2 commit
- */
-
- if ((failedList != null) && (failedList.size() > 0))
- {
- listToSave = failedList;
- }
- else
- {
- listToSave = preparedList;
- }
-
- AbstractRecord first = ((listToSave != null) ? listToSave.getFront()
- : null);
- AbstractRecord temp = first;
- boolean havePacked = ((listToSave == null) ? false : true);
-
- while ((res) && (temp != null))
- {
- listToSave.putRear(temp);
-
- /*
- * First check to see if we need to call save_state. If we do then
- * we must first save the record type (and enum) and then save the
- * unique identity of the record (a string). The former is needed to
- * determine what type of record we are restoring, while the latter
- * is required to re-create the actual record.
- */
-
- /*
- * First check to see if we need to call save_state. If we do then
- * we must first save the record type. This is used to determine
- * which type of record to create when restoring.
- */
-
- if (tsLogger.logger.isTraceEnabled())
- {
+
+ try
+ {
+ packHeader(os, new Header(get_uid(), Utility.getProcessUid()));
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+
+ /*
+ * In a presumed abort scenario, this routine is called: a) After a
+ * successful prepare - to save the intentions list. b) After a failure
+ * during phase 2 of commit - to overwrite the intentions list by the
+ * failedList.
+ *
+ * If we're using presumed nothing, then it could be called: a) Whenever
+ * a participant is registered.
+ */
+
+ RecordList listToSave = null;
+ boolean res = true;
+
+ /*
+ * If we have a failedList then we are re-writing a BasicAction object
+ * after a failure during phase 2 commit
+ */
+
+ if ((failedList != null) && (failedList.size() > 0))
+ {
+ listToSave = failedList;
+ }
+ else
+ {
+ listToSave = preparedList;
+ }
+
+ AbstractRecord first = ((listToSave != null) ? listToSave.getFront()
+ : null);
+ AbstractRecord temp = first;
+ boolean havePacked = ((listToSave == null) ? false : true);
+
+ while ((res) && (temp != null))
+ {
+ listToSave.putRear(temp);
+
+ /*
+ * First check to see if we need to call save_state. If we do then
+ * we must first save the record type (and enum) and then save the
+ * unique identity of the record (a string). The former is needed to
+ * determine what type of record we are restoring, while the latter
+ * is required to re-create the actual record.
+ */
+
+ /*
+ * First check to see if we need to call save_state. If we do then
+ * we must first save the record type. This is used to determine
+ * which type of record to create when restoring.
+ */
+
+ if (tsLogger.logger.isTraceEnabled())
+ {
tsLogger.logger.trace("BasicAction::save_state - next record to pack is a "+temp.typeIs()
+" record "+temp.type()+" should save it? = "+temp.doSave());
- }
-
- if (temp.doSave())
- {
- res = true;
-
- try
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ }
+
+ if (temp.doSave())
+ {
+ res = true;
+
+ try
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Packing a "+temp.typeIs()+" record");
}
-
- os.packInt(temp.typeIs());
- res = temp.save_state(os, ot);
- }
- catch (IOException e)
- {
- res = false;
- }
- }
-
- temp = listToSave.getFront();
-
- if (temp == first)
- {
- listToSave.putFront(temp);
- temp = null;
- }
- }
-
- /*
- * If we only ever had a heuristic list (e.g., one-phase commit) then
- * pack a record delimiter.
- */
-
- if (res && (os.notempty() || !havePacked))
- {
- try
- {
- if (tsLogger.logger.isTraceEnabled()) {
+
+ os.packInt(temp.typeIs());
+ res = temp.save_state(os, ot);
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+
+ temp = listToSave.getFront();
+
+ if (temp == first)
+ {
+ listToSave.putFront(temp);
+ temp = null;
+ }
+ }
+
+ /*
+ * If we only ever had a heuristic list (e.g., one-phase commit) then
+ * pack a record delimiter.
+ */
+
+ if (res && (os.notempty() || !havePacked))
+ {
+ try
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Packing a NONE_RECORD");
}
-
- os.packInt(RecordType.NONE_RECORD);
- }
- catch (IOException e)
- {
- res = false;
- }
- }
-
- if (res)
- {
- // Now deal with anything on the heuristic list!
-
- int hSize = ((heuristicList == null) ? 0 : heuristicList.size());
-
- try
- {
- os.packInt(hSize);
- }
- catch (IOException e)
- {
- res = false;
- }
-
- if (res && (hSize > 0))
- {
- first = heuristicList.getFront();
- temp = first;
-
- while (res && (temp != null))
- {
- heuristicList.putRear(temp);
-
- if (temp.doSave())
- {
- res = true;
-
- try
- {
- if (tsLogger.logger.isTraceEnabled()) {
+
+ os.packInt(RecordType.NONE_RECORD);
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+
+ if (res)
+ {
+ // Now deal with anything on the heuristic list!
+
+ int hSize = ((heuristicList == null) ? 0 : heuristicList.size());
+
+ try
+ {
+ os.packInt(hSize);
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+
+ if (res && (hSize > 0))
+ {
+ first = heuristicList.getFront();
+ temp = first;
+
+ while (res && (temp != null))
+ {
+ heuristicList.putRear(temp);
+
+ if (temp.doSave())
+ {
+ res = true;
+
+ try
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("HeuristicList - packing a "+temp.typeIs()+" record");
}
-
- os.packInt(temp.typeIs());
- res = temp.save_state(os, ot);
- }
- catch (IOException e)
- {
- res = false;
- }
- }
-
- temp = heuristicList.getFront();
-
- if (temp == first)
- {
- heuristicList.putFront(temp);
- temp = null;
- }
- }
-
- if (res && os.notempty())
- {
- try
- {
- if (tsLogger.logger.isTraceEnabled()) {
+
+ os.packInt(temp.typeIs());
+ res = temp.save_state(os, ot);
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+
+ temp = heuristicList.getFront();
+
+ if (temp == first)
+ {
+ heuristicList.putFront(temp);
+ temp = null;
+ }
+ }
+
+ if (res && os.notempty())
+ {
+ try
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("HeuristicList - packing a NONE_RECORD");
}
-
- os.packInt(RecordType.NONE_RECORD);
- }
- catch (IOException e)
- {
- res = false;
- }
- }
- }
- }
-
- if (res && os.notempty())
- {
- try
- {
- if (tsLogger.logger.isTraceEnabled()) {
+
+ os.packInt(RecordType.NONE_RECORD);
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+ }
+ }
+
+ if (res && os.notempty())
+ {
+ try
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Packing action status of "+ActionStatus.stringForm(actionStatus));
}
-
- os.packInt(actionStatus);
- os.packInt(actionType); // why pack since only top-level?
- os.packInt(heuristicDecision); // can we optimize?
- }
- catch (IOException e)
- {
- res = false;
- }
- }
-
- return res;
+
+ os.packInt(actionStatus);
+ os.packInt(actionType); // why pack since only top-level?
+ os.packInt(heuristicDecision); // can we optimize?
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+
+ return res;
}
/**
- * Remove a child action.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ * Remove a child action.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public final boolean removeChildAction (BasicAction act)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public final boolean removeChildAction (BasicAction act)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::removeChildAction () action "+get_uid()+" removing "+((act != null) ? act.get_uid() : Uid.nullUid()));
}
- if (act == null)
- return false;
+ if (act == null)
+ return false;
- boolean result = false;
+ boolean result = false;
- criticalStart();
+ criticalStart();
- synchronized (this)
- {
- if (_childActions != null)
- {
- _childActions.remove(act);
- result = true;
- }
- }
+ synchronized (this)
+ {
+ if (_childActions != null)
+ {
+ _childActions.remove(act);
+ result = true;
+ }
+ }
- criticalEnd();
+ criticalEnd();
- if (tsLogger.logger.isTraceEnabled())
- {
+ if (tsLogger.logger.isTraceEnabled())
+ {
tsLogger.logger.trace("BasicAction::removeChildAction () action "+get_uid()+" removing "+act.get_uid()+" result = "+result);
- }
+ }
- return result;
- }
+ return result;
+ }
- /**
- * Add the specified CheckedAction object to this transaction.
- *
- * @see com.arjuna.ats.arjuna.coordinator.CheckedAction
- */
+ /**
+ * Add the specified CheckedAction object to this transaction.
+ *
+ * @see com.arjuna.ats.arjuna.coordinator.CheckedAction
+ */
- protected final synchronized void setCheckedAction (CheckedAction c)
- {
- criticalStart();
+ protected final synchronized void setCheckedAction (CheckedAction c)
+ {
+ criticalStart();
- _checkedAction = c;
+ _checkedAction = c;
- criticalEnd();
- }
+ criticalEnd();
+ }
- /**
- * @return the Uid that the transaction's intentions list will be saved
- * under.
- */
+ /**
+ * @return the Uid that the transaction's intentions list will be saved
+ * under.
+ */
- public Uid getSavingUid ()
- {
- return get_uid();
- }
+ public Uid getSavingUid ()
+ {
+ return get_uid();
+ }
- /**
- * Overloads Object.toString()
- */
+ /**
+ * Overloads Object.toString()
+ */
- public String toString ()
- {
- return new String("BasicAction: " + get_uid() + " status: "
- + ActionStatus.stringForm(actionStatus));
- }
+ public String toString ()
+ {
+ return new String("BasicAction: " + get_uid() + " status: "
+ + ActionStatus.stringForm(actionStatus));
+ }
- /**
- * This assumes the various lists are zero length when it is called.
- *
- * @return <code>true</code> if successful, <code>false</code>
- * otherwise.
- */
+ /**
+ * This assumes the various lists are zero length when it is called.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
- public boolean restore_state (InputObjectState os, int ot)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ public boolean restore_state (InputObjectState os, int ot)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::restore_state ()");
}
- createPreparedLists();
+ createPreparedLists();
- boolean res = true;
- int record_type = RecordType.NONE_RECORD;
- int tempActionStatus = ActionStatus.INVALID;
- int tempActionType = ActionType.TOP_LEVEL;
- int tempHeuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+ boolean res = true;
+ int record_type = RecordType.NONE_RECORD;
+ int tempActionStatus = ActionStatus.INVALID;
+ int tempActionType = ActionType.TOP_LEVEL;
+ int tempHeuristicDecision = TwoPhaseOutcome.PREPARE_OK;
- /*
- * Unpack the prepared list. Note: This may either be a full intentions
- * list or just the failedList, either way, restore it as the prepared
- * list.
- */
+ /*
+ * Unpack the prepared list. Note: This may either be a full intentions
+ * list or just the failedList, either way, restore it as the prepared
+ * list.
+ */
- try
- {
- Header hdr = new Header();
+ try
+ {
+ Header hdr = new Header();
- unpackHeader(os, hdr);
- }
- catch (IOException e)
- {
- return false;
- }
+ unpackHeader(os, hdr);
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
- try
- {
- record_type = os.unpackInt();
+ try
+ {
+ record_type = os.unpackInt();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Unpacked a "+record_type+" record");
}
- }
- catch (IOException e)
- {
- res = false;
- }
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
- while ((res) && (record_type != RecordType.NONE_RECORD))
- {
- AbstractRecord record = AbstractRecord.create(record_type);
+ while ((res) && (record_type != RecordType.NONE_RECORD))
+ {
+ AbstractRecord record = AbstractRecord.create(record_type);
- if (record == null) {
+ if (record == null) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_21(Integer.toString(record_type));
res = false;
}
- else
- res = (record.restore_state(os, ot) && preparedList.insert(record));
+ else
+ res = (record.restore_state(os, ot) && preparedList.insert(record));
- if (res)
- {
- try
- {
- record_type = os.unpackInt();
+ if (res)
+ {
+ try
+ {
+ record_type = os.unpackInt();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Unpacked a "+record_type+" record");
}
- }
- catch (IOException e)
- {
- res = false;
- }
- }
- }
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
+ }
- // Now deal with the heuristic list!
+ // Now deal with the heuristic list!
- int hSize = 0;
+ int hSize = 0;
- if (res)
- {
- try
- {
- hSize = os.unpackInt();
+ if (res)
+ {
+ try
+ {
+ hSize = os.unpackInt();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("HeuristicList - Unpacked heuristic list size of "+hSize);
}
- }
- catch (IOException e)
- {
- res = false;
- }
- }
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ }
- if (hSize > 0)
- {
- try
- {
- record_type = os.unpackInt();
+ if (hSize > 0)
+ {
+ try
+ {
+ record_type = os.unpackInt();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("HeuristicList - Unpacked a "+record_type+" record");
}
- }
- catch (IOException e)
- {
- res = false;
- }
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
- while ((res) && (record_type != RecordType.NONE_RECORD))
- {
- AbstractRecord record = AbstractRecord.create(record_type);
+ while ((res) && (record_type != RecordType.NONE_RECORD))
+ {
+ AbstractRecord record = AbstractRecord.create(record_type);
- try
- {
- res = (record.restore_state(os, ot) && heuristicList.insert(record));
+ try
+ {
+ res = (record.restore_state(os, ot) && heuristicList.insert(record));
- record_type = os.unpackInt();
+ record_type = os.unpackInt();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("HeuristicList - Unpacked a "+record_type+" record");
}
- }
- catch (IOException e)
- {
- res = false;
- }
- catch (final NullPointerException ex) {
+ }
+ catch (IOException e)
+ {
+ res = false;
+ }
+ catch (final NullPointerException ex) {
tsLogger.i18NLogger.warn_coordinator_norecordfound(Integer.toString(record_type));
res = false;
}
- }
- }
+ }
+ }
- if (res)
- {
- try
- {
- tempActionStatus = os.unpackInt();
- tempActionType = os.unpackInt();
- tempHeuristicDecision = os.unpackInt();
- }
- catch (IOException e) {
+ if (res)
+ {
+ try
+ {
+ tempActionStatus = os.unpackInt();
+ tempActionType = os.unpackInt();
+ tempHeuristicDecision = os.unpackInt();
+ }
+ catch (IOException e) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_24();
res = false;
}
- }
+ }
- if (res)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ if (res)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Restored action status of "+ActionStatus.stringForm(tempActionStatus)+
" "+Integer.toString(tempActionStatus));
@@ -1208,93 +1208,93 @@
TwoPhaseOutcome.stringForm(tempHeuristicDecision)+" "+Integer.toString(tempHeuristicDecision));
}
- actionStatus = tempActionStatus;
- actionType = tempActionType;
- heuristicDecision = tempHeuristicDecision;
- savedIntentionList = true;
- }
-
- return res;
- }
+ actionStatus = tempActionStatus;
+ actionType = tempActionType;
+ heuristicDecision = tempHeuristicDecision;
+ savedIntentionList = true;
+ }
- /**
- * Overloads StateManager.type()
- */
+ return res;
+ }
- public String type ()
- {
- return "/StateManager/BasicAction";
- }
+ /**
+ * Overloads StateManager.type()
+ */
- /**
- * @return the thread's notion of the current transaction.
- */
+ public String type ()
+ {
+ return "/StateManager/BasicAction";
+ }
- public static BasicAction Current ()
- {
- return ThreadActionData.currentAction();
- }
+ /**
+ * @return the thread's notion of the current transaction.
+ */
- /**
- * If heuristic outcomes are returned, by default we will not save the state
- * once the forget method has been called on them (which happens as soon as
- * we have received all outcomes from registered resources). By specifying
- * otherwise, we will always maintain the heuristic information, which may
- * prove useful for logging and off-line resolution.
- *
- * @return <code>true</code> if the transaction should save its heuristic
- * information, <code>false</code> otherwise.
- */
+ public static BasicAction Current ()
+ {
+ return ThreadActionData.currentAction();
+ }
- public static boolean maintainHeuristics ()
- {
- return TxControl.maintainHeuristics;
- }
+ /**
+ * If heuristic outcomes are returned, by default we will not save the state
+ * once the forget method has been called on them (which happens as soon as
+ * we have received all outcomes from registered resources). By specifying
+ * otherwise, we will always maintain the heuristic information, which may
+ * prove useful for logging and off-line resolution.
+ *
+ * @return <code>true</code> if the transaction should save its heuristic
+ * information, <code>false</code> otherwise.
+ */
- /**
- * Overloads <code>StateManager.destroy</code> to prevent destroy being
- * called on a BasicAction. Could be a *very* bad idea!!
- *
- * @return <code>false</code>.
- * @see com.arjuna.ats.arjuna.StateManager
- */
+ public static boolean maintainHeuristics ()
+ {
+ return TxControl.maintainHeuristics;
+ }
- public boolean destroy ()
- {
- return true;
- }
+ /**
+ * Overloads <code>StateManager.destroy</code> to prevent destroy being
+ * called on a BasicAction. Could be a *very* bad idea!!
+ *
+ * @return <code>false</code>.
+ * @see com.arjuna.ats.arjuna.StateManager
+ */
- /**
- * @return the list of child transactions. Currently only their ids are
- * given.
- * @since JTS 2.2.
- */
+ public boolean destroy ()
+ {
+ return true;
+ }
- public final Object[] childTransactions ()
- {
- int size = ((_childActions == null) ? 0 : _childActions.size());
+ /**
+ * @return the list of child transactions. Currently only their ids are
+ * given.
+ * @since JTS 2.2.
+ */
- if (size > 0)
- {
- Collection c = _childActions.values();
+ public final Object[] childTransactions ()
+ {
+ int size = ((_childActions == null) ? 0 : _childActions.size());
- return c.toArray();
- }
+ if (size > 0)
+ {
+ Collection c = _childActions.values();
- return null;
- }
+ return c.toArray();
+ }
+ return null;
+ }
+
@Override
- public boolean equals (java.lang.Object obj)
- {
- if (obj instanceof BasicAction)
- {
- if (((BasicAction) obj).get_uid().equals(get_uid()))
- return true;
- }
+ public boolean equals (java.lang.Object obj)
+ {
+ if (obj instanceof BasicAction)
+ {
+ if (((BasicAction) obj).get_uid().equals(get_uid()))
+ return true;
+ }
- return false;
- }
+ return false;
+ }
@Override
public int hashCode()
@@ -1303,46 +1303,46 @@
}
/**
- * Forget any heuristics we may have received, and tell the resources which
- * generated them to forget too.
- *
- * @return <code>true</code> if heuristic information (if any) was
- * successfully forgotten, <code>false</code> otherwise.
- */
+ * Forget any heuristics we may have received, and tell the resources which
+ * generated them to forget too.
+ *
+ * @return <code>true</code> if heuristic information (if any) was
+ * successfully forgotten, <code>false</code> otherwise.
+ */
- protected boolean forgetHeuristics ()
- {
- if ((heuristicList != null) && (heuristicList.size() > 0))
- {
- doForget(heuristicList);
- updateState();
+ protected boolean forgetHeuristics ()
+ {
+ if ((heuristicList != null) && (heuristicList.size() > 0))
+ {
+ doForget(heuristicList);
+ updateState();
- if (heuristicList.size() == 0)
- return true;
- else
- return false;
- }
- else
- return true;
- }
+ if (heuristicList.size() == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return true;
+ }
- /**
- * Atomic action Begin operation. Does not change the calling thread's
- * notion of the current transaction.
- *
- * @return <code>ActionStatus</code> indicating outcome.
- */
+ /**
+ * Atomic action Begin operation. Does not change the calling thread's
+ * notion of the current transaction.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
- protected synchronized int Begin (BasicAction parentAct)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected synchronized int Begin (BasicAction parentAct)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::Begin() for action-id "
+ get_uid());
}
-
- // check to see if transaction system is enabled
-
- if (!TxControl.isEnabled()) {
+
+ // check to see if transaction system is enabled
+
+ if (!TxControl.isEnabled()) {
/*
* Prevent transaction from making forward progress.
*/
@@ -1351,76 +1351,76 @@
tsLogger.i18NLogger.warn_coordinator_notrunning();
}
- else
- {
- if (actionStatus != ActionStatus.CREATED) {
+ else
+ {
+ if (actionStatus != ActionStatus.CREATED) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_29(get_uid(), ActionStatus.stringForm(actionStatus));
}
- else
- {
- actionInitialise(parentAct);
- actionStatus = ActionStatus.RUNNING;
+ else
+ {
+ actionInitialise(parentAct);
+ actionStatus = ActionStatus.RUNNING;
- if ((actionType != ActionType.TOP_LEVEL)
- && ((parentAct == null) || (parentAct.status() > ActionStatus.RUNNING)))
- {
- actionStatus = ActionStatus.ABORT_ONLY;
+ if ((actionType != ActionType.TOP_LEVEL)
+ && ((parentAct == null) || (parentAct.status() > ActionStatus.RUNNING)))
+ {
+ actionStatus = ActionStatus.ABORT_ONLY;
- if (parentAct == null) {
+ if (parentAct == null) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_30(get_uid());
}
- else
- {
- tsLogger.i18NLogger.warn_coordinator_BasicAction_31(get_uid(), parentAct.get_uid(), Integer.toString(parentAct.status()));
- }
- }
+ else
+ {
+ tsLogger.i18NLogger.warn_coordinator_BasicAction_31(get_uid(), parentAct.get_uid(), Integer.toString(parentAct.status()));
+ }
+ }
- ActionManager.manager().put(this);
+ ActionManager.manager().put(this);
- if (TxStats.enabled())
- {
- TxStats.getInstance().incrementTransactions();
+ if (TxStats.enabled())
+ {
+ TxStats.getInstance().incrementTransactions();
- if (parentAct != null)
- TxStats.getInstance().incrementNestedTransactions();
- }
- }
- }
+ if (parentAct != null)
+ TxStats.getInstance().incrementNestedTransactions();
+ }
+ }
+ }
- return actionStatus;
- }
+ return actionStatus;
+ }
- /**
- * End the atomic action by committing it. This invokes the prepare()
- * operation. If this succeeds then the pendingList should be empty and the
- * records that were formally on it will have been distributed between the
- * preparedList and the readonlyList, also if the action is topLevel then
- * the intention list will have been written to the object store. Then
- * invoke phase2Commit and clean up the object store if necessary
- *
- * If prepare() fails invoke phase2Abort. In this case the pendingList may
- * still contain records but phase2Abort takes care of these. Also in this
- * case no intention list has been written.
- *
- * Does not change the calling thread's notion of the current transaction.
- *
- * Any heuristic outcomes will only be reported if the parameter is
- * <code>true</code>.
- *
- * @return <code>ActionStatus</code> indicating outcome.
- */
+ /**
+ * End the atomic action by committing it. This invokes the prepare()
+ * operation. If this succeeds then the pendingList should be empty and the
+ * records that were formally on it will have been distributed between the
+ * preparedList and the readonlyList, also if the action is topLevel then
+ * the intention list will have been written to the object store. Then
+ * invoke phase2Commit and clean up the object store if necessary
+ *
+ * If prepare() fails invoke phase2Abort. In this case the pendingList may
+ * still contain records but phase2Abort takes care of these. Also in this
+ * case no intention list has been written.
+ *
+ * Does not change the calling thread's notion of the current transaction.
+ *
+ * Any heuristic outcomes will only be reported if the parameter is
+ * <code>true</code>.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
- protected synchronized int End (boolean reportHeuristics)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected synchronized int End (boolean reportHeuristics)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::End() for action-id "
+ get_uid());
}
- /* Check for superfluous invocation */
+ /* Check for superfluous invocation */
- if ((actionStatus != ActionStatus.RUNNING)
- && (actionStatus != ActionStatus.ABORT_ONLY)) {
+ if ((actionStatus != ActionStatus.RUNNING)
+ && (actionStatus != ActionStatus.ABORT_ONLY)) {
switch (actionStatus) {
case ActionStatus.CREATED:
tsLogger.i18NLogger.warn_coordinator_BasicAction_33(get_uid());
@@ -1436,33 +1436,33 @@
return actionStatus;
}
- /*
- * Check we are the current action. Abort parents if not true. Check we
- * have not children (threads or actions).
- */
+ /*
+ * Check we are the current action. Abort parents if not true. Check we
+ * have not children (threads or actions).
+ */
- if (!checkIsCurrent() || checkChildren(true)
- || (actionStatus == ActionStatus.ABORT_ONLY))
- {
- return Abort();
- }
-
- if (pendingList != null)
- {
- /*
- * If we only have a single item on the prepare list then we can try
- * to commit in a single phase.
- */
+ if (!checkIsCurrent() || checkChildren(true)
+ || (actionStatus == ActionStatus.ABORT_ONLY))
+ {
+ return Abort();
+ }
- if (doOnePhase())
- {
- onePhaseCommit(reportHeuristics);
-
- ActionManager.manager().remove(get_uid());
- }
- else
- {
- if (prepare(reportHeuristics) == TwoPhaseOutcome.PREPARE_NOTOK) {
+ if (pendingList != null)
+ {
+ /*
+ * If we only have a single item on the prepare list then we can try
+ * to commit in a single phase.
+ */
+
+ if (doOnePhase())
+ {
+ onePhaseCommit(reportHeuristics);
+
+ ActionManager.manager().remove(get_uid());
+ }
+ else
+ {
+ if (prepare(reportHeuristics) == TwoPhaseOutcome.PREPARE_NOTOK) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_36(get_uid());
if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK) {
@@ -1477,102 +1477,102 @@
} else
phase2Abort(reportHeuristics); /* first phase failed */
}
- else
- {
- if (!reportHeuristics && TxControl.asyncCommit
- && (parentAction == null))
- {
- AsyncCommit.create(this, true);
- }
- else
- phase2Commit(reportHeuristics); /* first phase succeeded */
- }
- }
- }
- else
- {
- ActionManager.manager().remove(get_uid());
+ else
+ {
+ if (!reportHeuristics && TxControl.asyncCommit
+ && (parentAction == null))
+ {
+ AsyncCommit.create(this, true);
+ }
+ else
+ phase2Commit(reportHeuristics); /* first phase succeeded */
+ }
+ }
+ }
+ else
+ {
+ ActionManager.manager().remove(get_uid());
- actionStatus = ActionStatus.COMMITTED;
+ actionStatus = ActionStatus.COMMITTED;
- if (TxStats.enabled())
- {
- if (heuristicDecision != TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- {
- TxStats.getInstance().incrementCommittedTransactions();
- }
- }
- }
+ if (TxStats.enabled())
+ {
+ if (heuristicDecision != TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ {
+ TxStats.getInstance().incrementCommittedTransactions();
+ }
+ }
+ }
- boolean returnCurrentStatus = false;
+ boolean returnCurrentStatus = false;
- if (reportHeuristics || (!reportHeuristics && !TxControl.asyncCommit))
- returnCurrentStatus = true;
+ if (reportHeuristics || (!reportHeuristics && !TxControl.asyncCommit))
+ returnCurrentStatus = true;
- if (returnCurrentStatus)
- {
- if (reportHeuristics)
- {
- switch (heuristicDecision)
- {
- case TwoPhaseOutcome.PREPARE_OK:
- case TwoPhaseOutcome.FINISH_OK:
- break;
- case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
- return ActionStatus.H_ROLLBACK;
- case TwoPhaseOutcome.HEURISTIC_COMMIT:
- return ActionStatus.H_COMMIT;
- case TwoPhaseOutcome.HEURISTIC_MIXED:
- return ActionStatus.H_MIXED;
- case TwoPhaseOutcome.HEURISTIC_HAZARD:
- default:
- return ActionStatus.H_HAZARD;
- }
- }
+ if (returnCurrentStatus)
+ {
+ if (reportHeuristics)
+ {
+ switch (heuristicDecision)
+ {
+ case TwoPhaseOutcome.PREPARE_OK:
+ case TwoPhaseOutcome.FINISH_OK:
+ break;
+ case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
+ return ActionStatus.H_ROLLBACK;
+ case TwoPhaseOutcome.HEURISTIC_COMMIT:
+ return ActionStatus.H_COMMIT;
+ case TwoPhaseOutcome.HEURISTIC_MIXED:
+ return ActionStatus.H_MIXED;
+ case TwoPhaseOutcome.HEURISTIC_HAZARD:
+ default:
+ return ActionStatus.H_HAZARD;
+ }
+ }
- /*
- * If we have a heuristic decision then we only report it
- * if required. Otherwise we return committed as per OTS rules.
- */
-
- switch (actionStatus)
- {
- case ActionStatus.H_COMMIT:
- case ActionStatus.H_ROLLBACK:
- case ActionStatus.H_HAZARD:
- case ActionStatus.H_MIXED:
- if (!reportHeuristics)
- return ActionStatus.COMMITTED;
- default:
- return actionStatus;
- }
- }
- else
- return ActionStatus.COMMITTING; // if asynchronous then fake it.
- }
+ /*
+ * If we have a heuristic decision then we only report it
+ * if required. Otherwise we return committed as per OTS rules.
+ */
- /**
- * This is the user callable abort operation. It is invoked prior to the
- * start of two-phase commit and hence only processes records in the
- * pendingList (the other lists should be empty).
- *
- * Does not change the calling thread's notion of the current transaction.
- *
- * @return <code>ActionStatus</code> indicating outcome.
- */
+ switch (actionStatus)
+ {
+ case ActionStatus.H_COMMIT:
+ case ActionStatus.H_ROLLBACK:
+ case ActionStatus.H_HAZARD:
+ case ActionStatus.H_MIXED:
+ if (!reportHeuristics)
+ return ActionStatus.COMMITTED;
+ default:
+ return actionStatus;
+ }
+ }
+ else
+ return ActionStatus.COMMITTING; // if asynchronous then fake it.
+ }
- protected synchronized int Abort ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ /**
+ * This is the user callable abort operation. It is invoked prior to the
+ * start of two-phase commit and hence only processes records in the
+ * pendingList (the other lists should be empty).
+ *
+ * Does not change the calling thread's notion of the current transaction.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ protected synchronized int Abort ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::Abort() for action-id "
+ get_uid());
}
- /* Check for superfluous invocation */
+ /* Check for superfluous invocation */
- if ((actionStatus != ActionStatus.RUNNING)
- && (actionStatus != ActionStatus.ABORT_ONLY)
- && (actionStatus != ActionStatus.COMMITTING)) {
+ if ((actionStatus != ActionStatus.RUNNING)
+ && (actionStatus != ActionStatus.ABORT_ONLY)
+ && (actionStatus != ActionStatus.COMMITTING)) {
switch (actionStatus) {
case ActionStatus.CREATED:
tsLogger.i18NLogger.warn_coordinator_BasicAction_39(get_uid());
@@ -1588,270 +1588,270 @@
return actionStatus;
}
- /*
- * Check we are the current action. Abort parents if not true. Some
- * implementations may want to override this.
- */
+ /*
+ * Check we are the current action. Abort parents if not true. Some
+ * implementations may want to override this.
+ */
- checkIsCurrent();
+ checkIsCurrent();
- /*
- * Check we have no children (threads or actions).
- */
+ /*
+ * Check we have no children (threads or actions).
+ */
- checkChildren(false);
+ checkChildren(false);
- if (pendingList != null)
- {
- actionStatus = ActionStatus.ABORTING;
+ if (pendingList != null)
+ {
+ actionStatus = ActionStatus.ABORTING;
- while (pendingList.size() > 0)
- doAbort(pendingList, false); // turn off heuristics reporting
+ while (pendingList.size() > 0)
+ doAbort(pendingList, false); // turn off heuristics reporting
- /*
- * In case we get here because an End has failed. In this case we
- * still need to tell the heuristic resources to forget their
- * decision.
- */
+ /*
+ * In case we get here because an End has failed. In this case we
+ * still need to tell the heuristic resources to forget their
+ * decision.
+ */
- forgetHeuristics();
- }
+ forgetHeuristics();
+ }
- ActionManager.manager().remove(get_uid());
+ ActionManager.manager().remove(get_uid());
- actionStatus = ActionStatus.ABORTED;
+ actionStatus = ActionStatus.ABORTED;
- if (TxStats.enabled())
- TxStats.getInstance().incrementAbortedTransactions();
+ if (TxStats.enabled())
+ TxStats.getInstance().incrementAbortedTransactions();
- return actionStatus;
- }
+ return actionStatus;
+ }
- /**
- * Create a transaction of the specified type.
- */
+ /**
+ * Create a transaction of the specified type.
+ */
- protected BasicAction (int at)
- {
- super(ObjectType.NEITHER);
+ protected BasicAction (int at)
+ {
+ super(ObjectType.NEITHER);
- pendingList = null;
- preparedList = null;
- readonlyList = null;
- failedList = null;
- heuristicList = null;
+ pendingList = null;
+ preparedList = null;
+ readonlyList = null;
+ failedList = null;
+ heuristicList = null;
- currentHierarchy = null;
- participantStore = null;
- savedIntentionList = false;
+ currentHierarchy = null;
+ participantStore = null;
+ savedIntentionList = false;
- actionStatus = ActionStatus.CREATED;
- actionType = at;
- parentAction = null;
- recordBeingHandled = null;
+ actionStatus = ActionStatus.CREATED;
+ actionType = at;
+ parentAction = null;
+ recordBeingHandled = null;
- heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
- _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
+ heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+ _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
- _childThreads = null;
- _childActions = null;
- }
+ _childThreads = null;
+ _childActions = null;
+ }
- /**
- * Recreate the specified transaction. Used for crash recovery purposes.
- */
+ /**
+ * Recreate the specified transaction. Used for crash recovery purposes.
+ */
- protected BasicAction (Uid u, int at)
- {
- super(u, ObjectType.NEITHER);
+ protected BasicAction (Uid u, int at)
+ {
+ super(u, ObjectType.NEITHER);
- pendingList = null;
- preparedList = null;
- readonlyList = null;
- failedList = null;
- heuristicList = null;
+ pendingList = null;
+ preparedList = null;
+ readonlyList = null;
+ failedList = null;
+ heuristicList = null;
- currentHierarchy = null;
- participantStore = null;
- savedIntentionList = false;
+ currentHierarchy = null;
+ participantStore = null;
+ savedIntentionList = false;
- actionStatus = ActionStatus.CREATED;
- actionType = at;
- parentAction = null;
- recordBeingHandled = null;
+ actionStatus = ActionStatus.CREATED;
+ actionType = at;
+ parentAction = null;
+ recordBeingHandled = null;
- heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
- _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
+ heuristicDecision = TwoPhaseOutcome.PREPARE_OK;
+ _checkedAction = _checkedActionFactory.getCheckedAction(get_uid(), type());
- _childThreads = null;
- _childActions = null;
- }
+ _childThreads = null;
+ _childActions = null;
+ }
- /**
- * Defines the start of a critical region by setting the critical flag. If
- * the signal handler is called the class variable abortAndExit is set. The
- * value of this variable is checked in the corresponding operation to end
- * the critical region.
- */
+ /**
+ * Defines the start of a critical region by setting the critical flag. If
+ * the signal handler is called the class variable abortAndExit is set. The
+ * value of this variable is checked in the corresponding operation to end
+ * the critical region.
+ */
- protected final void criticalStart ()
- {
- // _lock.lock();
- }
+ protected final void criticalStart ()
+ {
+ // _lock.lock();
+ }
- /**
- * Defines the end of a critical region by resetting the critical flag. If
- * the signal handler is called the class variable abortAndExit is set. The
- * value of this variable is checked when ending the critical region.
- */
+ /**
+ * Defines the end of a critical region by resetting the critical flag. If
+ * the signal handler is called the class variable abortAndExit is set. The
+ * value of this variable is checked when ending the critical region.
+ */
- protected final void criticalEnd ()
- {
- // _lock.unlock();
- }
+ protected final void criticalEnd ()
+ {
+ // _lock.unlock();
+ }
- /**
- * Cleanup phase for actions. If an action is in the PREPARED state when a
- * terminate signal is delivered (ie the coordinator node has crashed) then
- * we need to cleanup. This is essentially the same as phase2Abort but we
- * call cleanup ops rather than abort ops and let the records take care of
- * appropriate cleanup.
- *
- * The pendingList is processed because it may not be empty - since
- * prepare() stops processing the list at the first PREPARE_NOTOK result.
- *
- * The read_only list is processed to ensure that actions are aborted
- * immediately and any servers killed at that point since they need not hang
- * around. This contrasts with commit where readonlyList entries are simply
- * merged with the parent list or discarded
- */
+ /**
+ * Cleanup phase for actions. If an action is in the PREPARED state when a
+ * terminate signal is delivered (ie the coordinator node has crashed) then
+ * we need to cleanup. This is essentially the same as phase2Abort but we
+ * call cleanup ops rather than abort ops and let the records take care of
+ * appropriate cleanup.
+ *
+ * The pendingList is processed because it may not be empty - since
+ * prepare() stops processing the list at the first PREPARE_NOTOK result.
+ *
+ * The read_only list is processed to ensure that actions are aborted
+ * immediately and any servers killed at that point since they need not hang
+ * around. This contrasts with commit where readonlyList entries are simply
+ * merged with the parent list or discarded
+ */
- protected final synchronized void phase2Cleanup ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected final synchronized void phase2Cleanup ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::phase2Cleanup() for action-id "
+ get_uid());
}
- criticalStart();
+ criticalStart();
- actionStatus = ActionStatus.CLEANUP;
+ actionStatus = ActionStatus.CLEANUP;
- while ((preparedList != null) && (preparedList.size() > 0))
- doCleanup(preparedList);
+ while ((preparedList != null) && (preparedList.size() > 0))
+ doCleanup(preparedList);
- while ((readonlyList != null) && (readonlyList.size() > 0))
- doCleanup(readonlyList);
+ while ((readonlyList != null) && (readonlyList.size() > 0))
+ doCleanup(readonlyList);
- while ((pendingList != null) && (pendingList.size() > 0))
- doCleanup(pendingList);
+ while ((pendingList != null) && (pendingList.size() > 0))
+ doCleanup(pendingList);
- criticalEnd();
- }
+ criticalEnd();
+ }
- /**
- * Second phase of the two-phase commit protocol for committing actions.
- * This operation first invokes the doCommit operation on the preparedList.
- * This ensures that the appropriate commit operation is performed on each
- * entry which is then either deleted (top_level) or merged into the
- * parent's pendingList.
- *
- * Processing of the readonlyList is different in that if the action is
- * top_level then all records in the readonlyList are deleted without
- * further processing. If nested the records must be merged. This is an
- * optimisation to avoid unnecessary processing.
- *
- * Note that at this point the pendingList SHOULD be empty due to the prior
- * invocation of prepare().
- */
+ /**
+ * Second phase of the two-phase commit protocol for committing actions.
+ * This operation first invokes the doCommit operation on the preparedList.
+ * This ensures that the appropriate commit operation is performed on each
+ * entry which is then either deleted (top_level) or merged into the
+ * parent's pendingList.
+ *
+ * Processing of the readonlyList is different in that if the action is
+ * top_level then all records in the readonlyList are deleted without
+ * further processing. If nested the records must be merged. This is an
+ * optimisation to avoid unnecessary processing.
+ *
+ * Note that at this point the pendingList SHOULD be empty due to the prior
+ * invocation of prepare().
+ */
- protected synchronized final void phase2Commit (boolean reportHeuristics)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected synchronized final void phase2Commit (boolean reportHeuristics)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::phase2Commit() for action-id "
+ get_uid());
}
- if ((pendingList != null) && (pendingList.size() > 0)) {
+ if ((pendingList != null) && (pendingList.size() > 0)) {
int size = ((pendingList == null) ? 0 : pendingList.size());
tsLogger.i18NLogger.warn_coordinator_BasicAction_42(get_uid(), Integer.toString(size), pendingList.toString());
phase2Abort(reportHeuristics);
}
- else
- {
- criticalStart();
+ else
+ {
+ criticalStart();
- actionStatus = ActionStatus.COMMITTING;
+ actionStatus = ActionStatus.COMMITTING;
- /*
- * If we get a heuristic during commit then we continue to commit
- * since we may have already told some records to commit. We could
- * optimise this if the first record raises the heuristic by
- * aborting (or going with the heuristic decision).
- */
+ /*
+ * If we get a heuristic during commit then we continue to commit
+ * since we may have already told some records to commit. We could
+ * optimise this if the first record raises the heuristic by
+ * aborting (or going with the heuristic decision).
+ */
- doCommit(preparedList, reportHeuristics); /*
+ doCommit(preparedList, reportHeuristics); /*
* process the
* preparedList
*/
- /*
- * Now check any heuristic decision. If we received one then we may
- * have to raise HEURISTIC_MIXED since we will have committed some
- * resources, whereas others may have aborted.
- */
+ /*
+ * Now check any heuristic decision. If we received one then we may
+ * have to raise HEURISTIC_MIXED since we will have committed some
+ * resources, whereas others may have aborted.
+ */
- if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK)
- {
- /*
- * Heuristic decision matched the actual outcome!
- */
+ if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK)
+ {
+ /*
+ * Heuristic decision matched the actual outcome!
+ */
- if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
- heuristicDecision = TwoPhaseOutcome.FINISH_OK;
- }
+ if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
+ heuristicDecision = TwoPhaseOutcome.FINISH_OK;
+ }
- /* The readonlyList requires special attention */
+ /* The readonlyList requires special attention */
- if ((readonlyList != null) && (readonlyList.size() > 0))
- {
- if (!TxControl.readonlyOptimisation)
- {
- if (readonlyList != null)
- doCommit(readonlyList, reportHeuristics);
- }
+ if ((readonlyList != null) && (readonlyList.size() > 0))
+ {
+ if (!TxControl.readonlyOptimisation)
+ {
+ if (readonlyList != null)
+ doCommit(readonlyList, reportHeuristics);
+ }
- // now still process the list.
-
- while (((recordBeingHandled = readonlyList.getFront()) != null))
- {
- if ((actionType == ActionType.NESTED)
- && (recordBeingHandled.propagateOnCommit()))
- {
- merge(recordBeingHandled);
- }
- else
- {
- recordBeingHandled = null;
- }
- }
- }
+ // now still process the list.
- forgetHeuristics();
+ while (((recordBeingHandled = readonlyList.getFront()) != null))
+ {
+ if ((actionType == ActionType.NESTED)
+ && (recordBeingHandled.propagateOnCommit()))
+ {
+ merge(recordBeingHandled);
+ }
+ else
+ {
+ recordBeingHandled = null;
+ }
+ }
+ }
- actionStatus = ActionStatus.COMMITTED;
+ forgetHeuristics();
- updateState();
+ actionStatus = ActionStatus.COMMITTED;
- ActionManager.manager().remove(get_uid());
-
- criticalEnd();
+ updateState();
+ ActionManager.manager().remove(get_uid());
+
+ criticalEnd();
+
// ok count this as a commit unless we got a heuristic rollback in which case phase2Abort
// will have been called and will already have counted it as an abort
-
+
if (TxStats.enabled()) {
if (heuristicDecision != TwoPhaseOutcome.HEURISTIC_ROLLBACK) {
TxStats.getInstance().incrementCommittedTransactions();
@@ -1859,101 +1859,101 @@
}
}
- }
+ }
- /**
- * Second phase of the two phase commit protocol for aborting actions.
- * Actions are aborted by invoking the doAbort operation on the
- * preparedList, the readonlyList, and the pendingList.
- *
- * The pendingList is processed because it may not be empty - since
- * prepare() stops processing the list at the first PREPARE_NOTOK result.
- *
- * By default, records that responsed PREPARE_READONLY will not be contacted
- * during second-phase abort, just as they are not during second-phase
- * commit. This can be overridden at runtime using the READONLY_OPTIMISATION
- * variable.
- */
+ /**
+ * Second phase of the two phase commit protocol for aborting actions.
+ * Actions are aborted by invoking the doAbort operation on the
+ * preparedList, the readonlyList, and the pendingList.
+ *
+ * The pendingList is processed because it may not be empty - since
+ * prepare() stops processing the list at the first PREPARE_NOTOK result.
+ *
+ * By default, records that responsed PREPARE_READONLY will not be contacted
+ * during second-phase abort, just as they are not during second-phase
+ * commit. This can be overridden at runtime using the READONLY_OPTIMISATION
+ * variable.
+ */
- protected synchronized final void phase2Abort (boolean reportHeuristics)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected synchronized final void phase2Abort (boolean reportHeuristics)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::phase2Abort() for action-id "
+ get_uid());
}
- criticalStart();
+ criticalStart();
- actionStatus = ActionStatus.ABORTING;
+ actionStatus = ActionStatus.ABORTING;
- if (preparedList != null)
- doAbort(preparedList, reportHeuristics);
+ if (preparedList != null)
+ doAbort(preparedList, reportHeuristics);
- if (!TxControl.readonlyOptimisation)
- {
- if (readonlyList != null)
- doAbort(readonlyList, reportHeuristics);
- }
+ if (!TxControl.readonlyOptimisation)
+ {
+ if (readonlyList != null)
+ doAbort(readonlyList, reportHeuristics);
+ }
- if (pendingList != null)
- doAbort(pendingList, reportHeuristics);
+ if (pendingList != null)
+ doAbort(pendingList, reportHeuristics);
- /*
- * Check heuristic decision, and try to make it match outcome.
- */
+ /*
+ * Check heuristic decision, and try to make it match outcome.
+ */
- if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK)
- {
- if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- heuristicDecision = TwoPhaseOutcome.FINISH_OK;
- }
+ if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK)
+ {
+ if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ heuristicDecision = TwoPhaseOutcome.FINISH_OK;
+ }
- forgetHeuristics();
+ forgetHeuristics();
- actionStatus = abortStatus();
+ actionStatus = abortStatus();
- updateState(); // we may end up saving more than the heuristic list
- // here!
+ updateState(); // we may end up saving more than the heuristic list
+ // here!
- ActionManager.manager().remove(get_uid());
-
- criticalEnd();
-
- /*
- * To get to this stage we had to try to commit, which means that we're
- * rolling back because of a resource problem.
- */
-
- if (TxStats.enabled()) {
+ ActionManager.manager().remove(get_uid());
+
+ criticalEnd();
+
+ /*
+ * To get to this stage we had to try to commit, which means that we're
+ * rolling back because of a resource problem.
+ */
+
+ if (TxStats.enabled()) {
TxStats.getInstance().incrementResourceRollbacks();
TxStats.getInstance().incrementAbortedTransactions();
}
}
- /**
- * Phase one of a two phase commit protocol. This function returns the
- * ouctome of the prepare operation. If all goes well it will be PREPARE_OK,
- * if not PREPARE_NOTOK. The value PREPARE_READONLY may also be returned if
- * all the records indicate that they are readonly records. Such records do
- * not take part in the second phase commit processing.
- *
- * @return <code>TwoPhaseOutcome</code> indicating outcome.
- */
+ /**
+ * Phase one of a two phase commit protocol. This function returns the
+ * ouctome of the prepare operation. If all goes well it will be PREPARE_OK,
+ * if not PREPARE_NOTOK. The value PREPARE_READONLY may also be returned if
+ * all the records indicate that they are readonly records. Such records do
+ * not take part in the second phase commit processing.
+ *
+ * @return <code>TwoPhaseOutcome</code> indicating outcome.
+ */
- protected synchronized final int prepare (boolean reportHeuristics)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected synchronized final int prepare (boolean reportHeuristics)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::prepare () for action-id "
+ get_uid());
}
- boolean commitAllowed = (actionStatus != ActionStatus.ABORT_ONLY);
+ boolean commitAllowed = (actionStatus != ActionStatus.ABORT_ONLY);
- actionStatus = ActionStatus.PREPARING;
+ actionStatus = ActionStatus.PREPARING;
- /* If we cannot commit - say the prepare failed */
+ /* If we cannot commit - say the prepare failed */
- if (!commitAllowed) {
+ if (!commitAllowed) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_43(get_uid());
actionStatus = ActionStatus.PREPARED;
@@ -1961,256 +1961,236 @@
return TwoPhaseOutcome.PREPARE_NOTOK;
}
- /*
- * Make sure the object store is set up for a top-level atomic action.
- */
+ /*
+ * Make sure the object store is set up for a top-level atomic action.
+ */
- if (actionType == ActionType.TOP_LEVEL)
- {
- if (getStore() == null)
- {
- actionStatus = ActionStatus.ABORT_ONLY;
+ if (actionType == ActionType.TOP_LEVEL)
+ {
+ if (getStore() == null)
+ {
+ actionStatus = ActionStatus.ABORT_ONLY;
- return TwoPhaseOutcome.PREPARE_NOTOK;
- }
- }
+ return TwoPhaseOutcome.PREPARE_NOTOK;
+ }
+ }
- criticalStart();
+ criticalStart();
- createPreparedLists();
+ createPreparedLists();
- /*
- * Here is the start of the hard work. Walk down the pendingList
- * invoking the appropriate prepare operation. If it succeeds put the
- * record on either the preparedList or the read_only list and continue
- * until the pendingList is exhausted.
- *
- * If prepare fails on any record stop processing immediately and put
- * the offending record back on the pendingList
- */
+ /*
+ * Here is the start of the hard work. Walk down the pendingList
+ * invoking the appropriate prepare operation. If it succeeds put the
+ * record on either the preparedList or the read_only list and continue
+ * until the pendingList is exhausted.
+ *
+ * If prepare fails on any record stop processing immediately and put
+ * the offending record back on the pendingList
+ */
- int p = TwoPhaseOutcome.PREPARE_OK;
+ int p = TwoPhaseOutcome.PREPARE_OK;
- /*
- * If asynchronous prepare, then spawn a separate thread to handle each
- * entry in the intentions list. Could have some configurable option to
- * allow more limited number of threads to divide up the intentions
- * list.
- */
+ /*
+ * If asynchronous prepare, then spawn a separate thread to handle each
+ * entry in the intentions list. Could have some configurable option to
+ * allow more limited number of threads to divide up the intentions
+ * list.
+ */
- if ((actionType == ActionType.TOP_LEVEL) && (TxControl.asyncPrepare))
- {
- int numberOfThreads = ((pendingList != null) ? pendingList.size()
- : 0);
- Thread[] threads = new Thread[numberOfThreads];
- int i;
+ if ((actionType == ActionType.TOP_LEVEL) && (TxControl.asyncPrepare))
+ {
+ int numberOfThreads = ((pendingList != null) ? pendingList.size()
+ : 0);
+ Thread[] threads = new Thread[numberOfThreads];
+ int i;
- /*
- * First create them in a suspended way, so that we can purge the
- * list before it is added to (in the event of failures!)
- */
+ /*
+ * First create them in a suspended way, so that we can purge the
+ * list before it is added to (in the event of failures!)
+ */
- for (i = 0; i < numberOfThreads; i++)
- {
- threads[i] = AsyncPrepare.create(this, reportHeuristics, pendingList.getFront());
- }
+ for (i = 0; i < numberOfThreads; i++)
+ {
+ threads[i] = AsyncPrepare.create(this, reportHeuristics, pendingList.getFront());
+ }
- /*
- * Now start the threads running.
- */
+ /*
+ * Now start the threads running.
+ */
- for (i = 0; i < numberOfThreads; i++)
- {
- threads[i].start();
- Thread.yield();
- }
+ for (i = 0; i < numberOfThreads; i++)
+ {
+ threads[i].start();
+ Thread.yield();
+ }
- /*
- * If one of these threads fails (PREPARE_NOTOK) do we terminate the
- * others or simply let them finish? Currently we wait and let them
- * all terminate regardless.
- */
+ /*
+ * If one of these threads fails (PREPARE_NOTOK) do we terminate the
+ * others or simply let them finish? Currently we wait and let them
+ * all terminate regardless.
+ */
- /*
- * Now synchronise with the threads.
- */
+ /*
+ * Now synchronise with the threads.
+ */
- for (int j = 0; j < numberOfThreads; j++)
- {
- while (threads[j].isAlive())
- {
- try
- {
- threads[j].join();
- }
- catch (Exception e)
- {
- tsLogger.logger.warn(e);
+ for (int j = 0; j < numberOfThreads; j++)
+ {
+ while (threads[j].isAlive())
+ {
+ try
+ {
+ threads[j].join();
+ }
+ catch (Exception e)
+ {
+ tsLogger.logger.warn(e);
- p = TwoPhaseOutcome.PREPARE_NOTOK;
- }
- }
+ p = TwoPhaseOutcome.PREPARE_NOTOK;
+ }
+ }
- /*
- * Only set the outcome if the current value is PREPARE_OK.
- */
+ /*
+ * Only set the outcome if the current value is PREPARE_OK.
+ */
- if (p == TwoPhaseOutcome.PREPARE_OK)
- p = ((AsyncPrepare) threads[j]).outcome();
+ if (p == TwoPhaseOutcome.PREPARE_OK)
+ p = ((AsyncPrepare) threads[j]).outcome();
- threads[j] = null;
- }
- }
- else
- {
- boolean ok = true;
+ threads[j] = null;
+ }
+ }
+ else
+ {
+ // single threaded prepare
- do
- {
- try
- {
- p = doPrepare(reportHeuristics);
+ // createPreparedLists will have ensured list exists, but it may be empty
+ if(pendingList.size() > 0) {
+ p = doPrepare(reportHeuristics);
+ }
+ }
- /*
- * Stop as soon as we get a failure return code.
- */
+ if ((p != TwoPhaseOutcome.PREPARE_OK)
+ && (p != TwoPhaseOutcome.PREPARE_READONLY))
+ {
+ if ((actionType == ActionType.NESTED)
+ && ((preparedList.size() > 0) && (p == TwoPhaseOutcome.ONE_PHASE_ERROR)))
+ {
+ /*
+ * For the OTS we must merge those records told to commit with
+ * the parent, as the rollback invocation must come from that
+ * since they have already been told this transaction has
+ * committed!
+ */
- if ((p != TwoPhaseOutcome.PREPARE_OK)
- && (p != TwoPhaseOutcome.PREPARE_READONLY))
- {
- ok = false;
- }
- }
- catch (IndexOutOfBoundsException e)
- {
- // end of list!
+ AbstractRecord tmpRec = preparedList.getFront();
- ok = false;
- }
+ while (tmpRec != null)
+ {
+ merge(tmpRec);
+ tmpRec = preparedList.getFront();
+ }
- } while (ok);
- }
-
- if ((p != TwoPhaseOutcome.PREPARE_OK)
- && (p != TwoPhaseOutcome.PREPARE_READONLY))
- {
- if ((actionType == ActionType.NESTED)
- && ((preparedList.size() > 0) && (p == TwoPhaseOutcome.ONE_PHASE_ERROR)))
- {
- /*
- * For the OTS we must merge those records told to commit with
- * the parent, as the rollback invocation must come from that
- * since they have already been told this transaction has
- * committed!
- */
-
- AbstractRecord tmpRec = preparedList.getFront();
-
- while (tmpRec != null)
- {
- merge(tmpRec);
- tmpRec = preparedList.getFront();
- }
-
- if (parentAction != null)
- parentAction.preventCommit();
- else {
+ if (parentAction != null)
+ parentAction.preventCommit();
+ else {
tsLogger.i18NLogger.warn_coordinator_BasicAction_44();
}
- }
+ }
- criticalEnd();
+ criticalEnd();
- return TwoPhaseOutcome.PREPARE_NOTOK;
- }
+ return TwoPhaseOutcome.PREPARE_NOTOK;
+ }
- /*
- * Now work out whether there is any state to save. Since we should be
- * single threaded once again, there is no need to protect the lists
- * with a synchronization.
- */
+ /*
+ * Now work out whether there is any state to save. Since we should be
+ * single threaded once again, there is no need to protect the lists
+ * with a synchronization.
+ */
- /*
- * Could do this as we traverse the lists above, but would need some
- * compound class for return values.
- */
+ /*
+ * Could do this as we traverse the lists above, but would need some
+ * compound class for return values.
+ */
- boolean stateToSave = false;
- RecordListIterator iter = new RecordListIterator(preparedList);
+ boolean stateToSave = false;
+ RecordListIterator iter = new RecordListIterator(preparedList);
- /*
- * First check the prepared list.
- */
+ /*
+ * First check the prepared list.
+ */
- while (((recordBeingHandled = iter.iterate()) != null))
- {
- if (!stateToSave)
- stateToSave = recordBeingHandled.doSave();
+ while (((recordBeingHandled = iter.iterate()) != null))
+ {
+ if (!stateToSave)
+ stateToSave = recordBeingHandled.doSave();
- if (stateToSave)
- break;
- }
+ if (stateToSave)
+ break;
+ }
- iter = null;
+ iter = null;
- if (!stateToSave)
- {
- iter = new RecordListIterator(heuristicList);
+ if (!stateToSave)
+ {
+ iter = new RecordListIterator(heuristicList);
- /*
- * Now check the heuristic list.
- */
+ /*
+ * Now check the heuristic list.
+ */
- while (((recordBeingHandled = heuristicList.getFront()) != null))
- {
- if (!stateToSave)
- stateToSave = recordBeingHandled.doSave();
+ while (((recordBeingHandled = heuristicList.getFront()) != null))
+ {
+ if (!stateToSave)
+ stateToSave = recordBeingHandled.doSave();
- if (stateToSave)
- break;
- }
+ if (stateToSave)
+ break;
+ }
- iter = null;
- }
+ iter = null;
+ }
- /*
- * The actual state we want to write depends upon whether or not we are
- * in charge of the transaction outcome:
- *
- * (i) if we are a root transaction, or an interposed transaction which
- * received a commit_one_phase call, then we have complete control over
- * what the transaction outcome will be. So, we will always try to
- * commit, and can set the state to committing.
- *
- * (ii) if we are an interposed transaction and it receives a complete
- * two-phase protocol, then the root is in control. So, we set the state
- * to prepared.
- *
- * (iii) nested transactions never write state, so the state is set to
- * prepared anyway.
- */
+ /*
+ * The actual state we want to write depends upon whether or not we are
+ * in charge of the transaction outcome:
+ *
+ * (i) if we are a root transaction, or an interposed transaction which
+ * received a commit_one_phase call, then we have complete control over
+ * what the transaction outcome will be. So, we will always try to
+ * commit, and can set the state to committing.
+ *
+ * (ii) if we are an interposed transaction and it receives a complete
+ * two-phase protocol, then the root is in control. So, we set the state
+ * to prepared.
+ *
+ * (iii) nested transactions never write state, so the state is set to
+ * prepared anyway.
+ */
- if (actionType == ActionType.TOP_LEVEL)
- actionStatus = preparedStatus();
- else
- actionStatus = ActionStatus.PREPARED;
+ if (actionType == ActionType.TOP_LEVEL)
+ actionStatus = preparedStatus();
+ else
+ actionStatus = ActionStatus.PREPARED;
- /*
- * If we are here then everything went okay so save the intention list
- * in the ObjectStore in case of a node crash providing that its not
- * empty
- */
+ /*
+ * If we are here then everything went okay so save the intention list
+ * in the ObjectStore in case of a node crash providing that its not
+ * empty
+ */
- if ((actionType == ActionType.TOP_LEVEL) && (stateToSave)
- && ((preparedList.size() > 0) || (heuristicList.size() > 0)))
- {
- /* Only do this if we have some records worth saving! */
+ if ((actionType == ActionType.TOP_LEVEL) && (stateToSave)
+ && ((preparedList.size() > 0) || (heuristicList.size() > 0)))
+ {
+ /* Only do this if we have some records worth saving! */
- Uid u = getSavingUid();
- String tn = type();
- OutputObjectState state = new OutputObjectState(u, tn);
+ Uid u = getSavingUid();
+ String tn = type();
+ OutputObjectState state = new OutputObjectState(u, tn);
- if (!save_state(state, ObjectType.ANDPERSISTENT)) {
+ if (!save_state(state, ObjectType.ANDPERSISTENT)) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_45(get_uid());
criticalEnd();
@@ -2218,52 +2198,52 @@
return TwoPhaseOutcome.PREPARE_NOTOK;
}
- if (state.notempty())
- {
- try
- {
- if (!participantStore.write_committed(u, tn, state)) {
+ if (state.notempty())
+ {
+ try
+ {
+ if (!participantStore.write_committed(u, tn, state)) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_46(get_uid());
criticalEnd();
return TwoPhaseOutcome.PREPARE_NOTOK;
}
- else
- savedIntentionList = true;
- }
- catch (ObjectStoreException e)
- {
- criticalEnd();
+ else
+ savedIntentionList = true;
+ }
+ catch (ObjectStoreException e)
+ {
+ criticalEnd();
- return TwoPhaseOutcome.PREPARE_NOTOK;
- }
- }
- }
+ return TwoPhaseOutcome.PREPARE_NOTOK;
+ }
+ }
+ }
- criticalEnd();
+ criticalEnd();
- if ((preparedList.size() == 0) && (readonlyList.size() >= 0))
- return TwoPhaseOutcome.PREPARE_READONLY;
- else
- return TwoPhaseOutcome.PREPARE_OK;
- }
+ if ((preparedList.size() == 0) && (readonlyList.size() >= 0))
+ return TwoPhaseOutcome.PREPARE_READONLY;
+ else
+ return TwoPhaseOutcome.PREPARE_OK;
+ }
- /**
- * There is only one record on the intentions list. Only called from
- * synchronized methods. Don't bother about creating separate threads here!
- */
+ /**
+ * There is only one record on the intentions list. Only called from
+ * synchronized methods. Don't bother about creating separate threads here!
+ */
- protected void onePhaseCommit (boolean reportHeuristics)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected void onePhaseCommit (boolean reportHeuristics)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::onePhaseCommit() for action-id "
+ get_uid());
}
- /* Are we forced to abort? */
+ /* Are we forced to abort? */
- if (actionStatus == ActionStatus.ABORT_ONLY) {
+ if (actionStatus == ActionStatus.ABORT_ONLY) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_43(get_uid());
Abort();
@@ -2271,83 +2251,83 @@
return;
}
- actionStatus = ActionStatus.COMMITTING;
+ actionStatus = ActionStatus.COMMITTING;
- criticalStart();
+ criticalStart();
- if ((heuristicList == null) && reportHeuristics)
- heuristicList = new RecordList();
-
- if (failedList == null)
- failedList = new RecordList();
-
- /*
- * Since it is one-phase, the outcome from the record is the outcome of
- * the transaction. Therefore, we don't need to save much intermediary
- * transaction state - only heuristics in the case of interposition.
- */
+ if ((heuristicList == null) && reportHeuristics)
+ heuristicList = new RecordList();
- boolean stateToSave = false;
+ if (failedList == null)
+ failedList = new RecordList();
- recordBeingHandled = pendingList.getFront();
+ /*
+ * Since it is one-phase, the outcome from the record is the outcome of
+ * the transaction. Therefore, we don't need to save much intermediary
+ * transaction state - only heuristics in the case of interposition.
+ */
- int p = ((actionType == ActionType.TOP_LEVEL) ? recordBeingHandled.topLevelOnePhaseCommit()
- : recordBeingHandled.nestedOnePhaseCommit());
-
- if ((p == TwoPhaseOutcome.FINISH_OK)
- || (p == TwoPhaseOutcome.PREPARE_READONLY))
- {
- if ((actionType == ActionType.NESTED)
- && recordBeingHandled.propagateOnCommit())
- {
- merge(recordBeingHandled);
- }
- else
- {
- recordBeingHandled = null;
- }
+ boolean stateToSave = false;
- actionStatus = ActionStatus.COMMITTED;
- }
- else
- {
- if ((p == TwoPhaseOutcome.FINISH_ERROR) || (p == TwoPhaseOutcome.ONE_PHASE_ERROR))
- {
- /*
- * If ONE_PHASE_ERROR then the resource has rolled back. Otherwise we
- * don't know and will ask recovery to keep trying. We differentiate
- * this kind of failure from a heuristic failure so that we can allow
- * recovery to retry the commit attempt periodically.
- */
-
- if (p == TwoPhaseOutcome.FINISH_ERROR)
- {
- /*
- * We still add to the failed list because this may not mean
- * that the transaction has aborted.
- */
-
- if (!failedList.insert(recordBeingHandled))
- recordBeingHandled = null;
- else
- {
- if (!stateToSave)
- stateToSave = recordBeingHandled.doSave();
- }
-
- /*
- * There's been a problem and we need to retry later. Assume
- * transaction has committed until we have further information.
- * This also ensures that recovery will kick in periodically.
- */
-
- actionStatus = ActionStatus.COMMITTED;
- }
- else
- actionStatus = ActionStatus.ABORTED;
- }
- else {
+ recordBeingHandled = pendingList.getFront();
+
+ int p = ((actionType == ActionType.TOP_LEVEL) ? recordBeingHandled.topLevelOnePhaseCommit()
+ : recordBeingHandled.nestedOnePhaseCommit());
+
+ if ((p == TwoPhaseOutcome.FINISH_OK)
+ || (p == TwoPhaseOutcome.PREPARE_READONLY))
+ {
+ if ((actionType == ActionType.NESTED)
+ && recordBeingHandled.propagateOnCommit())
+ {
+ merge(recordBeingHandled);
+ }
+ else
+ {
+ recordBeingHandled = null;
+ }
+
+ actionStatus = ActionStatus.COMMITTED;
+ }
+ else
+ {
+ if ((p == TwoPhaseOutcome.FINISH_ERROR) || (p == TwoPhaseOutcome.ONE_PHASE_ERROR))
+ {
/*
+ * If ONE_PHASE_ERROR then the resource has rolled back. Otherwise we
+ * don't know and will ask recovery to keep trying. We differentiate
+ * this kind of failure from a heuristic failure so that we can allow
+ * recovery to retry the commit attempt periodically.
+ */
+
+ if (p == TwoPhaseOutcome.FINISH_ERROR)
+ {
+ /*
+ * We still add to the failed list because this may not mean
+ * that the transaction has aborted.
+ */
+
+ if (!failedList.insert(recordBeingHandled))
+ recordBeingHandled = null;
+ else
+ {
+ if (!stateToSave)
+ stateToSave = recordBeingHandled.doSave();
+ }
+
+ /*
+ * There's been a problem and we need to retry later. Assume
+ * transaction has committed until we have further information.
+ * This also ensures that recovery will kick in periodically.
+ */
+
+ actionStatus = ActionStatus.COMMITTED;
+ }
+ else
+ actionStatus = ActionStatus.ABORTED;
+ }
+ else {
+ /*
* Heuristic decision!!
*/
@@ -2384,31 +2364,31 @@
// (could have
// aborted)
}
- }
+ }
- if (actionType == ActionType.TOP_LEVEL)
- {
- if (stateToSave && ((heuristicList.size() > 0) || (failedList.size() > 0)))
- {
- if (getStore() == null)
- {
- tsLogger.i18NLogger.fatal_coordinator_BasicAction_48();
+ if (actionType == ActionType.TOP_LEVEL)
+ {
+ if (stateToSave && ((heuristicList.size() > 0) || (failedList.size() > 0)))
+ {
+ if (getStore() == null)
+ {
+ tsLogger.i18NLogger.fatal_coordinator_BasicAction_48();
- throw new com.arjuna.ats.arjuna.exceptions.FatalError(
+ throw new com.arjuna.ats.arjuna.exceptions.FatalError(
tsLogger.i18NLogger.get_coordinator_BasicAction_69()
+ get_uid());
- }
+ }
- updateState();
- }
- }
+ updateState();
+ }
+ }
- forgetHeuristics();
+ forgetHeuristics();
- ActionManager.manager().remove(get_uid());
-
- criticalEnd();
+ ActionManager.manager().remove(get_uid());
+ criticalEnd();
+
if (TxStats.enabled()) {
if (actionStatus == ActionStatus.ABORTED) {
TxStats.getInstance().incrementAbortedTransactions();
@@ -2419,518 +2399,486 @@
}
- /**
- * @return the current heuristic decision. Each time a heuristic outcome is
- * received, we need to merge it with any previous outcome to
- * determine what the overall heuristic decision is (e.g., a
- * heuristic rollback followed by a heuristic commit means the
- * overall decision is heuristic mixed.)
- */
+ /**
+ * @return the current heuristic decision. Each time a heuristic outcome is
+ * received, we need to merge it with any previous outcome to
+ * determine what the overall heuristic decision is (e.g., a
+ * heuristic rollback followed by a heuristic commit means the
+ * overall decision is heuristic mixed.)
+ */
- protected final synchronized int getHeuristicDecision ()
- {
- return heuristicDecision;
- }
+ protected final synchronized int getHeuristicDecision ()
+ {
+ return heuristicDecision;
+ }
- /**
- * WARNING: use with extreme care!
- */
-
- protected final synchronized void setHeuristicDecision (int p)
- {
- heuristicDecision = p;
- }
+ /**
+ * WARNING: use with extreme care!
+ */
- /**
- * Add the specified abstract record to the transaction. Does not do any of
- * the runtime checking of BasicAction.add, so should be used with care.
- * Currently used by crash recovery.
- */
+ protected final synchronized void setHeuristicDecision (int p)
+ {
+ heuristicDecision = p;
+ }
- protected final synchronized void addRecord (AbstractRecord A)
- {
- preparedList.insert(A);
- }
+ /**
+ * Add the specified abstract record to the transaction. Does not do any of
+ * the runtime checking of BasicAction.add, so should be used with care.
+ * Currently used by crash recovery.
+ */
- /**
- * @return the transaction's prepared status.
- *
- * @since JTS 2.0.
- */
+ protected final synchronized void addRecord (AbstractRecord A)
+ {
+ preparedList.insert(A);
+ }
- protected int preparedStatus ()
- {
- if (actionType == ActionType.TOP_LEVEL)
- return ActionStatus.COMMITTING;
- else
- return ActionStatus.PREPARED;
- }
+ /**
+ * @return the transaction's prepared status.
+ *
+ * @since JTS 2.0.
+ */
- protected int abortStatus ()
- {
- return ActionStatus.ABORTED;
- }
+ protected int preparedStatus ()
+ {
+ if (actionType == ActionType.TOP_LEVEL)
+ return ActionStatus.COMMITTING;
+ else
+ return ActionStatus.PREPARED;
+ }
- protected int commitStatus ()
- {
- return ActionStatus.COMMITTED;
- }
+ protected int abortStatus ()
+ {
+ return ActionStatus.ABORTED;
+ }
- /*
- * Package visibility.
- */
+ protected int commitStatus ()
+ {
+ return ActionStatus.COMMITTED;
+ }
- /*
- * The single-threaded version of doPrepare. If we do not use asynchronous
- * prepare, then we don't need to lock the RecordLists - only one thread can
- * access them anyway!
- */
- /*
- * If we do not use asynchronous prepare, then we don't need to lock the
- * RecordLists - only one thread can access them anyway! However, if
- * asynchronous prepare is being used then we need to synchronize on them.
- * The 'lock' parameter (default false) indicates whether we should try to
- * synchronize the RecordList or not.
- */
+ /*
+ * The single-threaded version of doPrepare. If we do not use asynchronous
+ * prepare, then we don't need to lock the RecordLists - only one thread can
+ * access them anyway!
+ */
+ private int doPrepare (boolean reportHeuristics)
+ {
+ /*
+ * Here is the start of the hard work. Walk down the pendingList
+ * invoking the appropriate prepare operation. If it succeeds put the
+ * record on either the preparedList or the read_only list and continue
+ * until the pendingList is exhausted.
+ *
+ * If prepare fails on any record stop processing immediately and put
+ * the offending record back on the pendingList.
+ */
- protected int doPrepare (boolean reportHeuristics)
- throws IndexOutOfBoundsException
- {
- /*
- * Here is the start of the hard work. Walk down the pendingList
- * invoking the appropriate prepare operation. If it succeeds put the
- * record on either the preparedList or the read_only list and continue
- * until the pendingList is exhausted.
- *
- * If prepare fails on any record stop processing immediately and put
- * the offending record back on the pendingList.
- */
+ int overallTwoPhaseOutcome = TwoPhaseOutcome.PREPARE_READONLY;
- int p = TwoPhaseOutcome.PREPARE_NOTOK;
+ /*
+ * March down the pendingList and pass the head of the list to the
+ * main work routine until either we run out of elements, or one of
+ * them fails.
+ */
+ boolean keepGoing = true;
+ while(pendingList.size() > 0 && keepGoing) {
+ AbstractRecord record = pendingList.getFront();
+ /*
+ * If a failure occurs then the record will be put back on to
+ * the pending list. Otherwise it is moved to another list or
+ * dropped if readonly.
+ */
- do
- {
- AbstractRecord rec = ((pendingList != null) ? pendingList.getFront()
- : null);
+ int individualTwoPhaseOutcome = doPrepare(reportHeuristics, record);
- /*
- * March down the pendingList and pass the head of the list to the
- * main work routine until either we run out of elements, or one of
- * them fails.
- */
+ if(individualTwoPhaseOutcome != TwoPhaseOutcome.PREPARE_READONLY) {
+ overallTwoPhaseOutcome = individualTwoPhaseOutcome;
+ }
- if (rec != null)
- {
- /*
- * If a failure occurs then the record will be put back on to
- * the pending list. Otherwise it is moved to another list or
- * dropped if readonly.
- */
+ keepGoing = ( individualTwoPhaseOutcome == TwoPhaseOutcome.PREPARE_OK) || ( individualTwoPhaseOutcome == TwoPhaseOutcome.PREPARE_READONLY);
+ }
- p = doPrepare(reportHeuristics, rec);
+ return overallTwoPhaseOutcome;
+ }
- /*
- * If failure then it's back on the pending list by now. Move on
- * or terminate?
- *
- * Move on if a cohesion, but terminate if an atom!!
- */
- }
- else
- throw new IndexOutOfBoundsException();
+ /*
+ * The multi-threaded version of doPrepare. Each thread was given the record
+ * it should process when it was created so that if a failure occurs we can
+ * put it back onto the pendingList at the right place. It also cuts down on
+ * the amount of synchronisation we must do.
+ */
- } while ((p == TwoPhaseOutcome.PREPARE_OK)
- || (p == TwoPhaseOutcome.PREPARE_READONLY));
+ protected int doPrepare (boolean reportHeuristics, AbstractRecord record)
+ {
+ /*
+ * Here is the start of the hard work. Walk down the pendingList
+ * invoking the appropriate prepare operation. If it succeeds put the
+ * record on either the preparedList or the read_only list and continue
+ * until the pendingList is exhausted.
+ *
+ * If prepare fails on any record stop processing immediately and put
+ * the offending record back on the pendingList.
+ */
- return p;
- }
+ int p = TwoPhaseOutcome.PREPARE_NOTOK;
- /*
- * The multi-threaded version of doPrepare. Each thread was given the record
- * it should process when it was created so that if a failure occurs we can
- * put it back onto the pendingList at the right place. It also cuts down on
- * the amount of synchronisation we must do.
- */
+ p = ((actionType == ActionType.TOP_LEVEL) ? record.topLevelPrepare()
+ : record.nestedPrepare());
- protected int doPrepare (boolean reportHeuristics, AbstractRecord theRecord)
- throws IndexOutOfBoundsException
- {
- /*
- * Here is the start of the hard work. Walk down the pendingList
- * invoking the appropriate prepare operation. If it succeeds put the
- * record on either the preparedList or the read_only list and continue
- * until the pendingList is exhausted.
- *
- * If prepare fails on any record stop processing immediately and put
- * the offending record back on the pendingList.
- */
+ if (p == TwoPhaseOutcome.PREPARE_OK)
+ {
+ record = insertRecord(preparedList, record);
+ }
+ else
+ {
+ if (p == TwoPhaseOutcome.PREPARE_READONLY)
+ {
+ record = insertRecord(readonlyList, record);
+ }
+ else
+ {
+ if ((p == TwoPhaseOutcome.PREPARE_NOTOK)
+ || (p == TwoPhaseOutcome.ONE_PHASE_ERROR)
+ || (!reportHeuristics))
+ {
+ /*
+ * If we are a subtransaction and this is an OTS
+ * resource then we may be in trouble: we may have
+ * already told other records to commit.
+ */
- int p = TwoPhaseOutcome.PREPARE_NOTOK;
- AbstractRecord record = theRecord;
+ if (actionType == ActionType.NESTED)
+ {
+ if ((preparedList.size() > 0)
+ && (p == TwoPhaseOutcome.ONE_PHASE_ERROR)) {
+ tsLogger.i18NLogger.warn_coordinator_BasicAction_49(get_uid());
- if (record != null)
- {
- p = ((actionType == ActionType.TOP_LEVEL) ? record.topLevelPrepare()
- : record.nestedPrepare());
+ /*
+ * Force parent to rollback. If this is not the
+ * desired result then we may need to check some
+ * environment variable (either here or in the
+ * OTS) and act accordingly. If we check in the
+ * OTS then we need to return something other
+ * than PREPARE_NOTOK.
+ */
- if (p == TwoPhaseOutcome.PREPARE_OK)
- {
- record = insertRecord(preparedList, record);
- }
- else
- {
- if (p == TwoPhaseOutcome.PREPARE_READONLY)
- {
- record = insertRecord(readonlyList, record);
- }
- else
- {
- if ((p == TwoPhaseOutcome.PREPARE_NOTOK)
- || (p == TwoPhaseOutcome.ONE_PHASE_ERROR)
- || (!reportHeuristics))
- {
- /*
- * If we are a subtransaction and this is an OTS
- * resource then we may be in trouble: we may have
- * already told other records to commit.
- */
+ /*
+ * For the OTS we must merge those records told
+ * to commit with the parent, as the rollback
+ * invocation must come from that since they
+ * have already been told this transaction has
+ * committed!
+ *
+ * However, since we may be multi-threaded
+ * (asynchronous prepare) we don't do the
+ * merging yet. Wait until all threads have
+ * terminated and then do it.
+ *
+ * Therefore, can't force parent to rollback
+ * state at present, or merge will fail.
+ */
+ }
+ }
- if (actionType == ActionType.NESTED)
- {
- if ((preparedList.size() > 0)
- && (p == TwoPhaseOutcome.ONE_PHASE_ERROR)) {
- tsLogger.i18NLogger.warn_coordinator_BasicAction_49(get_uid());
+ /*
+ * Prepare on this record failed - we are in trouble.
+ * Add the record back onto the pendingList and return.
+ */
- /*
- * Force parent to rollback. If this is not the
- * desired result then we may need to check some
- * environment variable (either here or in the
- * OTS) and act accordingly. If we check in the
- * OTS then we need to return something other
- * than PREPARE_NOTOK.
- */
+ record = insertRecord(pendingList, record);
- /*
- * For the OTS we must merge those records told
- * to commit with the parent, as the rollback
- * invocation must come from that since they
- * have already been told this transaction has
- * committed!
- *
- * However, since we may be multi-threaded
- * (asynchronous prepare) we don't do the
- * merging yet. Wait until all threads have
- * terminated and then do it.
- *
- * Therefore, can't force parent to rollback
- * state at present, or merge will fail.
- */
- }
- }
+ record = null;
- /*
- * Prepare on this record failed - we are in trouble.
- * Add the record back onto the pendingList and return.
- */
+ actionStatus = ActionStatus.PREPARED;
- record = insertRecord(pendingList, record);
+ return p;
+ }
+ else {
+ /*
+ * Heuristic decision!!
+ */
- record = null;
+ /*
+ * Only report if request to do so.
+ */
- actionStatus = ActionStatus.PREPARED;
+ tsLogger.i18NLogger.warn_coordinator_BasicAction_50(get_uid(), TwoPhaseOutcome.stringForm(p));
- return p;
- }
- else {
- /*
- * Heuristic decision!!
- */
+ if (reportHeuristics)
+ updateHeuristic(p, false);
- /*
- * Only report if request to do so.
- */
+ /*
+ * Don't add to the prepared list. We process heuristics
+ * separately during phase 2. The processing of records
+ * will not be in the same order as during phase 1, but
+ * does this matter for heuristic decisions? If so, then
+ * we need to modify RecordList so that records can
+ * appear on multiple lists at the same time.
+ */
- tsLogger.i18NLogger.warn_coordinator_BasicAction_50(get_uid(), TwoPhaseOutcome.stringForm(p));
+ record = insertRecord(heuristicList, record);
- if (reportHeuristics)
- updateHeuristic(p, false);
+ /*
+ * If we have had a heuristic decision, then attempt to
+ * make the action outcome the same. If we have a
+ * conflict, then we will abort.
+ */
- /*
- * Don't add to the prepared list. We process heuristics
- * separately during phase 2. The processing of records
- * will not be in the same order as during phase 1, but
- * does this matter for heuristic decisions? If so, then
- * we need to modify RecordList so that records can
- * appear on multiple lists at the same time.
- */
+ if (heuristicDecision != TwoPhaseOutcome.HEURISTIC_COMMIT) {
+ actionStatus = ActionStatus.PREPARED;
- record = insertRecord(heuristicList, record);
-
+ return TwoPhaseOutcome.PREPARE_NOTOK;
+ } else {
/*
- * If we have had a heuristic decision, then attempt to
- * make the action outcome the same. If we have a
- * conflict, then we will abort.
- */
-
- if (heuristicDecision != TwoPhaseOutcome.HEURISTIC_COMMIT) {
- actionStatus = ActionStatus.PREPARED;
-
- return TwoPhaseOutcome.PREPARE_NOTOK;
- } else {
- /*
- * Heuristic commit, which is ok since we want to
- * commit anyway! So, ignore it (but remember the
- * resource so we can tell it to forget later.)
- */
- }
+ * Heuristic commit, which is ok since we want to
+ * commit anyway! So, ignore it (but remember the
+ * resource so we can tell it to forget later.)
+ */
}
- }
- }
- }
- else
- // no more entries in pendingList
- throw new IndexOutOfBoundsException();
+ }
+ }
+ }
- return p;
- }
+ return p;
+ }
- /**
- * Walk down a record list extracting records and calling the appropriate
- * commit function. Discard or merge records as appropriate
- */
+ /**
+ * Walk down a record list extracting records and calling the appropriate
+ * commit function. Discard or merge records as appropriate
+ */
- protected int doCommit (RecordList rl, boolean reportHeuristics)
- {
- if ((rl != null) && (rl.size() > 0))
- {
- AbstractRecord rec;
- boolean pastFirstParticipant = false;
+ protected int doCommit (RecordList rl, boolean reportHeuristics)
+ {
+ if ((rl != null) && (rl.size() > 0))
+ {
+ AbstractRecord rec;
+ boolean pastFirstParticipant = false;
- while (((rec = rl.getFront()) != null))
- {
- int outcome = doCommit(reportHeuristics, rec);
+ while (((rec = rl.getFront()) != null))
+ {
+ int outcome = doCommit(reportHeuristics, rec);
- /*
- * Check the outcome and if we have a heuristic rollback try to
- * rollback everything else in the list *if* we have not already
- * committed something. That way we make the outcome for all
- * participants the same as the first (rollback) and don't get a
- * heuristic!
- */
+ /*
+ * Check the outcome and if we have a heuristic rollback try to
+ * rollback everything else in the list *if* we have not already
+ * committed something. That way we make the outcome for all
+ * participants the same as the first (rollback) and don't get a
+ * heuristic!
+ */
- switch (outcome)
- {
- case TwoPhaseOutcome.FINISH_OK:
- case TwoPhaseOutcome.HEURISTIC_COMMIT:
- pastFirstParticipant = true;
- break;
- case TwoPhaseOutcome.HEURISTIC_MIXED:
- case TwoPhaseOutcome.HEURISTIC_HAZARD:
- default:
- /*
- * Do nothing and continue to commit everything else. We've
- * got this far as errors have caused problems, but we gain
- * nothing by now rolling back some participants. This could
- * cause further heuristics!
- */
+ switch (outcome)
+ {
+ case TwoPhaseOutcome.FINISH_OK:
+ case TwoPhaseOutcome.HEURISTIC_COMMIT:
+ pastFirstParticipant = true;
+ break;
+ case TwoPhaseOutcome.HEURISTIC_MIXED:
+ case TwoPhaseOutcome.HEURISTIC_HAZARD:
+ default:
+ /*
+ * Do nothing and continue to commit everything else. We've
+ * got this far as errors have caused problems, but we gain
+ * nothing by now rolling back some participants. This could
+ * cause further heuristics!
+ */
- pastFirstParticipant = true;
- break;
- case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
- {
- /*
- * A heuristic decision of commit means that we have got
- * past the first entry in the list. So there is no going
- * back now!
- */
+ pastFirstParticipant = true;
+ break;
+ case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
+ {
+ /*
+ * A heuristic decision of commit means that we have got
+ * past the first entry in the list. So there is no going
+ * back now!
+ */
- if (pastFirstParticipant)
- break;
- else
- {
- /*
- * Remember the heuristic decision so we can restore it
- * after rolling back. Otherwise we can't return the
- * right value from commit.
- */
+ if (pastFirstParticipant)
+ break;
+ else
+ {
+ /*
+ * Remember the heuristic decision so we can restore it
+ * after rolling back. Otherwise we can't return the
+ * right value from commit.
+ */
- pastFirstParticipant = true;
+ pastFirstParticipant = true;
- int oldDecision = heuristicDecision;
+ int oldDecision = heuristicDecision;
- phase2Abort(reportHeuristics);
+ phase2Abort(reportHeuristics);
- heuristicDecision = oldDecision;
- }
- }
- break;
- }
- }
- }
+ heuristicDecision = oldDecision;
+ }
+ }
+ break;
+ }
+ }
+ }
- return TwoPhaseOutcome.FINISH_OK;
- }
+ return TwoPhaseOutcome.FINISH_OK;
+ }
- protected int doCommit (boolean reportHeuristics, AbstractRecord record)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected int doCommit (boolean reportHeuristics, AbstractRecord record)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::doCommit ("
+ record + ")");
}
- /*
- * To get heuristics right, as soon as we manage to commit the first
- * record we set the heuristic to HEURISTIC_COMMIT. Then, if any other
- * heuristics are raised we can manage the final outcome correctly.
- */
+ /*
+ * To get heuristics right, as soon as we manage to commit the first
+ * record we set the heuristic to HEURISTIC_COMMIT. Then, if any other
+ * heuristics are raised we can manage the final outcome correctly.
+ */
- int ok = TwoPhaseOutcome.FINISH_ERROR;
+ int ok = TwoPhaseOutcome.FINISH_ERROR;
- recordBeingHandled = record;
+ recordBeingHandled = record;
- if (recordBeingHandled != null)
- {
- if (actionType == ActionType.TOP_LEVEL)
- {
- if ((ok = recordBeingHandled.topLevelCommit()) == TwoPhaseOutcome.FINISH_OK)
- {
- /*
- * Record successfully committed, we can delete it now.
- */
+ if (recordBeingHandled != null)
+ {
+ if (actionType == ActionType.TOP_LEVEL)
+ {
+ if ((ok = recordBeingHandled.topLevelCommit()) == TwoPhaseOutcome.FINISH_OK)
+ {
+ /*
+ * Record successfully committed, we can delete it now.
+ */
- recordBeingHandled = null;
+ recordBeingHandled = null;
- updateHeuristic(TwoPhaseOutcome.FINISH_OK, true); // must
- // remember
- // that
- // something
- // has
- // committed
- }
- else
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ updateHeuristic(TwoPhaseOutcome.FINISH_OK, true); // must
+ // remember
+ // that
+ // something
+ // has
+ // committed
+ }
+ else
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction.doCommit for "+get_uid()+" received "+
TwoPhaseOutcome.stringForm(ok)+" from "+RecordType.typeToClass(recordBeingHandled.typeIs()));
}
- if ((reportHeuristics)
- && ((ok == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- || (ok == TwoPhaseOutcome.HEURISTIC_COMMIT)
- || (ok == TwoPhaseOutcome.HEURISTIC_MIXED) || (ok == TwoPhaseOutcome.HEURISTIC_HAZARD)))
- {
- updateHeuristic(ok, true);
- heuristicList.insert(recordBeingHandled);
- }
- else
- {
- if (ok == TwoPhaseOutcome.NOT_PREPARED)
- {
- /*
- * If this is the first resource then rollback,
- * otherwise promote to HEURISTIC_HAZARD, but don't
- * add to heuristicList.
- */
+ if ((reportHeuristics)
+ && ((ok == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ || (ok == TwoPhaseOutcome.HEURISTIC_COMMIT)
+ || (ok == TwoPhaseOutcome.HEURISTIC_MIXED) || (ok == TwoPhaseOutcome.HEURISTIC_HAZARD)))
+ {
+ updateHeuristic(ok, true);
+ heuristicList.insert(recordBeingHandled);
+ }
+ else
+ {
+ if (ok == TwoPhaseOutcome.NOT_PREPARED)
+ {
+ /*
+ * If this is the first resource then rollback,
+ * otherwise promote to HEURISTIC_HAZARD, but don't
+ * add to heuristicList.
+ */
- updateHeuristic(TwoPhaseOutcome.HEURISTIC_HAZARD, true);
- }
- else
- {
- /*
- * The commit failed. Add this record to the failed
- * list to indicate this. Covers statuses like FAILED_ERROR.
- */
+ updateHeuristic(TwoPhaseOutcome.HEURISTIC_HAZARD, true);
+ }
+ else
+ {
+ /*
+ * The commit failed. Add this record to the failed
+ * list to indicate this. Covers statuses like FAILED_ERROR.
+ */
- failedList.insert(recordBeingHandled);
- }
- }
- }
- }
- else
- {
- /*
- * Thankfully nested actions cannot raise heuristics!
- */
+ failedList.insert(recordBeingHandled);
+ }
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Thankfully nested actions cannot raise heuristics!
+ */
- ok = recordBeingHandled.nestedCommit();
+ ok = recordBeingHandled.nestedCommit();
- if (recordBeingHandled.propagateOnCommit())
- {
- merge(recordBeingHandled);
- }
- else
- {
- recordBeingHandled = null;
- }
- }
+ if (recordBeingHandled.propagateOnCommit())
+ {
+ merge(recordBeingHandled);
+ }
+ else
+ {
+ recordBeingHandled = null;
+ }
+ }
- if (ok != TwoPhaseOutcome.FINISH_OK)
- {
- /* Preserve error messages */
- }
- }
+ if (ok != TwoPhaseOutcome.FINISH_OK)
+ {
+ /* Preserve error messages */
+ }
+ }
- return ok;
- }
+ return ok;
+ }
- /*
- * Walk down a record list extracting records and calling the appropriate
- * abort function. Discard records when done.
- */
+ /*
+ * Walk down a record list extracting records and calling the appropriate
+ * abort function. Discard records when done.
+ */
- protected int doAbort (RecordList list_toprocess, boolean reportHeuristics)
- {
- if ((list_toprocess != null) && (list_toprocess.size() > 0))
- {
- while ((recordBeingHandled = list_toprocess.getFront()) != null)
- {
- doAbort(reportHeuristics, recordBeingHandled);
- }
- }
+ protected int doAbort (RecordList list_toprocess, boolean reportHeuristics)
+ {
+ if ((list_toprocess != null) && (list_toprocess.size() > 0))
+ {
+ while ((recordBeingHandled = list_toprocess.getFront()) != null)
+ {
+ doAbort(reportHeuristics, recordBeingHandled);
+ }
+ }
- return TwoPhaseOutcome.FINISH_OK;
- }
+ return TwoPhaseOutcome.FINISH_OK;
+ }
- protected int doAbort (boolean reportHeuristics, AbstractRecord record)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ protected int doAbort (boolean reportHeuristics, AbstractRecord record)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::doAbort ("
+ record + ")");
}
- int ok = TwoPhaseOutcome.FINISH_OK;
+ int ok = TwoPhaseOutcome.FINISH_OK;
- recordBeingHandled = record;
+ recordBeingHandled = record;
- if (recordBeingHandled != null)
- {
- if (actionType == ActionType.TOP_LEVEL)
- ok = recordBeingHandled.topLevelAbort();
- else
- ok = recordBeingHandled.nestedAbort();
+ if (recordBeingHandled != null)
+ {
+ if (actionType == ActionType.TOP_LEVEL)
+ ok = recordBeingHandled.topLevelAbort();
+ else
+ ok = recordBeingHandled.nestedAbort();
- if ((actionType != ActionType.TOP_LEVEL)
- && (recordBeingHandled.propagateOnAbort()))
- {
- merge(recordBeingHandled);
- }
- else
- {
- if (ok == TwoPhaseOutcome.FINISH_OK)
- {
- updateHeuristic(TwoPhaseOutcome.FINISH_OK, false); // remember
- // that
- // something
- // aborted
- // ok
- }
- else
- {
- if ((reportHeuristics)
- && ((ok == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- || (ok == TwoPhaseOutcome.HEURISTIC_COMMIT)
- || (ok == TwoPhaseOutcome.HEURISTIC_MIXED) || (ok == TwoPhaseOutcome.HEURISTIC_HAZARD))) {
+ if ((actionType != ActionType.TOP_LEVEL)
+ && (recordBeingHandled.propagateOnAbort()))
+ {
+ merge(recordBeingHandled);
+ }
+ else
+ {
+ if (ok == TwoPhaseOutcome.FINISH_OK)
+ {
+ updateHeuristic(TwoPhaseOutcome.FINISH_OK, false); // remember
+ // that
+ // something
+ // aborted
+ // ok
+ }
+ else
+ {
+ if ((reportHeuristics)
+ && ((ok == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ || (ok == TwoPhaseOutcome.HEURISTIC_COMMIT)
+ || (ok == TwoPhaseOutcome.HEURISTIC_MIXED) || (ok == TwoPhaseOutcome.HEURISTIC_HAZARD))) {
if (actionType == ActionType.TOP_LEVEL)
tsLogger.i18NLogger.warn_coordinator_BasicAction_52(get_uid(), TwoPhaseOutcome.stringForm(ok));
else
@@ -2939,9 +2887,9 @@
updateHeuristic(ok, false);
heuristicList.insert(recordBeingHandled);
}
- else
- {
- if (ok != TwoPhaseOutcome.FINISH_OK) {
+ else
+ {
+ if (ok != TwoPhaseOutcome.FINISH_OK) {
if (actionType == ActionType.TOP_LEVEL)
tsLogger.i18NLogger.warn_coordinator_BasicAction_54(get_uid(),
TwoPhaseOutcome.stringForm(ok),
@@ -2951,277 +2899,277 @@
TwoPhaseOutcome.stringForm(ok),
RecordType.typeToClass(recordBeingHandled.typeIs()).getCanonicalName());
}
- }
- }
+ }
+ }
- /*
- * Don't need a canDelete as in the C++ version since Java's
- * garbage collection will deal with things for us.
- */
+ /*
+ * Don't need a canDelete as in the C++ version since Java's
+ * garbage collection will deal with things for us.
+ */
- recordBeingHandled = null;
- }
- }
+ recordBeingHandled = null;
+ }
+ }
- return ok;
- }
+ return ok;
+ }
- protected AbstractRecord insertRecord (RecordList reclist, AbstractRecord record)
- {
- boolean lock = TxControl.asyncPrepare;
+ protected AbstractRecord insertRecord (RecordList reclist, AbstractRecord record)
+ {
+ boolean lock = TxControl.asyncPrepare;
- if (lock)
- {
- synchronized (reclist)
- {
- if (!reclist.insert(record))
- record = null;
- }
- }
- else
- {
- if (!reclist.insert(record))
- record = null;
- }
+ if (lock)
+ {
+ synchronized (reclist)
+ {
+ if (!reclist.insert(record))
+ record = null;
+ }
+ }
+ else
+ {
+ if (!reclist.insert(record))
+ record = null;
+ }
- return record;
- }
+ return record;
+ }
- /**
- * Do we want to check that a transaction can only be terminated by a thread
- * that has it as its current transaction? The base class has this check
- * enabled (i.e., we check), but some implementations may wish to override
- * this.
- *
- * @return <code>false</code> to disable checking.
- */
+ /**
+ * Do we want to check that a transaction can only be terminated by a thread
+ * that has it as its current transaction? The base class has this check
+ * enabled (i.e., we check), but some implementations may wish to override
+ * this.
+ *
+ * @return <code>false</code> to disable checking.
+ */
- protected boolean checkForCurrent ()
- {
- return false;
- }
+ protected boolean checkForCurrent ()
+ {
+ return false;
+ }
- /*
- * If we get a single heuristic then we will always rollback during prepare.
- *
- * Getting a heuristic during commit is slightly different, since some
- * resources may have already committed, changing the type of heuristic we
- * may need to throw. However, once we get to commit we know that it will be
- * the final outcome. So, as soon as a single resource commits successfully,
- * we can take it as a HEURISTIC_COMMIT. We will forget a HEURISTIC_COMMIT
- * outcome at the end anyway.
- */
+ /*
+ * If we get a single heuristic then we will always rollback during prepare.
+ *
+ * Getting a heuristic during commit is slightly different, since some
+ * resources may have already committed, changing the type of heuristic we
+ * may need to throw. However, once we get to commit we know that it will be
+ * the final outcome. So, as soon as a single resource commits successfully,
+ * we can take it as a HEURISTIC_COMMIT. We will forget a HEURISTIC_COMMIT
+ * outcome at the end anyway.
+ */
- protected final synchronized void updateHeuristic (int p, boolean commit)
- {
- /*
- * Some resource has prepared/committed ok, so we need to remember this
- * in case we get a future heuristic.
- */
+ protected final synchronized void updateHeuristic (int p, boolean commit)
+ {
+ /*
+ * Some resource has prepared/committed ok, so we need to remember this
+ * in case we get a future heuristic.
+ */
- if (p == TwoPhaseOutcome.FINISH_OK)
- {
- // only count the first heuristic.
-
- if (TxStats.enabled())
- TxStats.getInstance().incrementHeuristics();
-
- if (commit)
- {
- if (heuristicDecision == TwoPhaseOutcome.PREPARE_OK)
- p = TwoPhaseOutcome.HEURISTIC_COMMIT;
+ if (p == TwoPhaseOutcome.FINISH_OK)
+ {
+ // only count the first heuristic.
- if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
- }
- else
- {
- if (heuristicDecision == TwoPhaseOutcome.PREPARE_OK)
- p = TwoPhaseOutcome.HEURISTIC_ROLLBACK;
+ if (TxStats.enabled())
+ TxStats.getInstance().incrementHeuristics();
- if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
- }
+ if (commit)
+ {
+ if (heuristicDecision == TwoPhaseOutcome.PREPARE_OK)
+ p = TwoPhaseOutcome.HEURISTIC_COMMIT;
- // leave HAZARD and MIXED alone
- }
+ if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
+ }
+ else
+ {
+ if (heuristicDecision == TwoPhaseOutcome.PREPARE_OK)
+ p = TwoPhaseOutcome.HEURISTIC_ROLLBACK;
- /*
- * Is this the first heuristic? Always give HEURISTIC_MIXED priority,
- * but if we have no heuristic and we get a HEURISTIC_HAZARD then go
- * with that until something better comes along!
- */
+ if (heuristicDecision == TwoPhaseOutcome.HEURISTIC_COMMIT)
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
+ }
- /*
- * Have we already been given a conflicting heuristic? If so, raise the
- * decision to the next heuristic level.
- */
+ // leave HAZARD and MIXED alone
+ }
- switch (heuristicDecision)
- {
- case TwoPhaseOutcome.PREPARE_OK:
- if ((p != TwoPhaseOutcome.PREPARE_OK)
- && (p != TwoPhaseOutcome.FINISH_OK)) // first heuristic
- // outcome.
- heuristicDecision = p;
- break;
- case TwoPhaseOutcome.HEURISTIC_COMMIT:
- if ((p == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
- || (p == TwoPhaseOutcome.HEURISTIC_MIXED))
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
- else
- {
- if (p == TwoPhaseOutcome.HEURISTIC_HAZARD)
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_HAZARD;
- }
- break;
- case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
- if ((p == TwoPhaseOutcome.HEURISTIC_COMMIT)
- || (p == TwoPhaseOutcome.HEURISTIC_MIXED))
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
- else
- {
- if (p == TwoPhaseOutcome.HEURISTIC_HAZARD)
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_HAZARD;
- }
- break;
- case TwoPhaseOutcome.HEURISTIC_HAZARD:
- if (p == TwoPhaseOutcome.HEURISTIC_MIXED)
- heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
- break;
- case TwoPhaseOutcome.HEURISTIC_MIXED:
- break;
- default:
- heuristicDecision = p; // anything!
- break;
- }
- }
+ /*
+ * Is this the first heuristic? Always give HEURISTIC_MIXED priority,
+ * but if we have no heuristic and we get a HEURISTIC_HAZARD then go
+ * with that until something better comes along!
+ */
- protected void updateState ()
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ /*
+ * Have we already been given a conflicting heuristic? If so, raise the
+ * decision to the next heuristic level.
+ */
+
+ switch (heuristicDecision)
+ {
+ case TwoPhaseOutcome.PREPARE_OK:
+ if ((p != TwoPhaseOutcome.PREPARE_OK)
+ && (p != TwoPhaseOutcome.FINISH_OK)) // first heuristic
+ // outcome.
+ heuristicDecision = p;
+ break;
+ case TwoPhaseOutcome.HEURISTIC_COMMIT:
+ if ((p == TwoPhaseOutcome.HEURISTIC_ROLLBACK)
+ || (p == TwoPhaseOutcome.HEURISTIC_MIXED))
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
+ else
+ {
+ if (p == TwoPhaseOutcome.HEURISTIC_HAZARD)
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_HAZARD;
+ }
+ break;
+ case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
+ if ((p == TwoPhaseOutcome.HEURISTIC_COMMIT)
+ || (p == TwoPhaseOutcome.HEURISTIC_MIXED))
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
+ else
+ {
+ if (p == TwoPhaseOutcome.HEURISTIC_HAZARD)
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_HAZARD;
+ }
+ break;
+ case TwoPhaseOutcome.HEURISTIC_HAZARD:
+ if (p == TwoPhaseOutcome.HEURISTIC_MIXED)
+ heuristicDecision = TwoPhaseOutcome.HEURISTIC_MIXED;
+ break;
+ case TwoPhaseOutcome.HEURISTIC_MIXED:
+ break;
+ default:
+ heuristicDecision = p; // anything!
+ break;
+ }
+ }
+
+ protected void updateState ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::updateState() for action-id "
+ get_uid());
}
- /*
- * If the action is topLevel then prepare() will have written the
- * intention_list to the object_store. If any of the phase2Commit
- * processing failed then records will exist on the failedList. If this
- * is the case then we need to re-write the BasicAction record in the
- * object store. If the failed list is empty we can simply delete the
- * BasicAction record.
- */
+ /*
+ * If the action is topLevel then prepare() will have written the
+ * intention_list to the object_store. If any of the phase2Commit
+ * processing failed then records will exist on the failedList. If this
+ * is the case then we need to re-write the BasicAction record in the
+ * object store. If the failed list is empty we can simply delete the
+ * BasicAction record.
+ */
- if (actionType == ActionType.TOP_LEVEL)
- {
- /*
- * make sure the object store is set up for a top-level atomic
- * action.
- */
+ if (actionType == ActionType.TOP_LEVEL)
+ {
+ /*
+ * make sure the object store is set up for a top-level atomic
+ * action.
+ */
- getStore();
+ getStore();
- /*
- * If we have failures then rewrite the intentions list. Otherwise,
- * delete the log entry. Depending upon how we get here the intentions
- * list will either be in the preparedList or the failedList. Fortunately
- * save_state will figure out which one to use.
- */
+ /*
+ * If we have failures then rewrite the intentions list. Otherwise,
+ * delete the log entry. Depending upon how we get here the intentions
+ * list will either be in the preparedList or the failedList. Fortunately
+ * save_state will figure out which one to use.
+ */
- if (((failedList != null) && (failedList.size() > 0))
- || ((heuristicList != null) && (heuristicList.size() > 0))
- || ((preparedList != null) && (preparedList.size() > 0)))
- {
- /*
- * Re-write the BasicAction record with the failed list
- */
+ if (((failedList != null) && (failedList.size() > 0))
+ || ((heuristicList != null) && (heuristicList.size() > 0))
+ || ((preparedList != null) && (preparedList.size() > 0)))
+ {
+ /*
+ * Re-write the BasicAction record with the failed list
+ */
- Uid u = getSavingUid();
- String tn = type();
- OutputObjectState state = new OutputObjectState(u, tn);
+ Uid u = getSavingUid();
+ String tn = type();
+ OutputObjectState state = new OutputObjectState(u, tn);
- if (!save_state(state, ObjectType.ANDPERSISTENT)) {
+ if (!save_state(state, ObjectType.ANDPERSISTENT)) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_64();
// what else?
}
- if (state.notempty())
- {
- try
- {
- if (!participantStore.write_committed(u, tn, state)) {
+ if (state.notempty())
+ {
+ try
+ {
+ if (!participantStore.write_committed(u, tn, state)) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_65();
}
- }
- catch (ObjectStoreException e)
- {
- tsLogger.logger.warn(e);
- }
- }
- }
- else
- {
- try
- {
- if (savedIntentionList)
- {
- if (participantStore.remove_committed(getSavingUid(), type()))
- {
- savedIntentionList = false;
- }
- }
- }
- catch (ObjectStoreException e) {
+ }
+ catch (ObjectStoreException e)
+ {
+ tsLogger.logger.warn(e);
+ }
+ }
+ }
+ else
+ {
+ try
+ {
+ if (savedIntentionList)
+ {
+ if (participantStore.remove_committed(getSavingUid(), type()))
+ {
+ savedIntentionList = false;
+ }
+ }
+ }
+ catch (ObjectStoreException e) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_70(e);
}
- }
- }
- }
+ }
+ }
+ }
- /*
- * This is only meant as an instance cut of the children, so don't lock the
- * entire transaction. Thus, the list may change before we return.
- */
+ /*
+ * This is only meant as an instance cut of the children, so don't lock the
+ * entire transaction. Thus, the list may change before we return.
+ */
- private final void createPreparedLists ()
- {
- if (preparedList == null)
- preparedList = new RecordList();
+ private final void createPreparedLists ()
+ {
+ if (preparedList == null)
+ preparedList = new RecordList();
- if (readonlyList == null)
- readonlyList = new RecordList();
+ if (readonlyList == null)
+ readonlyList = new RecordList();
- if (failedList == null)
- failedList = new RecordList();
+ if (failedList == null)
+ failedList = new RecordList();
- if (heuristicList == null)
- heuristicList = new RecordList();
+ if (heuristicList == null)
+ heuristicList = new RecordList();
- if (pendingList == null)
- pendingList = new RecordList();
- }
+ if (pendingList == null)
+ pendingList = new RecordList();
+ }
- /**
- * Check to see if this transaction is the one that is current for this
- * thread. If it isn't, then we mark this transaction as rollback only.
- *
- * @return <code>true</code> if the transaction is current,
- * <code>false</code> otherwise.
- */
+ /**
+ * Check to see if this transaction is the one that is current for this
+ * thread. If it isn't, then we mark this transaction as rollback only.
+ *
+ * @return <code>true</code> if the transaction is current,
+ * <code>false</code> otherwise.
+ */
- private final boolean checkIsCurrent ()
- {
- boolean isCurrent = true;
+ private final boolean checkIsCurrent ()
+ {
+ boolean isCurrent = true;
- if (checkForCurrent())
- {
- BasicAction currentAct = BasicAction.Current();
+ if (checkForCurrent())
+ {
+ BasicAction currentAct = BasicAction.Current();
- /* Ensure I am the currently active action */
+ /* Ensure I am the currently active action */
- if ((currentAct != null) && (currentAct != this)) {
+ if ((currentAct != null) && (currentAct != this)) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_56(currentAct.get_uid(), get_uid());
isCurrent = false;
@@ -3240,25 +3188,25 @@
}
}
- currentAct = null;
- }
+ currentAct = null;
+ }
- return isCurrent;
- }
+ return isCurrent;
+ }
- private final boolean checkChildren (boolean isCommit)
- {
- boolean problem = false;
+ private final boolean checkChildren (boolean isCommit)
+ {
+ boolean problem = false;
- /*
- * If we have child threads then by default we just print a warning and
- * continue. The other threads will eventually find out the outcome.
- */
+ /*
+ * If we have child threads then by default we just print a warning and
+ * continue. The other threads will eventually find out the outcome.
+ */
- if ((_childThreads != null) && (_childThreads.size() > 0))
- {
- if ((_childThreads.size() != 1)
- || ((_childThreads.size() == 1) && (!_childThreads.contains(Thread.currentThread())))) {
+ if ((_childThreads != null) && (_childThreads.size() > 0))
+ {
+ if ((_childThreads.size() != 1)
+ || ((_childThreads.size() == 1) && (!_childThreads.contains(Thread.currentThread())))) {
/*
* More than one thread or the one thread is not the current
* thread
@@ -3275,32 +3223,32 @@
removeAllChildThreads();
}
- }
+ }
- /* Ensure I have no child actions */
+ /* Ensure I have no child actions */
- if ((_childActions != null) && (_childActions.size() > 0))
- {
- problem = true;
+ if ((_childActions != null) && (_childActions.size() > 0))
+ {
+ problem = true;
- Enumeration iter = _childActions.elements();
- BasicAction child = null;
- boolean printError = true;
+ Enumeration iter = _childActions.elements();
+ BasicAction child = null;
+ boolean printError = true;
- /*
- * We may have already aborted our children, e.g., because of an
- * out-of-sequence commit, so we check here to reduce the number of
- * error messages!
- *
- * We can't just remove the children when we are finished with them
- * because BasicAction is not responsible for action tracking.
- */
+ /*
+ * We may have already aborted our children, e.g., because of an
+ * out-of-sequence commit, so we check here to reduce the number of
+ * error messages!
+ *
+ * We can't just remove the children when we are finished with them
+ * because BasicAction is not responsible for action tracking.
+ */
- while (iter.hasMoreElements())
- {
- child = (BasicAction) iter.nextElement();
+ while (iter.hasMoreElements())
+ {
+ child = (BasicAction) iter.nextElement();
- if (child.status() != ActionStatus.ABORTED) {
+ if (child.status() != ActionStatus.ABORTED) {
if (printError) {
if (isCommit) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_59(get_uid());
@@ -3316,293 +3264,293 @@
child.Abort();
child = null;
}
- }
+ }
- iter = null;
+ iter = null;
- if (isCommit) {
+ if (isCommit) {
tsLogger.i18NLogger.warn_coordinator_BasicAction_62(((child != null ? child.get_uid().toString() : "null")));
}
- }
+ }
- return problem;
- }
+ return problem;
+ }
- /*
- * Just in case we are deleted/terminated with threads still registered. We
- * must make sure those threads don't try to remove themselves from this
- * action later. So we unregister them ourselves now.
- *
- * This is only called by End/Abort and so all child actions will have been
- * previously terminated as well.
- */
+ /*
+ * Just in case we are deleted/terminated with threads still registered. We
+ * must make sure those threads don't try to remove themselves from this
+ * action later. So we unregister them ourselves now.
+ *
+ * This is only called by End/Abort and so all child actions will have been
+ * previously terminated as well.
+ */
- private final void removeAllChildThreads ()
- {
- /*
- * Do not remove the current thread as it is committing/aborting!
- */
+ private final void removeAllChildThreads ()
+ {
+ /*
+ * Do not remove the current thread as it is committing/aborting!
+ */
- criticalStart();
+ criticalStart();
- if ((_childThreads != null) && (_childThreads.size() != 0))
- {
- Thread currentThread = Thread.currentThread();
+ if ((_childThreads != null) && (_childThreads.size() != 0))
+ {
+ Thread currentThread = Thread.currentThread();
- /*
- * Iterate through all registered threads and tell them to ignore
- * the action pointer, i.e., they are now no longer within this
- * action.
- */
+ /*
+ * Iterate through all registered threads and tell them to ignore
+ * the action pointer, i.e., they are now no longer within this
+ * action.
+ */
- Enumeration iter = _childThreads.elements();
- Thread t = null;
+ Enumeration iter = _childThreads.elements();
+ Thread t = null;
- while (iter.hasMoreElements())
- {
- t = (Thread) iter.nextElement();
+ while (iter.hasMoreElements())
+ {
+ t = (Thread) iter.nextElement();
- if (tsLogger.logger.isTraceEnabled()) {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::removeAllChildThreads () action "+get_uid()+" removing "+t);
}
- if (t != currentThread)
- ThreadActionData.purgeAction(this, t);
- }
- }
+ if (t != currentThread)
+ ThreadActionData.purgeAction(this, t);
+ }
+ }
- criticalEnd();
- }
+ criticalEnd();
+ }
- /**
- * actionInitialise determines whether the BasicAction is a nested,
- * top-level, or a top-level nested atomic action
- */
+ /**
+ * actionInitialise determines whether the BasicAction is a nested,
+ * top-level, or a top-level nested atomic action
+ */
- private final void actionInitialise (BasicAction parent)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ private final void actionInitialise (BasicAction parent)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::actionInitialise() for action-id "
+ get_uid());
}
- criticalStart();
+ criticalStart();
- if (parent != null) /* ie not top_level */
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ if (parent != null) /* ie not top_level */
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("Action "+get_uid()+" with parent status "+parent.actionStatus);
}
- currentHierarchy = new ActionHierarchy(parent.getHierarchy());
- }
- else
- {
- currentHierarchy = new ActionHierarchy(
- ActionHierarchy.DEFAULT_HIERARCHY_DEPTH);
+ currentHierarchy = new ActionHierarchy(parent.getHierarchy());
+ }
+ else
+ {
+ currentHierarchy = new ActionHierarchy(
+ ActionHierarchy.DEFAULT_HIERARCHY_DEPTH);
- /*
- * This is a top-level atomic action so set the signal handler block
- * a number of signals.
- */
- }
+ /*
+ * This is a top-level atomic action so set the signal handler block
+ * a number of signals.
+ */
+ }
- currentHierarchy.add(get_uid(), actionType);
+ currentHierarchy.add(get_uid(), actionType);
- switch (actionType)
- {
- case ActionType.TOP_LEVEL:
- if (parent != null)
- {
- /*
- * do not want to print warning all the time as this is what
- * nested top-level actions are used for.
- */
+ switch (actionType)
+ {
+ case ActionType.TOP_LEVEL:
+ if (parent != null)
+ {
+ /*
+ * do not want to print warning all the time as this is what
+ * nested top-level actions are used for.
+ */
- if (tsLogger.logger.isTraceEnabled()) {
- tsLogger.logger.trace("Running Top Level Action "+get_uid()+" from within " +
- "nested action ("+parent.get_uid()+")");
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("Running Top Level Action "+get_uid()+" from within " +
+ "nested action ("+parent.get_uid()+")");
+ }
}
- }
- break;
- case ActionType.NESTED:
- if (parent == null)
- actionType = ActionType.TOP_LEVEL;
- break;
- }
+ break;
+ case ActionType.NESTED:
+ if (parent == null)
+ actionType = ActionType.TOP_LEVEL;
+ break;
+ }
- parentAction = parent;
+ parentAction = parent;
- criticalEnd();
- }
+ criticalEnd();
+ }
- private final void doForget (RecordList list_toprocess)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ private final void doForget (RecordList list_toprocess)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::doForget ("
+ list_toprocess + ")");
}
- /*
- * If the user has selected to maintain all heuristic information, then
- * we never explicitly tell resources to forget. We assume that the user
- * (or some management tool) will do this, and simply save as much
- * information as we can into the action state to allow them to do so.
- *
- * However, if we had a resource that returned a heuristic outcome and
- * we managed to make the outcome of this transaction the same as that
- * outcome, we removed the heuristic. So, we need to tell the resource
- * regardless, or it'll never be able to tidy up.
- */
+ /*
+ * If the user has selected to maintain all heuristic information, then
+ * we never explicitly tell resources to forget. We assume that the user
+ * (or some management tool) will do this, and simply save as much
+ * information as we can into the action state to allow them to do so.
+ *
+ * However, if we had a resource that returned a heuristic outcome and
+ * we managed to make the outcome of this transaction the same as that
+ * outcome, we removed the heuristic. So, we need to tell the resource
+ * regardless, or it'll never be able to tidy up.
+ */
- boolean force = (boolean) (heuristicDecision == TwoPhaseOutcome.FINISH_OK);
+ boolean force = (boolean) (heuristicDecision == TwoPhaseOutcome.FINISH_OK);
- if (!TxControl.maintainHeuristics || force)
- {
- if (list_toprocess.size() > 0)
- {
- RecordList tmpList = new RecordList();
+ if (!TxControl.maintainHeuristics || force)
+ {
+ if (list_toprocess.size() > 0)
+ {
+ RecordList tmpList = new RecordList();
- while (((recordBeingHandled = list_toprocess.getFront())) != null)
- {
- /*
- * Remember for later if we cannot tell it to forget.
- */
+ while (((recordBeingHandled = list_toprocess.getFront())) != null)
+ {
+ /*
+ * Remember for later if we cannot tell it to forget.
+ */
- if (recordBeingHandled.forgetHeuristic())
- recordBeingHandled = null;
- else
- tmpList.putFront(recordBeingHandled);
- }
+ if (recordBeingHandled.forgetHeuristic())
+ recordBeingHandled = null;
+ else
+ tmpList.putFront(recordBeingHandled);
+ }
- /*
- * Now put those resources we couldn't tell to forget back on
- * the heuristic list.
- */
+ /*
+ * Now put those resources we couldn't tell to forget back on
+ * the heuristic list.
+ */
- if (tmpList.size() > 0)
- {
- while ((recordBeingHandled = tmpList.getFront()) != null)
- list_toprocess.putFront(recordBeingHandled);
- }
- }
- }
- }
+ if (tmpList.size() > 0)
+ {
+ while ((recordBeingHandled = tmpList.getFront()) != null)
+ list_toprocess.putFront(recordBeingHandled);
+ }
+ }
+ }
+ }
- /*
- * Walk down a record list extracting records and calling the appropriate
- * cleanup function. Discard records when done. NOTE: We only need to do
- * cleanup at top level since cleanup at nested level would be subsumed when
- * the parent action is forced to abort
- *
- * Ignore heuristics. Who can we report them to?
- *
- * This routine is called by phase2Cleanup, which gets called only in
- * exceptional circumstances. By default we leave cleaning up the various
- * lists until the action instance goes out of scope.
- */
+ /*
+ * Walk down a record list extracting records and calling the appropriate
+ * cleanup function. Discard records when done. NOTE: We only need to do
+ * cleanup at top level since cleanup at nested level would be subsumed when
+ * the parent action is forced to abort
+ *
+ * Ignore heuristics. Who can we report them to?
+ *
+ * This routine is called by phase2Cleanup, which gets called only in
+ * exceptional circumstances. By default we leave cleaning up the various
+ * lists until the action instance goes out of scope.
+ */
- private final void doCleanup (RecordList list_toprocess)
- {
- if (tsLogger.logger.isTraceEnabled()) {
+ private final void doCleanup (RecordList list_toprocess)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
tsLogger.logger.trace("BasicAction::doCleanup ("
+ list_toprocess + ")");
}
- if (list_toprocess.size() > 0)
- {
- int ok = TwoPhaseOutcome.FINISH_OK;
+ if (list_toprocess.size() > 0)
+ {
+ int ok = TwoPhaseOutcome.FINISH_OK;
- while (((recordBeingHandled = list_toprocess.getFront()) != null))
- {
- if (actionType == ActionType.TOP_LEVEL)
- ok = recordBeingHandled.topLevelCleanup();
- else
- ok = recordBeingHandled.nestedCleanup();
+ while (((recordBeingHandled = list_toprocess.getFront()) != null))
+ {
+ if (actionType == ActionType.TOP_LEVEL)
+ ok = recordBeingHandled.topLevelCleanup();
+ else
+ ok = recordBeingHandled.nestedCleanup();
- if ((actionType != ActionType.TOP_LEVEL)
- && (recordBeingHandled.propagateOnAbort()))
- {
- merge(recordBeingHandled);
- }
- else
- {
- if (ok != TwoPhaseOutcome.FINISH_OK)
- {
- /* Preserve error messages */
- }
+ if ((actionType != ActionType.TOP_LEVEL)
+ && (recordBeingHandled.propagateOnAbort()))
+ {
+ merge(recordBeingHandled);
+ }
+ else
+ {
+ if (ok != TwoPhaseOutcome.FINISH_OK)
+ {
+ /* Preserve error messages */
+ }
- recordBeingHandled = null;
- }
- }
- }
- }
+ recordBeingHandled = null;
+ }
+ }
+ }
+ }
- private final synchronized boolean doOnePhase ()
- {
- if (TxControl.onePhase)
- {
- return (((pendingList == null) || (pendingList.size() == 1)) ? true
- : false);
- }
- else
- return false;
- }
+ private final synchronized boolean doOnePhase ()
+ {
+ if (TxControl.onePhase)
+ {
+ return (((pendingList == null) || (pendingList.size() == 1)) ? true
+ : false);
+ }
+ else
+ return false;
+ }
- /*
- * Operation to merge a record into those held by the parent BasicAction.
- * This is accomplished by invoking the add operation of the parent
- * BasicAction. If the add operation does not return AR_ADDED, the record is
- * deleted
- */
+ /*
+ * Operation to merge a record into those held by the parent BasicAction.
+ * This is accomplished by invoking the add operation of the parent
+ * BasicAction. If the add operation does not return AR_ADDED, the record is
+ * deleted
+ */
- private final synchronized void merge (AbstractRecord A)
- {
- int as;
+ private final synchronized void merge (AbstractRecord A)
+ {
+ int as;
- if ((as = parentAction.add(A)) != AddOutcome.AR_ADDED)
- {
- A = null;
+ if ((as = parentAction.add(A)) != AddOutcome.AR_ADDED)
+ {
+ A = null;
if (as == AddOutcome.AR_REJECTED)
tsLogger.i18NLogger.warn_coordinator_BasicAction_68();
- }
- }
+ }
+ }
- /* These (genuine) lists hold the abstract records */
+ /* These (genuine) lists hold the abstract records */
- protected RecordList pendingList;
- protected RecordList preparedList;
- protected RecordList readonlyList;
- protected RecordList failedList;
- protected RecordList heuristicList;
- protected boolean savedIntentionList;
-
- private ActionHierarchy currentHierarchy;
- private ParticipantStore participantStore;
+ protected RecordList pendingList;
+ protected RecordList preparedList;
+ protected RecordList readonlyList;
+ protected RecordList failedList;
+ protected RecordList heuristicList;
+ protected boolean savedIntentionList;
- // private boolean savedIntentionList;
+ private ActionHierarchy currentHierarchy;
+ private ParticipantStore participantStore;
- /* Atomic action status variables */
+ // private boolean savedIntentionList;
- private int actionStatus;
- private int actionType;
- private BasicAction parentAction;
- private AbstractRecord recordBeingHandled;
- private int heuristicDecision;
- private CheckedAction _checkedAction; // control what happens if threads active when terminating.
+ /* Atomic action status variables */
- /*
- * We need to keep track of the number of threads associated with each
- * action. Since we can't override the basic thread methods, we have to
- * provide an explicit means of registering threads with an action.
- */
+ private int actionStatus;
+ private int actionType;
+ private BasicAction parentAction;
+ private AbstractRecord recordBeingHandled;
+ private int heuristicDecision;
+ private CheckedAction _checkedAction; // control what happens if threads active when terminating.
- private Hashtable _childThreads;
- private Hashtable _childActions;
+ /*
+ * We need to keep track of the number of threads associated with each
+ * action. Since we can't override the basic thread methods, we have to
+ * provide an explicit means of registering threads with an action.
+ */
- // private Mutex _lock = new Mutex(); // TODO
-
- private static CheckedActionFactory _checkedActionFactory = arjPropertyManager.getCoordinatorEnvironmentBean().getCheckedActionFactory();
+ private Hashtable _childThreads;
+ private Hashtable _childActions;
+
+ // private Mutex _lock = new Mutex(); // TODO
+
+ private static CheckedActionFactory _checkedActionFactory = arjPropertyManager.getCoordinatorEnvironmentBean().getCheckedActionFactory();
}
More information about the jboss-svn-commits
mailing list