Durable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / TransactionBridge / Microsoft / Transactions / Wsat / StateMachines / Durable.cs / 1 / Durable.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

// This file contains the implementation of the various states used by 
// the durable TwoPhaseCommit participant state machine
 
using System; 
using System.Diagnostics;
using System.ServiceModel.Channels; 

using Microsoft.Transactions.Bridge;
using Microsoft.Transactions.Wsat.InputOutput;
using Microsoft.Transactions.Wsat.Messaging; 
using Microsoft.Transactions.Wsat.Protocol;
using Microsoft.Transactions.Wsat.Recovery; 
 
using DiagnosticUtility = Microsoft.Transactions.Bridge.DiagnosticUtility;
 
namespace Microsoft.Transactions.Wsat.StateMachines
{
    //=============================================================================
    // DurableRegistering 
    //
    // A participant registered for durable 2PC 
    // We asked the TM to create a new subordinate enlistment 
    //=============================================================================
    class DurableRegistering : InactiveState 
    {
        public DurableRegistering (ProtocolState state) : base (state) {}

        public override void OnEvent(TmRegisterResponseEvent e) 
        {
            ProcessTmRegisterResponse(e); 
 
            if (e.Status == Status.Success)
            { 
                e.StateMachine.ChangeState(state.States.DurableActive);
            }
            else
            { 
                e.StateMachine.ChangeState(state.States.DurableInitializationFailed);
            } 
        } 
    }
 
    //==============================================================================
    // DurableActive
    //
    // The TM created a subordinate enlistment and success was sent to the registrant 
    //=============================================================================
    class DurableActive : ActiveState 
    { 
        public DurableActive (ProtocolState state) : base (state) {}
 
        // Unsolicited ReadOnly
        public override void OnEvent(MsgReadOnlyEvent e)
        {
            e.StateMachine.ChangeState(state.States.DurableUnregistered); 
        }
 
        // Unsolicited Aborted 
        public override void OnEvent(MsgAbortedEvent e)
        { 
            state.TransactionManagerSend.Rollback (e.Participant);
            e.StateMachine.ChangeState(state.States.DurableAborted);
        }
 
