package org.jboss.jbossts.xts.recovery.coordinator.ba; import org.jboss.jbossts.xts.recovery.logging.RecoveryLogger; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.ats.arjuna.coordinator.ActionStatus; import com.arjuna.ats.arjuna.coordinator.RecordListIterator; import com.arjuna.ats.arjuna.coordinator.AbstractRecord; import com.arjuna.mwlabs.wscf.model.sagas.arjunacore.BACoordinator; import com.arjuna.mwlabs.wscf.model.sagas.arjunacore.ParticipantRecord; /** * This class is a plug-in module for the recovery manager. * It is responsible for recovering failed WSBA ACCoordinator transactions. * */ public class RecoveryBACoordinator extends BACoordinator { /** * Re-creates/activates an AtomicAction for the specified * transaction Uid. */ public RecoveryBACoordinator( Uid rcvUid ) { super( rcvUid ) ; _activated = activate() ; if (_activated) { setRecoveryCoordinator(); } } /** * provide the recovered participants with a handle on this coordinator so they can * propagate events through to it. */ public void setRecoveryCoordinator() { if (preparedList != null) { RecordListIterator iter = new RecordListIterator(preparedList); AbstractRecord absRec = iter.iterate(); while (absRec != null) { if (absRec instanceof ParticipantRecord) { ParticipantRecord pr = (ParticipantRecord) absRec; } absRec = iter.iterate(); } } } /** * Replays phase 2 of the commit protocol. */ public void replayPhase2() { final int status = status(); if (RecoveryLogger.logger.isDebugEnabled()) { RecoveryLogger.logger.debugv("RecoveryBACoordinator.replayPhase2 recovering {0} ActionStatus is {1}", new Object[]{get_uid(), ActionStatus.stringForm(status)}); } if ( _activated ) { // we only need to rerun phase2 if the action status is PREPARED, which happens // when we crash between a successful complete beginning a close, or COMMITTING, which // happens when we get a comms timeout from one of the participants after sending it a CLOSE // message. in the former case all participant records will be listed in the prepared list. // in the latter case the failed participant record(s) will have been reinstated in the // prepared list and the participant stub engine reactivated, where necessary, // under the call to activate() when this coordinator was created. // we can also arrive here when the action status is ABORTING. This happens when we // get a comms timeout from one of the participants after sending it a CANCEL message // or if we get a comms timeout from one of the participants after sending it a COMPENSATE // message. if ((status == ActionStatus.PREPARED) || (status == ActionStatus.COMMITTING) || (status == ActionStatus.COMMITTED) || (status == ActionStatus.H_COMMIT) || (status == ActionStatus.H_MIXED) || (status == ActionStatus.H_HAZARD)) { super.phase2Commit( _reportHeuristics ) ; } else if ((status == ActionStatus.ABORTED) || (status == ActionStatus.H_ROLLBACK) || (status == ActionStatus.ABORTING) || (status == ActionStatus.ABORT_ONLY)) { super.phase2Abort( _reportHeuristics ) ; } if (RecoveryLogger.logger.isDebugEnabled()) { RecoveryLogger.logger.debugv("RecoveryBACoordinator.replayPhase2( {0} ) finished", new Object[]{get_uid()}); } } else { RecoveryLogger.i18NLogger.warn_coordinator_ba_RecoveryBACoordinator_4(get_uid()); } } // Flag to indicate that this transaction has been re-activated // successfully. private boolean _activated = false ; // whether heuristic reporting on phase 2 commit is enabled. private boolean _reportHeuristics = true ; }