[jboss-svn-commits] JBL Code SVN: r24887 - labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jan 23 09:12:56 EST 2009
Author: adinn
Date: 2009-01-23 09:12:56 -0500 (Fri, 23 Jan 2009)
New Revision: 24887
Modified:
labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ACCoordinator.java
labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ParticipantRecord.java
Log:
fixed BA recovery so that arjunacore runs prepare and commit at close rather than splitting them between complete and close -- fixes JBTM-471
Modified: labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ACCoordinator.java
===================================================================
--- labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ACCoordinator.java 2009-01-23 12:12:19 UTC (rev 24886)
+++ labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ACCoordinator.java 2009-01-23 14:12:56 UTC (rev 24887)
@@ -52,14 +52,17 @@
import com.arjuna.mw.wscf.exceptions.*;
/**
- * This class represents a specific coordination instance. It is essentially an
- * ArjunaCore BasicAction which gives us independent prepare, commit and abort
- * without synchronization support and without thread management. We don't
- * inherit from TwoPhaseCoordinator because we don't ever initiate a 2phase
- * operation directly -- we map the BA Termination protocol complete message
- * to prepare, the close message to commit and the cancel to abort so these
- * operations are decoupled actions. Also, since we don't call end we cannot
- * usefully use the synchronization support (not that we need it anyway).
+ * This class represents a specific coordination instance. It inherits from
+ * ArjunaCore TwoPhaseCoordinator so we can do the prepare and commit when a
+ * BA client close is requested and have it roll back if anything goes wrong.
+ * The BA client cancel request maps through to TwoPhaseCoordinator cancel which
+ * also does what we need. Although we inherit synchronization support from
+ * TwoPhaseCoordinator it is not used by the BA code.
+ *
+ * This class also exposes a separate complete method which implements
+ * the deprectaed BA client complete operation allowing coordinator completion
+ * participants to be notified that they complete. This is pretty much redundant
+ * as complete gets called at close anyway.
*
* @author Mark Little (mark.little at arjuna.com)
* @version $Id: ACCoordinator.java,v 1.5 2005/05/19 12:13:37 nmcl Exp $
@@ -67,24 +70,16 @@
*
* @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_1
* [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_1] -
- * Cannot complete business activity until all ParticipantCompletion participants have completed
+ * Participant failed to complete in activity {1}
* @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_2
* [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_2] -
* Null is an invalid parameter.
* @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_3
* [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_3] -
* Wrong state for operation!
- * @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_4
- * [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_4] -
- * Complete of action-id {0} failed.
- * @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_5
- * [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_5] - Received
- * heuristic: {0} .
- * @message com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_6
- * [com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_6] - Action marked as AbortOnly {0}.
*/
-public class ACCoordinator extends BasicAction
+public class ACCoordinator extends TwoPhaseCoordinator
{
private final static int DELISTED = 0;
@@ -135,52 +130,6 @@
}
/**
- * start the transaction
- *
- * @param parentAction
- * @return
- */
- public int start (BasicAction parentAction)
- {
- if (parentAction != null)
- parentAction.addChildAction(this);
-
- return super.Begin(parentAction);
- }
-
- /**
- * ensure that none of required participants are still active throwing a SystemException if they are
- * @param allParticipants true if no participants, including CooordinatorCompletion participants,
- * may still be active and false if only CooordinatorCompletion participants may still be active.
- * @throws SystemException if any of the required participants has not completed.
- */
- void ensureNotActive(boolean allParticipants) throws SystemException
- {
- if (pendingList != null)
- {
- RecordListIterator iter = new RecordListIterator(pendingList);
- AbstractRecord absRec = iter.iterate();
-
- while (absRec != null)
- {
- if (absRec instanceof ParticipantRecord)
- {
- ParticipantRecord pr = (ParticipantRecord) absRec;
-
- if ((allParticipants || pr.isParticipantCompletion()) && pr.isActive())
- {
- throw new SystemException(
- wscfLogger.log_mesg
- .getString("com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_1"));
- }
- }
-
- absRec = iter.iterate();
- }
- }
- }
-
- /**
* ensure all ParticipantCompletion participants have completed and then send a complete message to
* any remaining CoordinatorCompletion participants.
* @throws WrongStateException if the transaction is neither RUNNING nor PREPARED
@@ -197,178 +146,57 @@
// check that all ParticipantCompletion participants have completed
// throwing a wobbly if not
- ensureNotActive(false);
-
- doComplete();
-
- }
- else
- {
- throw new WrongStateException();
- }
- }
-
- /**
- * invoke the prepare operation in order to drive all CoordinatorCompletion participants to completion
- * @throws SystemException if any of the participants fails to complete
- */
- private void doComplete() throws SystemException
- {
- // we can emerge from this with outcome PREPARE_NOTOK if one of the CoordinatorCompletion participants
- // failed to respond to a completed request. in that case the action status will be PREPARING
- int outcome = super.prepare(true);
-
- if (outcome == TwoPhaseOutcome.PREPARE_NOTOK) {
- if (wscfLogger.arjLoggerI18N.isWarnEnabled())
+ if (pendingList != null)
{
- wscfLogger.arjLoggerI18N.warn("com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_4", new Object[] { get_uid() });
- }
+ RecordListIterator iter = new RecordListIterator(pendingList);
+ AbstractRecord absRec = iter.iterate();
- int heuristicDecision = getHeuristicDecision();
-
- if (heuristicDecision != TwoPhaseOutcome.PREPARE_OK)
- {
- if (wscfLogger.arjLoggerI18N.isWarnEnabled())
+ while (absRec != null)
{
- wscfLogger.arjLoggerI18N.warn("com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_5", new Object[] { TwoPhaseOutcome.stringForm(heuristicDecision) });
- }
- }
+ if (absRec instanceof ParticipantRecord)
+ {
+ ParticipantRecord pr = (ParticipantRecord) absRec;
- if (wscfLogger.arjLoggerI18N.isWarnEnabled())
- {
- wscfLogger.arjLoggerI18N.warn("com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_6",new Object[] { get_uid() });
- }
+ if (!pr.complete()) {
- }
- }
+ // ok, we must force a rollback
- /**
- * if all is well with the TX invoke the phase2Commit operation in order to drive all participants to
- * closed status, if not invoke Abort.
- * @return the outcome of the commit or abort
- * @throws SystemException if there are _any_ uncompleted participants, either because the client has
- * not called close to close CoordinatorCompletion participants or because not all ParticipantCompletion
- * participants have notified completion.
- */
- public int close () throws SystemException
- {
- int outcome;
+ preventCommit();
- if (parent() != null)
- parent().removeChildAction(this);
+ wscfLogger.arjLoggerI18N.warn("com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ACCoordinator_1", new Object[] { get_uid() });
- if (status() == ActionStatus.RUNNING) {
- // check that _all_ participants have completed throwing a SystemException if not
+ throw new SystemException("Participant failed to complete");
+ }
+ }
- ensureNotActive(true);
-
- // ok, we do a complete anyway to ensure we log the participant list and progress to state
- // PREPARED. this should not fail since the participants ought to just say yeah yeah whateva
-
- doComplete();
- }
-
- switch (status()) {
- case ActionStatus.PREPARING:
- {
- // we failed during prepare so we have to do a phase2Abort in order to clean up
- // this means we may end up leaving a log entry for an aborted transaction with
- // a heuristic outcome
- super.phase2Abort(true);
- outcome = status();
- }
- break;
- // we managed to prepare so we need to do a phase2Commit
- case ActionStatus.PREPARED:
- case ActionStatus.COMMITTING:
- {
- if (parent() != null)
- parent().removeChildAction(this);
-
- super.phase2Commit(true);
- // remap the status if there are heuristics
- outcome = status();
- int heuristicDecision = getHeuristicDecision();
-
- switch (heuristicDecision)
- {
- case TwoPhaseOutcome.PREPARE_OK:
- case TwoPhaseOutcome.FINISH_OK:
- break;
- case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
- outcome = ActionStatus.H_ROLLBACK;
- case TwoPhaseOutcome.HEURISTIC_COMMIT:
- outcome = ActionStatus.H_COMMIT;
- case TwoPhaseOutcome.HEURISTIC_MIXED:
- outcome = ActionStatus.H_MIXED;
- case TwoPhaseOutcome.HEURISTIC_HAZARD:
- default:
- outcome = ActionStatus.H_HAZARD;
+ absRec = iter.iterate();
}
}
- break;
- // this covers the case where the tx is marked as ABORT_ONLY
- default:
- {
- if (parent() != null)
- parent().removeChildAction(this);
-
- // no heuristics to deal with
-
- outcome = super.Abort();
- }
+ }
+ else
+ {
+ throw new WrongStateException();
}
-
- return outcome;
}
/**
- * invoke Abort.
- * @return the outcome of the abort
+ * close the activity
+ * @return
+ * @throws SystemException
*/
- public int cancel ()
+ public int close () throws SystemException
{
- // we cannot do this as per TwoPhaseCoordinator because TxControl and TxStats are package private
- // but note that JTS does not count this either
- //if (TxControl.enableStatistics)
- // TxStats.incrementApplicationRollbacks();
-
- if (parent() != null)
- parent().removeChildAction(this);
-
- int outcome;
-
- switch (status()) {
-
- // PREPARING/PREPARED/COMMITTING mean we have committed or tried to commit in which case we
- // may have entries in the pending and prepared lists and we may have written a log record
- // which we need to update. it also means we can end up leaving a log entry for an aborted
- // transaction with a heuristic outcome
-
- case ActionStatus.PREPARING:
- case ActionStatus.PREPARED:
- case ActionStatus.COMMITTING:
- {
- super.phase2Abort(true);
- outcome = status();
- }
- break;
- // RUNNING or ABORT_ONLY means we never got to commit so we can just do a normal abort
- case ActionStatus.RUNNING:
- case ActionStatus.ABORT_ONLY:
- {
- outcome = super.Abort();
- }
- break;
- // nothing to do if we are in any other state
- default:
- {
- outcome = status();
- }
- break;
+ // we need to make sure all coordinator completion aprticipants ahve completed
+ try {
+ complete();
+ } catch (Exception e) {
+ // carry on as end will catch any further problems
}
- return outcome;
+ // now call end(). if any of the participant completion participants are not
+ // completed they will throw a WrongStateException during prepare leading to rollback
+
+ return end(true);
}
/**
Modified: labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ParticipantRecord.java
===================================================================
--- labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ParticipantRecord.java 2009-01-23 12:12:19 UTC (rev 24886)
+++ labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/sagas/arjunacore/ParticipantRecord.java 2009-01-23 14:12:56 UTC (rev 24887)
@@ -387,21 +387,20 @@
try
{
boolean result;
- // only complete if we have not exited
- if (!_exited) {
- result = complete();
- } else {
- result = false;
- }
- // if we have failed we return heuristic hazard so the participant is added to
- // the heuristic list and the transaction is logged
+ if (_failed) {
+ // if we have failed we return heuristic hazard so the participant is added to
+ // the heuristic list and the transaction is logged
- if (_failed) {
return TwoPhaseOutcome.HEURISTIC_HAZARD;
} else if (_exited) {
+ // otherwise if we have exited then this means the resource is read only
+
return TwoPhaseOutcome.PREPARE_READONLY;
} else {
- return (result ? TwoPhaseOutcome.PREPARE_OK: TwoPhaseOutcome.PREPARE_NOTOK);
+ // otherwise we only need to have completed for the prepare to be ok -- if we have
+ // not completed then the prepare is not ok
+
+ return (_completed ? TwoPhaseOutcome.PREPARE_OK: TwoPhaseOutcome.PREPARE_NOTOK);
}
}
catch (Exception e6)
@@ -465,6 +464,10 @@
{
if (_resourceHandle != null)
{
+ // we cannot proceed if the participant has not completed
+
+ if (!_completed) return TwoPhaseOutcome.FINISH_ERROR;
+
try
{
if (!_exited) _resourceHandle.close();
More information about the jboss-svn-commits
mailing list