        // The WS-AT 1.0 state machines dictate a polite answer for Replay
        // System.Transactions allows a durable participant to receive a phase zero prepare 
        // instead of a phase one prepare. This implies that it might attempt to recover while 
        // the coordinator is still active, since System.Transactions will register a volatile
        // for the phase zero prepare. 
        //
        // We wouldnt want the participant to receive a fault when it should really
        // receive a polite Rollback message.
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableActive), "OnEvent(replay)"); 
            ParticipantEnlistment participant = e.Participant; 
            state.TwoPhaseCommitCoordinator.SendRollback (participant);
 
            state.TransactionManagerSend.Rollback (participant);
            e.StateMachine.ChangeState(state.States.DurableAborted);
        }
 
        public override void OnEvent(TmPrepareEvent e)
        { 
            ParticipantEnlistment participant = e.Participant; 

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TwoPhaseCommitCoordinator.SendPrepare (participant);

            e.StateMachine.ChangeState(state.States.DurablePreparing);
        } 

        public override void OnEvent(TmRollbackEvent e) 
        { 
            ParticipantEnlistment participant = e.Participant;
            state.TwoPhaseCommitCoordinator.SendRollback (participant); 

            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Aborted(participant);
 
            e.StateMachine.ChangeState(state.States.DurableAborted);
        } 
    } 

    //============================================================================== 
    // DurableUnregistered
    //
    // The participant sent an unsolicited readonly and "unregistered" from the transaction
    // This is an active state because we can still abort 
    //==============================================================================
    class DurableUnregistered : ActiveState 
    { 
        public DurableUnregistered (ProtocolState state) : base (state) {}
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgReadOnlyEvent e)
        {
            return; 
        }
 
        // Deliver the ReadOnly we're been saving up 
        public override void OnEvent(TmPrepareEvent e)
        { 
            ParticipantEnlistment participant = e.Participant;

            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ReadOnly (participant); 

            e.StateMachine.ChangeState(state.States.DurableInDoubt); 
        } 

        public override void OnEvent(TmRollbackEvent e) 
        {
            ParticipantEnlistment participant = e.Participant;

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant);
 
            e.StateMachine.ChangeState(state.States.DurableAborted); 
        }
    } 

    //=============================================================================
    // DurablePreparing
    // 
    // The TM told us to prepare. We told the participant to prepare
    //============================================================================== 
    class DurablePreparing : ActiveState 
    {
        public DurablePreparing (ProtocolState state) : base (state) {} 

        public override void Enter (StateMachine stateMachine)
        {
            base.Enter (stateMachine); 

            // Set send Prepare time for performance counter 
            ((ParticipantEnlistment)stateMachine.Enlistment).LastMessageTime = State.QueryStartTime(); 

            // Start up a Prepare timer 
            stateMachine.StartTimer (TimerProfile.Preparing);
        }

        public override void Leave (StateMachine stateMachine) 
        {
            base.Leave (stateMachine); 
 
            ParticipantEnlistment participant = (ParticipantEnlistment) stateMachine.Enlistment;
 
            long elapsed = State.QueryStopTime() - participant.LastMessageTime;
            state.Perf.AverageParticipantPrepareResponseTimeBase.Increment();
            state.Perf.AverageParticipantPrepareResponseTime.IncrementBy(elapsed);
 
            // Cancel the Prepare timer
            participant.Retries = 0; 
            stateMachine.CancelTimer(); 
        }
 
        public override void OnEvent(MsgReadOnlyEvent e)
        {
            state.TransactionManagerSend.ReadOnly (e.Participant);
            e.StateMachine.ChangeState(state.States.DurableInDoubt); 
        }
 
        public override void OnEvent(MsgPreparedEvent e) 
        {
            ParticipantEnlistment participant = e.Participant; 

            Exception failed = null;
            try
            { 
                byte[] recovery = state.LogEntrySerialization.Serialize(participant);
                participant.Enlistment.SetRecoveryData (recovery); 
 
                state.TransactionManagerSend.Prepared (participant);
                e.StateMachine.ChangeState(state.States.DurablePrepared); 

            }
            catch (SerializationException exception)
            { 
                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                failed = exception; 
            } 

            if (failed != null) 
            {
                if (DebugTrace.Error)
                    DebugTrace.Trace(TraceLevel.Verbose,
                                     "Failed to serialize log entry for participant: {0}", 
                                     failed);
 
                ParticipantRecoveryLogEntryCreationFailureRecord.TraceAndLog( 
                    participant.EnlistmentId,
                    participant.Enlistment.RemoteTransactionId, 
                    failed.Message,
                    failed
                    );
 
                // We react to serialization failures by aborting the transaction
                state.TwoPhaseCommitCoordinator.SendRollback (participant); 
 
                state.TransactionManagerSend.Aborted(participant);
                e.StateMachine.ChangeState(state.States.DurableAborted); 
            }
        }

        public override void OnEvent(MsgAbortedEvent e) 
        {
            state.TransactionManagerSend.Aborted(e.Participant); 
            e.StateMachine.ChangeState(state.States.DurableAborted); 
        }
 
        // We might also receive a Replay in this state, but we're going to call that a failure
        //
        // We abort the transaction if this occurs.  We never received a Prepared message
        // from this participant, and we don't really know what could have happened to it. 
        // There are cases where the participant might write a Prepared log record, then
        // try to send Prepared, fail, decide to abort and fail.  An RM would generally write 
        // an abort log record before performing undo steps, but a TM can optimize the log write 
        // by neglecting to write an abort record and simply forgetting its local state. If the TM
        // were to fail after, say, having sent rollbacks to half of its participants, it would wake 
        // up in an indoubt state with respect to that transaction.
        //
        // In these cases, the participant relies on us to keep it straight.
        // 
        // The sad thing is that there are legitimate cases where this pattern could occur.  If the
        // participant's Prepared response were lost and then the participant failed, we would 
        // see this message in this state.  Unfortunately, we can't tell the difference between 
        // a legitimate replay and the case described above.
 
        public override void OnEvent(MsgReplayEvent e)
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurablePreparing), "OnEvent(replay)");
 
            ParticipantEnlistment participant = e.Participant;
 
            if (DurableParticipantReplayWhilePreparingRecord.ShouldTrace) 
            {
                DurableParticipantReplayWhilePreparingRecord.Trace ( 
                    participant.EnlistmentId,
                    participant.Enlistment.RemoteTransactionId
                    );
            } 

            state.TwoPhaseCommitCoordinator.SendRollback (participant); 
 
            state.TransactionManagerSend.Aborted(participant);
            e.StateMachine.ChangeState(state.States.DurableAborted); 
        }

        // Async rollback from the TM...  Could be a timeout, could be another participant aborting
        public override void OnEvent(TmRollbackEvent e) 
        {
            ParticipantEnlistment participant = e.Participant; 
            state.TwoPhaseCommitCoordinator.SendRollback (participant); 

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant);

            e.StateMachine.ChangeState(state.States.DurableAborted);
        } 

        public override void OnEvent(TimerParticipantEvent e) 
        { 
            ParticipantEnlistment participant = e.Participant;
            participant.Retries ++; 

            if (PrepareMessageRetryRecord.ShouldTrace)
            {
                PrepareMessageRetryRecord.Trace ( 
                    participant.EnlistmentId,
                    participant.Enlistment.RemoteTransactionId, 
                    participant.Retries 
                    );
            } 

            state.Perf.PrepareRetryCountPerInterval.Increment();

            // Send another prepare message 
            state.TwoPhaseCommitCoordinator.SendPrepare (participant);
        } 
    } 

    //============================================================================= 
    // DurablePrepared
    //
    // The participant said prepared. We told the TM prepared
    //============================================================================= 
    class DurablePrepared : DecidedState
    { 
        public DurablePrepared (ProtocolState state) : base (state) {} 

        // Tolerate duplicate messages 
        public override void OnEvent(MsgPreparedEvent e)
        {
            return;
        } 

        // We will deliver outcome when we're ready 
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurablePrepared), "OnEvent(replay)"); 
            return;
        }

        public override void OnEvent(TmCommitEvent e) 
        {
            ParticipantEnlistment participant = e.Participant; 
            state.TwoPhaseCommitCoordinator.SendCommit (participant); 

            participant.SetCallback(e.Callback, e.CallbackState); 
            e.StateMachine.ChangeState(state.States.DurableCommitting);
        }

        public override void OnEvent(TmRollbackEvent e) 
        {
            ParticipantEnlistment participant = e.Participant; 
            state.TwoPhaseCommitCoordinator.SendRollback (participant); 

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant);

            e.StateMachine.ChangeState(state.States.DurableAborted);
        } 

        public override void OnEvent(TimerParticipantEvent e) 
        { 
            return;
        } 
    }

    //=============================================================================
    // DurableCommitting 
    //
    // The participant has been instructed to commit 
    //============================================================================== 
    class DurableCommitting : DecidedState
    { 
        public DurableCommitting (ProtocolState state) : base (state) {}

        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine);
 
            // Set send Commit time for performance counter 
            ((ParticipantEnlistment) stateMachine.Enlistment).LastMessageTime = State.QueryStartTime();
 
            // Start up a Commit timer
            stateMachine.StartTimer (TimerProfile.Committing);
        }
 
        public override void Leave (StateMachine stateMachine)
        { 
            base.Leave (stateMachine); 

            long elapsed = 
                State.QueryStopTime() - ((ParticipantEnlistment)stateMachine.Enlistment).LastMessageTime;

            state.Perf.AverageParticipantCommitResponseTimeBase.Increment();
            state.Perf.AverageParticipantCommitResponseTime.IncrementBy(elapsed); 

            // Cancel the Commit timer 
            stateMachine.CancelTimer(); 
        }
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgPreparedEvent e)
        {
            state.TwoPhaseCommitCoordinator.SendCommit (e.Participant); 
        }
 
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableCommitting), "OnEvent(replay)"); 
            state.TwoPhaseCommitCoordinator.SendCommit (e.Participant);
        }

        public override void OnEvent(MsgCommittedEvent e) 
        {
            state.TransactionManagerSend.Committed (e.Participant); 
            e.StateMachine.ChangeState(state.States.DurableCommitted); 
        }
 
        public override void OnEvent(TmParticipantForgetEvent e)
        {
            ParticipantEnlistment participant = e.Participant;
 
            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ForgetResponse(participant, Status.Success); 
 
            e.StateMachine.ChangeState(state.States.DurableInDoubt);
        } 

        public override void OnEvent(TimerParticipantEvent e)
        {
            // This reminder be from a preparing timer, in which case we'll ignore it 
            if (e.Profile == TimerProfile.Committing)
            { 
                ParticipantEnlistment participant = e.Participant; 
                participant.Retries ++;
 
                if (CommitMessageRetryRecord.ShouldTrace)
                {
                    CommitMessageRetryRecord.Trace (
                        participant.EnlistmentId, 
                        participant.Enlistment.RemoteTransactionId,
                        participant.Retries 
                        ); 
                }
 
                state.Perf.CommitRetryCountPerInterval.Increment();

                // Resend the commit
                state.TwoPhaseCommitCoordinator.SendCommit (participant); 
            }
        } 
    } 

    //============================================================================= 
    // DurableRecovering
    //
    // During recovery, we received a rejoin message from the TM
    //============================================================================== 
    class DurableRecovering : InactiveState
    { 
        public DurableRecovering (ProtocolState state) : base (state) {} 

        public override void OnEvent(TmRejoinEvent e) 
        {
            if (!state.Recovering)
            {
                // Being here outside of recovery is impossible. 
                // This only safe thing to do is crash so that
                // we don't corrupt any transaction state. 
                DiagnosticUtility.FailFast("Rejoin events should only be delivered during recovery"); 
            }
 
            ParticipantEnlistment participant = e.Participant;

            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Rejoined (participant); 

            e.StateMachine.ChangeState(state.States.DurableRejoined); 
        } 
    }
 
    //==============================================================================
    // DurableRejoined
    //
    // We finished rejoining and await outcome 
    // We might receive network messages too
    //============================================================================= 
    class DurableRejoined : DecidedState 
    {
        public DurableRejoined (ProtocolState state) : base (state) {} 

        // We will deliver outcome when we're ready
        public override void OnEvent(MsgPreparedEvent e)
        { 
            return;
        } 
 
        // We will deliver outcome when we're ready
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableRejoined), "OnEvent(replay)");
            return;
        } 

        public override void OnEvent(MsgCommittedEvent e) 
        { 
            return;
        } 

        public override void OnEvent(MsgAbortedEvent e)
        {
            return; 
        }
 
        public override void OnEvent(TmCommitEvent e) 
        {
            // If we're still recovering, put the event in the recovery queue 
            if (state.Recovering && state.TryEnqueueRecoveryOutcome (e))
            {
                e.StateMachine.ChangeState(state.States.DurableRecoveryAwaitingCommit);
            } 
            else
            { 
                e.Participant.SetCallback(e.Callback, e.CallbackState); 
                e.StateMachine.ChangeState(state.States.DurableRecoveryReceivedCommit);
            } 
        }

        public override void OnEvent(TmRollbackEvent e)
        { 
            // If we're still recovering, put the event in the recovery queue
            if (state.Recovering && state.TryEnqueueRecoveryOutcome (e)) 
            { 
                e.StateMachine.ChangeState(state.States.DurableRecoveryAwaitingRollback);
            } 
            else
            {
                e.Participant.SetCallback(e.Callback, e.CallbackState);
                e.StateMachine.ChangeState(state.States.DurableRecoveryReceivedRollback); 
            }
        } 
    } 

    //============================================================================== 
    // DurableRecoveryAwaitingCommit
    //
    // We enqueued a commit outcome from the TM in the recovery queue
    //============================================================================= 
    class DurableRecoveryAwaitingCommit : DecidedState
    { 
        public DurableRecoveryAwaitingCommit (ProtocolState state) : base (state) {} 

        // We will deliver outcome when we're ready 
        public override void OnEvent(MsgPreparedEvent e)
        {
            return;
        } 

        // We will deliver outcome when we're ready 
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableRecoveryAwaitingCommit), "OnEvent(replay)"); 
            return;
        }

        public override void OnEvent(MsgCommittedEvent e) 
        {
            // We must have sent a commit to the participant in a previous life 
            e.StateMachine.ChangeState(state.States.DurableCommitted); 
        }
 
        // This is a repost sent when recovery ended
        public override void OnEvent(TmCommitEvent e)
        {
            if (state.Recovering) 
            {
                // Being here inside of recovery is impossible. 
                // This only safe thing to do is crash so that 
                // we don't corrupt any transaction state.
                DiagnosticUtility.FailFast("Rejoin events should only be re-delivered after recovery"); 
            }

            e.Participant.SetCallback(e.Callback, e.CallbackState);
            e.StateMachine.ChangeState(state.States.DurableRecoveryReceivedCommit); 
        }
 
        public override void OnEvent(TmParticipantForgetEvent e) 
        {
            ParticipantEnlistment participant = e.Participant; 

            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ForgetResponse(participant, Status.Success);
 
            e.StateMachine.ChangeState(state.States.DurableInDoubt);
        } 
    } 

    //============================================================================= 
    // DurableRecoveryReceivedCommit
    //
    // We recovered a participant enlistment, and the TM told us to commit
    //============================================================================= 
    class DurableRecoveryReceivedCommit : DecidedState
    { 
        public DurableRecoveryReceivedCommit(ProtocolState state) : base(state) {} 

        public override void Enter(StateMachine stateMachine) 
        {
            ParticipantEnlistment participant = (ParticipantEnlistment) stateMachine.Enlistment;

            // Ensure our proxy has a proper 'from' 
            participant.CreateCoordinatorService();
 
            // Send our participant a commit 
            state.TwoPhaseCommitCoordinator.SendCommit(participant);
 
            // We'll ack the TM later, when the participant responds
            stateMachine.ChangeState(state.States.DurableCommitting);
        }
    } 

    //============================================================================== 
    // DurableRecoveryAwaitingRollback 
    //
    // We enqueued a rollback outcome from the TM in the recovery queue 
    //=============================================================================
    class DurableRecoveryAwaitingRollback : DecidedState
    {
        public DurableRecoveryAwaitingRollback (ProtocolState state) : base (state) {} 

        // We will deliver outcome when we're ready 
        public override void OnEvent(MsgPreparedEvent e) 
        {
            return; 
        }

        // We'll deliver outcome when we receive our TmRollbackEvent repost
        public override void OnEvent(MsgReplayEvent e) 
        {
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableRecoveryAwaitingRollback), "OnEvent(replay)"); 
            return; 
        }
 
        // We must have sent a rollback to the participant in a previous life
        public override void OnEvent(MsgAbortedEvent e)
        {
            e.StateMachine.ChangeState(state.States.DurableAborted); 
        }
 
        // This is a repost sent when recovery ended 
        public override void OnEvent(TmRollbackEvent e)
        { 
            e.Participant.SetCallback(e.Callback, e.CallbackState);
            e.StateMachine.ChangeState(state.States.DurableRecoveryReceivedRollback);
        }
    } 

    //============================================================================== 
    // DurableRecoveryReceivedRollback 
    //
    // We recovered a participant enlistment, and the TM told us to rollback 
    //==============================================================================
    class DurableRecoveryReceivedRollback : DecidedState
    {
        public DurableRecoveryReceivedRollback(ProtocolState state) : base(state) {} 

        public override void Enter(StateMachine stateMachine) 
        { 
            ParticipantEnlistment participant = (ParticipantEnlistment) stateMachine.Enlistment;
 
            // Ensure our proxy has a proper 'from'
            participant.CreateCoordinatorService();

            // Send our participant a rollback 
            state.TwoPhaseCommitCoordinator.SendRollback (participant);
 
            // Ack the TM 
            state.TransactionManagerSend.Aborted(participant);
 
            stateMachine.ChangeState(state.States.DurableAborted);
        }
    }
 
    //=============================================================================
    // DurableFailedRecovery 
    // 
    // We failed to create a proxy during recovery, so we sit idle and wait
    // On restart, perhaps we will have better luck with policy negotiation 
    //==============================================================================
    class DurableFailedRecovery : DecidedState
    {
        public DurableFailedRecovery (ProtocolState state) : base (state) {} 

        public override void OnEvent(TmRejoinEvent e) 
        { 
            ParticipantEnlistment participant = e.Participant;
 
            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Rejoined(participant);
        }
 
        public override void OnEvent(TmCommitEvent e)
        { 
            return; 
        }
 
        public override void OnEvent(TmRollbackEvent e)
        {
            ParticipantEnlistment participant = e.Participant;
 
            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Aborted(participant); 
 
            e.StateMachine.ChangeState(state.States.DurableAborted);
        } 

        public override void OnEvent(TmParticipantForgetEvent e)
        {
            ParticipantEnlistment participant = e.Participant; 

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.ForgetResponse(participant, Status.Success); 

            e.StateMachine.ChangeState(state.States.DurableInDoubt); 
        }
    }

    //============================================================================= 
    // DurableCommitted
    // 
    // We think we're done, and the transaction committed 
    //=============================================================================
    class DurableCommitted : TerminalState 
    {
        public DurableCommitted (ProtocolState state) : base (state) {}

        public override void Enter (StateMachine stateMachine) 
        {
            base.Enter (stateMachine); 
 
            if (ParticipantStateMachineFinishedRecord.ShouldTrace)
            { 
                ParticipantStateMachineFinishedRecord.Trace(
                    stateMachine.Enlistment.EnlistmentId,
                    stateMachine.Enlistment.Enlistment.RemoteTransactionId,
                    TransactionOutcome.Committed 
                    );
            } 
        } 

        // We already received a committed message 
        public override void OnEvent(MsgPreparedEvent e)
        {
            return;
        } 

        public override void OnEvent(MsgCommittedEvent e) 
        { 
            return;
        } 

        // We already received a committed message
        public override void OnEvent(MsgReplayEvent e)
        { 
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableCommitted), "OnEvent(replay)");
            return; 
        } 

        // This is a repost from the recovery queue 
        public override void OnEvent(TmCommitEvent e)
        {
            ParticipantEnlistment participant = e.Participant;
 
            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Committed (participant); 
        } 

        public override void OnEvent(TmParticipantForgetEvent e) 
        {
            ParticipantEnlistment participant = e.Participant;
            participant.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ForgetResponse(participant, Status.Success); 
        }
 
        public override void OnEvent(TimerParticipantEvent e) 
        {
            return; 
        }
    }

    //============================================================================= 
    // DurableAborted
    // 
    // We think we're done, and the transaction aborted 
    //==============================================================================
    class DurableAborted : TerminalState 
    {
        public DurableAborted(ProtocolState state) : base (state) {}

        public override void Enter (StateMachine stateMachine) 
        {
            base.Enter (stateMachine); 
 
            if (ParticipantStateMachineFinishedRecord.ShouldTrace)
            { 
                ParticipantStateMachineFinishedRecord.Trace(
                    stateMachine.Enlistment.EnlistmentId,
                    stateMachine.Enlistment.Enlistment.RemoteTransactionId,
                    TransactionOutcome.Aborted 
                    );
            } 
        } 

        public override void OnEvent(MsgReadOnlyEvent e) 
        {
            return;
        }
 
        public override void OnEvent(MsgPreparedEvent e)
        { 
            state.TwoPhaseCommitCoordinator.SendRollback(e.ReplyTo); 
        }
 
        public override void OnEvent(MsgAbortedEvent e)
        {
            return;
        } 

        public override void OnEvent(MsgReplayEvent e) 
        { 
            ProtocolVersionHelper.AssertProtocolVersion10(this.state.ProtocolVersion, typeof(DurableAborted), "OnEvent(replay)");
            state.TwoPhaseCommitCoordinator.SendRollback(e.ReplyTo); 
        }

        public override void OnEvent(TmPrepareEvent e)
        { 
            ParticipantEnlistment participant = e.Participant;
 
            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant);
        } 

        public override void OnEvent(TmRollbackEvent e)
        {
            ParticipantEnlistment participant = e.Participant; 

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant); 
        }
 
        public override void OnEvent(TmRollbackResponseEvent e)
        {
            if (e.Status != Status.Aborted)
            { 
                // The only valid status is Aborted. If this is not true, we
                // shouldn't be in this state method. 
                DiagnosticUtility.FailFast("Transaction manager should respond Aborted to Rollback"); 
            }
            return; 
        }

        public override void OnEvent(TmParticipantForgetEvent e)
        { 
            ParticipantEnlistment participant = e.Participant;
            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.ForgetResponse(participant, Status.Success); 
        }
 
        public override void OnEvent(TimerParticipantEvent e)
        {
            return;
        } 
    }
 
    //============================================================================= 
    // DurableInDoubt
    // 
    // We think we're done, and the transaction is indoubt
    //==============================================================================
    class DurableInDoubt : TerminalState
    { 
        public DurableInDoubt (ProtocolState state) : base (state) {}
 
        public override void Enter (StateMachine stateMachine) 
        {
            base.Enter (stateMachine); 

            if (ParticipantStateMachineFinishedRecord.ShouldTrace)
            {
                ParticipantStateMachineFinishedRecord.Trace( 
                    stateMachine.Enlistment.EnlistmentId,
                    stateMachine.Enlistment.Enlistment.RemoteTransactionId, 
                    TransactionOutcome.InDoubt 
                    );
            } 
        }

        public override void OnEvent(MsgReadOnlyEvent e)
        { 
            return;
        } 
 
        public override void OnEvent(MsgAbortedEvent e)
        { 
            return;
        }

        public override void OnEvent(MsgCommittedEvent e) 
        {
            return; 
        } 

        public override void OnEvent(TmRollbackEvent e) 
        {
            ParticipantEnlistment participant = e.Participant;

            participant.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Aborted(participant);
        } 
 
        public override void OnEvent(TimerParticipantEvent e)
        { 
            return;
        }
    }
 
    //==============================================================================
    // DurableInitializationFailed 
    // 
    // We think we're done because we couldn't create a subordinate enlistment
    //============================================================================= 
    class DurableInitializationFailed : TerminalState
    {
        public DurableInitializationFailed(ProtocolState state) : base(state) { }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK