Coordinator.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 / Coordinator.cs / 1 / Coordinator.cs

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

// This file contains the the implementations of the various states used by 
// the coordinator state machine (both durable and volatile)
 
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
{
    //=============================================================================
    // CoordinatorInitializing 
    //
    // An EnlistTransaction message was received, and a new transaction 
    // object was created to process it. 
    //=============================================================================
    class CoordinatorInitializing : InactiveState 
    {
        public CoordinatorInitializing(ProtocolState state) : base(state) { }

        public override void OnEvent(MsgEnlistTransactionEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 
 
            // If InboundTransactions are disabled, we don't even try to create
            // a superior enlistment with the TM.  Instead, we simply forward 
            // the event to a subordinate enlistment.
            // If the transaction already exists, good.  Otherwise, fail.
            if (!state.TransactionManager.Settings.NetworkInboundAccess)
            { 
                ForwardEnlistmentEventToSubordinate(e);
                coordinator.StateMachine.ChangeState(state.States.CoordinatorInitializationFailed); 
            } 
            else
            { 
                CoordinationContext context = e.Body.CurrentContext;

                // Resolve the registration proxy
                RegistrationProxy proxy = state.TryCreateRegistrationProxy(context.RegistrationService); 
                if (proxy == null)
                { 
                    coordinator.ContextManager.Fault = this.state.Faults.RegistrationProxyFailed; 
                    coordinator.StateMachine.ChangeState(state.States.CoordinatorInitializationFailed);
                } 
                else
                {
                    try
                    { 
                        coordinator.SetRegistrationProxy(proxy);
 
                        EnlistmentOptions options = coordinator.CreateEnlistmentOptions(context.Expires, 
                                                                                        context.ExpiresPresent,
                                                                                        context.IsolationLevel, 
                                                                                        context.IsolationFlags,
                                                                                        context.Description);
                        // Ask the TM to create a superior enlistment for us
                        state.TransactionManagerSend.EnlistTransaction(coordinator, options, e); 
                        e.StateMachine.ChangeState(state.States.CoordinatorEnlisting);
                    } 
                    finally 
                    {
                        proxy.Release(); 
                    }
                }
            }
        } 
    }
 
    //============================================================================== 
    // CoordinatorEnlisting
    // 
    // The TM has been asked to create a new superior enlistment
    //=============================================================================
    class CoordinatorEnlisting : InactiveState
    { 
        public CoordinatorEnlisting (ProtocolState state) : base (state) {}
 
        public override void OnEvent(TmEnlistTransactionResponseEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 
            MsgEnlistTransactionEvent source = e.SourceEvent;

            switch (e.Status)
            { 
                case Status.Success:
 
                    if (EnlistTransactionRecord.ShouldTrace) 
                    {
                        EnlistTransactionRecord.Trace(coordinator.EnlistmentId, source.Body.CurrentContext); 
                    }

                    coordinator.OnCoordinatorEnlisted();
                    coordinator.StateMachine.ChangeState(state.States.CoordinatorEnlisted); 
                    break;
 
                case Status.DuplicateTransaction: 

                    ForwardEnlistmentEventToSubordinate(source); 
                    coordinator.StateMachine.ChangeState(state.States.CoordinatorInitializationFailed);
                    break;

                default: 

                    if (EnlistTransactionFailureRecord.ShouldTrace) 
                    { 
                        EnlistTransactionFailureRecord.Trace(
                            coordinator.EnlistmentId, 
                            source.Body.CurrentContext,
                            SR.GetString (SR.PplCreateSuperiorEnlistmentFailed, e.Status.ToString())
                            );
                    } 

                    coordinator.ContextManager.Fault = this.state.Faults.TMEnlistFailed(e.Status); 
                    coordinator.StateMachine.ChangeState(state.States.CoordinatorInitializationFailed); 
                    break;
            } 
        }
    }

    //============================================================================== 
    // CoordinatorEnlisted
    // 
    // The TM has created a new superior enlistment 
    //
    // This is a bootstrap state that is only visited once 
    //==============================================================================
    class CoordinatorEnlisted : ActiveState
    {
        public CoordinatorEnlisted (ProtocolState state) : base (state) {} 

        public override void Enter (StateMachine stateMachine) 
        { 
            base.Enter (stateMachine);
 
            // We have to register for durable 2PC before responding to Enlist messages.
            // This is because we don't want to split the transaction tree. If we have
            // only a volatile 2PC pipe between us and our coordinator, we might not
            // receive a reliable outcome message.  Furthermore, while the TM will send 
            // us EnlistPrePrepare notifications, it will not send us an "EnlistPrepare".
            // So we need to fault in the durable pipe every time we're superior to the TM 
            // and subordinate to another WS-AT node. 
            //
            // We cannot return a coordination context to a subordinate until our superior 
            // sends us a register response for durable 2PC.  The reason is that someone could
            // cross-marshal that context to some other protocol, like OleTx, and register
            // for 2PC.  The TM won't tell us about this event, so there will be someone out there
            // who thinks that the transaction is real when it really isn't, because we 
            // don't have a pipe to our superior yet, and we can't provide any guarantees.
            // 
            // Bottom line: we state axiomatically that a protocol provider must always establish 
            // a durable pipe to its superior before responding to Enlist messages
 
            // Ask our superior for a durable pipe
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment;
            state.RegistrationParticipant.SendDurableRegister(coordinator);
        } 

        public override void OnEvent(MsgRegisterDurableResponseEvent e) 
        { 
            SetDurableCoordinatorActive (e);
            e.Coordinator.StateMachine.ChangeState(state.States.CoordinatorActive); 
        }

        public override void OnEvent(TmEnlistPrePrepareEvent e)
        { 
            EnlistPrePrepare (e);
 
            // Now we're registering for both protocols 
            e.StateMachine.ChangeState(state.States.CoordinatorRegisteringBoth);
        } 

        public override void OnEvent(TmAsyncRollbackEvent e)
        {
            ProcessTmAsyncRollback(e); 
        }
    } 
 
    //=============================================================================
    // CoordinatorRegisteringBoth 
    //
    // The TM has created a new superior enlistment
    // We sent our superior a register request for durable
    // We received an EnlistPrePrepare from the TM 
    //
    // This is a bootstrap state that is only visited once 
    //============================================================================== 
    class CoordinatorRegisteringBoth : ActiveState
    { 
        public CoordinatorRegisteringBoth (ProtocolState state) : base (state) {}

        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine);
 
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment)stateMachine.Enlistment; 
            if (coordinator.RegisterVolatileCoordinator == null)
            { 
                // Assumption is that the RegisterVolatileCoordinator is set.
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorRegisteringBoth requires RegisterVolatileCoordinator"); 
            }
        } 
 
        public override void OnEvent(MsgRegisterDurableResponseEvent e)
        { 
            SetDurableCoordinatorActive (e);
            e.StateMachine.ChangeState(state.States.CoordinatorRegisteringVolatile);
        }
 
        public override void OnEvent(MsgRegisterVolatileResponseEvent e)
        { 
            // We can't set our volatile coordinator to be active, because we don't have 
            // a durable pipe yet.  If we responded to the EnlistPrePrepare now, we would
            // begin sending responses to CCC w/context with volatile registers, which 
            // could then be used to cross-marshal to other protocols, which would then
            // assume a durable pipe.
            //
            // So we just save the EPR and keep waiting for the durable register response 

            e.VolatileCoordinator.SetCoordinatorProxy(e.Proxy); 
            e.StateMachine.ChangeState(state.States.CoordinatorRegisteringDurable); 
        }
 
        public override void OnEvent(TmAsyncRollbackEvent e)
        {
            ProcessTmAsyncRollback(e);
        } 
    }
 
    //============================================================================= 
    // CoordinatorRegisteringDurable
    // 
    // The TM has created a new superior enlistment
    // We sent our superior a register request for durable
    // We already received a register response for volatile
    // 
    // This is a bootstrap state that is only visited once
    //============================================================================= 
    class CoordinatorRegisteringDurable : ActiveState 
    {
        public CoordinatorRegisteringDurable (ProtocolState state) : base (state) {} 

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

            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment; 
 
            if (coordinator.RegisterVolatileCoordinator == null)
            { 
                // Assumption is that the RegisterVolatileCoordinator is set.
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorRegisteringDurable requires RegisterVolatileCoordinator"); 
            }
        } 
 
        public override void OnEvent(MsgRegisterDurableResponseEvent e)
        { 
            SetDurableCoordinatorActive(e);
            e.StateMachine.ChangeState(state.States.CoordinatorVolatileActive);
        }
 
        public override void OnEvent(MsgVolatileRollbackEvent e)
        { 
            state.TransactionManagerSend.Rollback(e.VolatileCoordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorAborted);
        } 

        public override void OnEvent(TmAsyncRollbackEvent e)
        {
            ProcessTmAsyncRollback(e); 
        }
    } 
 
    //=============================================================================
    // CoordinatorRegisteringVolatile 
    //
    // The TM has created a new superior enlistment
    // We registered for durable
    // We sent our superior a register request for volatile 
    //
    // We will return to this state for each phase zero wave 
    //============================================================================== 
    class CoordinatorRegisteringVolatile : ActiveState
    { 
        public CoordinatorRegisteringVolatile (ProtocolState state) : base (state) {}

        public override void Enter(StateMachine stateMachine)
        { 
            base.Enter(stateMachine);
 
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment; 
            if (coordinator.RegisterVolatileCoordinator == null)
            { 
                // Assumption is that the RegisterVolatileCoordinator is set.
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorRegisteringVolatile requires RegisterVolatileCoordinator"); 
            }
        } 
 
        public override void OnEvent(MsgRegisterVolatileResponseEvent e)
        { 
            e.VolatileCoordinator.SetCoordinatorProxy (e.Proxy);
            e.StateMachine.ChangeState(state.States.CoordinatorVolatileActive);
        }
 
        public override void OnEvent(MsgVolatilePrepareEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator; 
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;
 
            if (ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator))
            {
                // A duplicate message for the last completed volatile coordinator - resend ReadOnly
                state.TwoPhaseCommitParticipant.SendVolatileReadOnly(volatileCoordinator); 
            }
            else 
            { 
                // Ignore duplicate message from older volatile coordinator
                return; 
            }
        }

        public override void OnEvent(MsgVolatileRollbackEvent e) 
        {
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator; 
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator; 

            if (ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator)) 
            {
                state.TwoPhaseCommitParticipant.SendVolatileAborted(volatileCoordinator);
                state.TransactionManagerSend.Rollback(volatileCoordinator);
                e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
            }
            else 
            { 
                base.OnEvent(e);
            } 
        }

        public override void OnEvent(MsgDurableRollbackEvent e)
        { 
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        } 

        public override void OnEvent(TmAsyncRollbackEvent e) 
        {
            ProcessTmAsyncRollback(e);
        }
    } 

    //============================================================================= 
    // CoordinatorVolatileActive 
    //
    // The TM has created a new superior enlistment 
    // We have created a durable registration
    // We have an outstanding volatile registration
    //
    // We await a volatile Prepare from our superior 
    //==============================================================================
    class CoordinatorVolatileActive : ActiveState 
    { 
        public CoordinatorVolatileActive (ProtocolState state) : base (state) {}
 
        public override void Enter (StateMachine stateMachine)
        {
            base.Enter (stateMachine);
 
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment;
            if (coordinator.RegisterVolatileCoordinator == null) 
            { 
                // Assumption is that the RegisterVolatileCoordinator is set.
                // If the assumption is incorrect, then the rest 
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorVolatileActive requires RegisterVolatileCoordinator");
            }
 
            if (RegisterCoordinatorRecord.ShouldTrace)
            { 
                RegisterCoordinatorRecord.Trace( 
                    coordinator.EnlistmentId,
                    coordinator.SuperiorContext, 
                    ControlProtocol.Volatile2PC,
                    coordinator.RegisterVolatileCoordinator.CoordinatorProxy.To,
                    this.state.ProtocolVersion
                    ); 
            }
 
            // Release the pending EnlistPrePrepare 
            TmEnlistPrePrepareEvent e = coordinator.EnlistPrePrepareEvent;
            coordinator.EnlistPrePrepareEvent = null; 

            coordinator.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.EnlistPrePrepareResponse (coordinator, Status.Success);
        } 

        public override void OnEvent(MsgVolatilePrepareEvent e) 
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator;
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator; 

            if (ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator))
            {
                // A duplicate message for the previous volatile coordinator - resend ReadOnly 
                state.TwoPhaseCommitParticipant.SendVolatileReadOnly(volatileCoordinator);
            } 
            else if (ReferenceEquals(volatileCoordinator, coordinator.RegisterVolatileCoordinator)) 
            {
                // Rotate the pointers 
                coordinator.PreparingVolatileCoordinator = volatileCoordinator;
                coordinator.RegisterVolatileCoordinator = null;

                state.TransactionManagerSend.PrePrepare(volatileCoordinator); 
                e.StateMachine.ChangeState(state.States.CoordinatorVolatilePreparing);
            } 
            else 
            {
                // Ignore - we've already completed this enlistment 
                return;
            }
        }
 
        public override void OnEvent(MsgVolatileRollbackEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator; 
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;
 
            if (ReferenceEquals(volatileCoordinator, coordinator.RegisterVolatileCoordinator) ||
                ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator))
            {
                state.TransactionManagerSend.Rollback(volatileCoordinator); 
                e.StateMachine.ChangeState(state.States.CoordinatorAborted);
            } 
            else 
            {
                base.OnEvent(e); 
            }
        }

        public override void OnEvent(MsgDurableRollbackEvent e) 
        {
            state.TransactionManagerSend.Rollback(e.Coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        }
 
        public override void OnEvent(TmAsyncRollbackEvent e)
        {
            ProcessTmAsyncRollback(e);
        } 
    }
 
    //============================================================================== 
    // CoordinatorVolatilePreparing
    // 
    // We told the TM to PrePrepare the current Phase Zero wave
    //=============================================================================
    class CoordinatorVolatilePreparing : ActiveState
    { 
        public CoordinatorVolatilePreparing (ProtocolState state) : base (state) {}
 
        public override void Enter (StateMachine stateMachine) 
        {
            base.Enter (stateMachine); 

            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment;

            if (coordinator.RegisterVolatileCoordinator != null) 
            {
                // Assumption is that the RegisterVolatileCoordinator is not set yet. 
                // If the assumption is incorrect, then the rest 
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparing requires null RegisterVolatileCoordinator"); 
            }
            if (coordinator.PreparingVolatileCoordinator == null)
            {
                // Assumption is that the PreparingVolatileCoordinator is set. 
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug. 
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparing requires PreparingVolatileCoordinator"); 
            }
        } 

        // Tolerate duplicate messages
        public override void OnEvent(MsgVolatilePrepareEvent e)
        { 
            return;
        } 
 
        public override void OnEvent(MsgVolatileRollbackEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator;
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;

            if (ReferenceEquals(volatileCoordinator, coordinator.PreparingVolatileCoordinator)) 
            {
                state.TransactionManagerSend.Rollback(volatileCoordinator); 
                e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
            }
            else 
            {
                base.OnEvent(e);
            }
        } 

        public override void OnEvent(MsgDurableRollbackEvent e) 
        { 
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        }

        public override void OnEvent(TmPrePrepareResponseEvent e)
        { 
            switch (e.Status)
            { 
                case Status.PrePrepared: 

                    // We're always registered for durable 2PC, so we can lose the volatile pipe 
                    // Therefore, we respond readonly and save messages
                    state.TwoPhaseCommitParticipant.SendVolatileReadOnly (e.VolatileCoordinator);

                    // Rotate the volatile coordinator pointers 
                    CoordinatorEnlistment coordinator = e.VolatileCoordinator.Coordinator;
                    coordinator.LastCompletedVolatileCoordinator = coordinator.PreparingVolatileCoordinator; 
                    coordinator.PreparingVolatileCoordinator = null; 

                    e.StateMachine.ChangeState(state.States.CoordinatorActive); 
                    break;

                case Status.Aborted:
                    // The Aborted response is sent on state enter 
                    e.StateMachine.ChangeState(state.States.CoordinatorAborted);
                    break; 
 
                default:
                    // An invalid Enum value on this internal code path indicates 
                    // a product bug and violates assumptions about
                    // valid values in MSDTC.
                    DiagnosticUtility.FailFast("Invalid status code");
                    break;  // Keep the compiler happy 
            }
        } 
 
        // The next Phase Zero wave has begun, so we need to open a new pipe
        public override void OnEvent(TmEnlistPrePrepareEvent e) 
        {
            EnlistPrePrepare(e);

            // Now we're registering for both protocols 
            e.StateMachine.ChangeState(state.States.CoordinatorVolatilePreparingRegistering);
        } 
 
        public override void OnEvent(TmAsyncRollbackEvent e)
        { 
            ProcessTmAsyncRollback(e);
        }
    }
 
    //==============================================================================
    // CoordinatorVolatilePreparingRegistering 
    // 
    // We told the TM to PrePrepare the current wave
    // The TM asked us for another volatile enlistment 
    // We sent a register to our superior
    //=============================================================================
    class CoordinatorVolatilePreparingRegistering : ActiveState
    { 
        public CoordinatorVolatilePreparingRegistering (ProtocolState state) : base (state) {}
 
        public override void Enter (StateMachine stateMachine) 
        {
            base.Enter(stateMachine); 

            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment;

            if (coordinator.PreparingVolatileCoordinator == null) 
            {
                // Assumption is that the PreparingVolatileCoordinator is set. 
                // If the assumption is incorrect, then the rest 
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparingRegistering requires PreparingVolatileCoordinator"); 
            }
            if (coordinator.RegisterVolatileCoordinator == null)
            {
                // Assumption is that the RegisterVolatileCoordinator is set. 
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug. 
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparingRegistering requires RegisterVolatileCoordinator"); 
            }
        } 

        public override void OnEvent(MsgRegisterVolatileResponseEvent e)
        {
            e.VolatileCoordinator.SetCoordinatorProxy(e.Proxy); 
            e.StateMachine.ChangeState(state.States.CoordinatorVolatilePreparingRegistered);
        } 
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgVolatilePrepareEvent e) 
        {
            // We can't see a Prepare for the next volatile participant in this state,
            // because we haven't received RegisterResponse, so the dispatcher
            // won't be able to authorize the incoming message 
            return;
        } 
 
        public override void OnEvent(MsgVolatileRollbackEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator;
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;

            if (ReferenceEquals(volatileCoordinator, coordinator.PreparingVolatileCoordinator)) 
            {
                state.TransactionManagerSend.Rollback(volatileCoordinator); 
                e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
            }
            else 
            {
                base.OnEvent(e);
            }
        } 

        public override void OnEvent(MsgDurableRollbackEvent e) 
        { 
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        }

        public override void OnEvent(TmPrePrepareResponseEvent e)
        { 
            switch (e.Status)
            { 
                case Status.PrePrepared: 

                    // We're always registered for durable 2PC, so we can lose the volatile pipe 
                    // Therefore, we respond readonly and save messages
                    state.TwoPhaseCommitParticipant.SendVolatileReadOnly(e.VolatileCoordinator);

                    // Rotate the volatile coordinator pointers 
                    CoordinatorEnlistment coordinator = e.VolatileCoordinator.Coordinator;
                    coordinator.LastCompletedVolatileCoordinator = coordinator.PreparingVolatileCoordinator; 
                    coordinator.PreparingVolatileCoordinator = null; 

                    e.StateMachine.ChangeState(state.States.CoordinatorRegisteringVolatile); 
                    break;

                case Status.Aborted:
                    // The Aborted response is sent on state enter 
                    e.StateMachine.ChangeState(state.States.CoordinatorAborted);
                    break; 
 
                default:
                    // An invalid Enum value on this internal code path indicates 
                    // a product bug and violates assumptions about
                    // valid values in MSDTC.
                    DiagnosticUtility.FailFast("Invalid status code");
                    break;  // Keep the compiler happy 
            }
        } 
 
        public override void OnEvent(TmAsyncRollbackEvent e)
        { 
            ProcessTmAsyncRollback(e);
        }
    }
 
    //=============================================================================
    // CoordinatorVolatilePreparingRegistered 
    // 
    // We told the TM to PrePrepare the current wave
    // The TM asked us for another volatile enlistment 
    // We registered for the next wave with our superior
    // Our superior sent us a register response
    // We're still waiting for the TM to respond to our PrePrepare
    //============================================================================= 
    class CoordinatorVolatilePreparingRegistered : ActiveState
    { 
        public CoordinatorVolatilePreparingRegistered (ProtocolState state) : base (state) {} 

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

            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment; 

            if (coordinator.PreparingVolatileCoordinator == null) 
            { 
                // Assumption is that the PreparingVolatileCoordinator is set.
                // If the assumption is incorrect, then the rest 
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparingRegistered requires PreparingVolatileCoordinator");
            }
            if (coordinator.RegisterVolatileCoordinator == null) 
            {
                // Assumption is that the RegisterVolatileCoordinator is set. 
                // If the assumption is incorrect, then the rest 
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorVolatilePreparingRegistered requires RegisterVolatileCoordinator"); 
            }
        }

        public override void OnEvent(MsgVolatilePrepareEvent e) 
        {
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator; 
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator; 

            if (ReferenceEquals(volatileCoordinator, coordinator.RegisterVolatileCoordinator)) 
            {
                // The volatile coordinator sent Prepare before we responded to the previous wave
                base.OnEvent(e);
            } 
            else
            { 
                // Ignore duplicate messages 
                return;
            } 
        }

        public override void OnEvent(MsgVolatileRollbackEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator;
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator; 
 
            if (ReferenceEquals(volatileCoordinator, coordinator.RegisterVolatileCoordinator) ||
                ReferenceEquals(volatileCoordinator, coordinator.PreparingVolatileCoordinator)) 
            {
                state.TransactionManagerSend.Rollback(volatileCoordinator);
                e.StateMachine.ChangeState(state.States.CoordinatorAborted);
            } 
            else
            { 
                base.OnEvent(e); 
            }
        } 

        public override void OnEvent(MsgDurableRollbackEvent e)
        {
            state.TransactionManagerSend.Rollback(e.Coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorAborted);
        } 
 
        public override void OnEvent(TmPrePrepareResponseEvent e)
        { 
            switch (e.Status)
            {
                case Status.PrePrepared:
 
                    // We're always registered for durable 2PC, so we can lose the volatile pipe
                    // Therefore, we respond readonly and save messages 
                    state.TwoPhaseCommitParticipant.SendVolatileReadOnly(e.VolatileCoordinator); 

                    // Rotate the volatile coordinator pointers 
                    CoordinatorEnlistment coordinator = e.VolatileCoordinator.Coordinator;
                    coordinator.LastCompletedVolatileCoordinator = coordinator.PreparingVolatileCoordinator;
                    coordinator.PreparingVolatileCoordinator = null;
 
                    e.StateMachine.ChangeState(state.States.CoordinatorVolatileActive);
                    break; 
 
                case Status.Aborted:
                    // The Aborted response is sent on state enter 
                    e.StateMachine.ChangeState(state.States.CoordinatorAborted);
                    break;

                default: 
                    // An invalid Enum value on this internal code path indicates
                    // a product bug and violates assumptions about 
                    // valid values in MSDTC. 
                    DiagnosticUtility.FailFast("Invalid status code");
                    break;  // Keep the compiler happy 
            }
        }

        public override void OnEvent(TmAsyncRollbackEvent e) 
        {
            ProcessTmAsyncRollback(e); 
        } 
    }
 
    //==============================================================================
    // CoordinatorActive
    //
    // The TM has created a new superior enlistment 
    // We established a durable registration
    // We have gone through any number of Phase Zero waves 
    //============================================================================= 
    class CoordinatorActive : ActiveState
    { 
        public CoordinatorActive (ProtocolState state) : base (state) {}

        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter(stateMachine);
 
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment)stateMachine.Enlistment; 
            if (coordinator.RegisterVolatileCoordinator != null)
            { 
                // Assumption is that the RegisterVolatileCoordinator is not set.
                // If the assumption is incorrect, then the rest
                // of the assumptions in the code are incorrect and this is a product bug.
                DiagnosticUtility.FailFast("CoordinatorActive requires null RegisterVolatileCoordinator"); 
            }
        } 
 
        // Sigh...  Start another Phase Zero wave
        public override void OnEvent(TmEnlistPrePrepareEvent e) 
        {
            EnlistPrePrepare(e);

            // Now we're registering for both protocols 
            e.StateMachine.ChangeState(state.States.CoordinatorRegisteringVolatile);
        } 
 
        public override void OnEvent(MsgVolatilePrepareEvent e)
        { 
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator;
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;

            if (ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator)) 
            {
                state.TwoPhaseCommitParticipant.SendVolatileReadOnly(volatileCoordinator); 
            } 
            else
            { 
                // Ignore
                return;
            }
        } 

        public override void OnEvent(MsgDurablePrepareEvent e) 
        { 
            CoordinatorEnlistment coordinator = e.Coordinator;
 
            Exception failed = null;
            try
            {
                byte[] recovery = state.LogEntrySerialization.Serialize(coordinator); 
                coordinator.Enlistment.SetRecoveryData(recovery);
 
                state.TransactionManagerSend.Prepare(coordinator); 
                e.StateMachine.ChangeState(state.States.CoordinatorPreparing);
            } 
            catch (SerializationException exception)
            {
                DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Error);
                failed = exception; 
            }
 
            if (failed != null) 
            {
                if (DebugTrace.Error) 
                    DebugTrace.Trace(TraceLevel.Error,
                                     "Failed to serialize log entry for coordinator: {0}",
                                     failed);
 
                CoordinatorRecoveryLogEntryCreationFailureRecord.TraceAndLog(
                    coordinator.EnlistmentId, 
                    coordinator.Enlistment.RemoteTransactionId, 
                    failed.Message,
                    failed 
                    );

                // We react to serialization failures by aborting the transaction
                state.TwoPhaseCommitParticipant.SendDurableAborted(coordinator); 

                state.TransactionManagerSend.Rollback(coordinator); 
                e.StateMachine.ChangeState(state.States.DurableAborted); 
            }
        } 

        public override void OnEvent(MsgVolatileRollbackEvent e)
        {
            VolatileCoordinatorEnlistment volatileCoordinator = e.VolatileCoordinator; 
            CoordinatorEnlistment coordinator = volatileCoordinator.Coordinator;
 
            if (ReferenceEquals(volatileCoordinator, coordinator.LastCompletedVolatileCoordinator)) 
            {
                state.TwoPhaseCommitParticipant.SendVolatileAborted(volatileCoordinator); 
                state.TransactionManagerSend.Rollback(volatileCoordinator);
                e.StateMachine.ChangeState(state.States.CoordinatorAborted);
            }
            else 
            {
                base.OnEvent(e); 
            } 
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        {
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        }
 
        public override void OnEvent(TmAsyncRollbackEvent e) 
        {
            ProcessTmAsyncRollback(e); 
        }
    }

    //============================================================================== 
    // CoordinatorPreparing
    // 
    // The coordinator sent Prepare and we forwarded it to the TM 
    //==============================================================================
    class CoordinatorPreparing : ActiveState 
    {
        public CoordinatorPreparing (ProtocolState state) : base (state) {}

        // Tolerate duplicate messages 
        public override void OnEvent(MsgVolatilePrepareEvent e)
        { 
            return; 
        }
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgDurablePrepareEvent e)
        {
            return; 
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e) 
        {
            state.TransactionManagerSend.Rollback(e.Coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorAborted);
        }

        public override void OnEvent(TmPrepareResponseEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 
 
            State newState;
            switch (e.Status) 
            {
                case Status.Prepared:
                    state.TwoPhaseCommitParticipant.SendPrepared (coordinator);
                    newState = state.States.CoordinatorPrepared; 
                    break;
 
                case Status.Readonly: 
                    state.TwoPhaseCommitParticipant.SendDurableReadOnly (coordinator);
                    newState = state.States.CoordinatorReadOnlyInDoubt; 
                    break;

                case Status.Aborted:
                    // The Aborted response is sent on state enter 
                    newState = state.States.CoordinatorAborted;
                    break; 
 
                default:
                    // An invalid Enum value on this internal code path indicates 
                    // a product bug and violates assumptions about
                    // valid values in MSDTC.
                    DiagnosticUtility.FailFast("Invalid status code");
                    newState = null;    // Keep the compiler happy 
                    break;
            } 
 
            e.StateMachine.ChangeState(newState);
        } 

        public override void OnEvent(TmAsyncRollbackEvent e)
        {
            ProcessTmAsyncRollback(e); 
        }
    } 
 
    //=============================================================================
    // CoordinatorPrepared 
    //
    // The TM said Prepared
    //==============================================================================
    class CoordinatorPrepared : DecidedState 
    {
        public CoordinatorPrepared (ProtocolState state) : base (state) {} 
 
        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine);

            // Create a prepared timer
            stateMachine.StartTimer (TimerProfile.Prepared); 
        }
 
        public override void Leave (StateMachine stateMachine) 
        {
            base.Leave (stateMachine); 

            // Cancel the prepared timer
            stateMachine.CancelTimer();
        } 

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

        // Respond to the duplicate message
        public override void OnEvent(MsgDurablePrepareEvent e) 
        {
            state.TwoPhaseCommitParticipant.SendPrepared (e.Coordinator); 
        } 

        public override void OnEvent(MsgDurableCommitEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator;

            state.TransactionManagerSend.Commit (coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorCommitting);
        } 
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        { 
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted);
        }
 
        public override void OnEvent(TmCoordinatorForgetEvent e)
        { 
            CoordinatorEnlistment coordinator = e.Coordinator; 

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

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

        // Just keep sending Prepared messages until we receive a response 
        public override void OnEvent(TimerCoordinatorEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 

            if (PreparedMessageRetryRecord.ShouldTrace)
            {
                coordinator.Retries ++; 

                PreparedMessageRetryRecord.Trace( 
                    coordinator.EnlistmentId, 
                    coordinator.Enlistment.RemoteTransactionId,
                    coordinator.Retries 
                    );
            }

            state.Perf.PreparedRetryCountPerInterval.Increment(); 

            state.TwoPhaseCommitParticipant.SendPrepared (coordinator); 
        } 
    }
 
    //=============================================================================
    // CoordinatorCommitting
    //
    // Our coordinator told us to commit the transaction. We told the TM the same 
    //=============================================================================
    class CoordinatorCommitting : DecidedState 
    { 
        public CoordinatorCommitting (ProtocolState state) : base (state) {}
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgVolatilePrepareEvent e)
        {
            return; 
        }
 
        // Tolerate duplicate messages 
        public override void OnEvent(MsgDurablePrepareEvent e)
        { 
            return;
        }

        // Tolerate duplicate messages 
        public override void OnEvent(MsgDurableCommitEvent e)
        { 
            return; 
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        {
            // We implement this event because the spec's state tables dictate a non-standard response:
            // we fault with InconsistentInternalState instead of InvalidState 
            TraceInvalidEvent (e, false);
            state.TwoPhaseCommitParticipant.SendFault(e.FaultTo, e.MessageId, this.state.Faults.InconsistentInternalState); 
        } 

        public override void OnEvent(TmCommitResponseEvent e) 
        {
            if (e.Status != Status.Committed)
            {
                // The only valid status is Committed. If this is not true, we 
                // shouldn't be in this state method.
                DiagnosticUtility.FailFast("Transaction manager should respond Committed to Commit"); 
            } 

            state.TwoPhaseCommitParticipant.SendCommitted (e.Coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorCommitted);
        }

        public override void OnEvent(TmCoordinatorForgetEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 
 
            coordinator.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ForgetResponse(coordinator, Status.Success); 

            e.StateMachine.ChangeState(state.States.CoordinatorForgotten);
        }
 
        // This is a repost from the recovery queue. Ignore it
        public override void OnEvent(TmReplayEvent e) 
        { 
            return;
        } 

        // Tolerate timer notifications left over from the Prepared or Replaying states
        public override void OnEvent(TimerCoordinatorEvent e)
        { 
            return;
        } 
    } 

    //============================================================================= 
    // CoordinatorRecovering
    //
    // The TM asked us for replay. A new coordinator enlistment was created to process it
    //============================================================================== 
    class CoordinatorRecovering : DecidedState
    { 
        public CoordinatorRecovering (ProtocolState state) : base (state) {} 

        public override void OnEvent(TmReplayEvent 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("Replay events should only be delivered during recovery"); 
            }
 
            CoordinatorEnlistment coordinator = e.Coordinator;

            // We're still recovering, so queue up a replay for later
            state.EnqueueRecoveryReplay(e); 

            coordinator.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.Replayed(coordinator); 

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

    //============================================================================= 
    // CoordinatorAwaitingEndOfRecovery
    // 
    // Waiting for recovery to finish so we can send our coordinator a replay message 
    //==============================================================================
    class CoordinatorAwaitingEndOfRecovery : DecidedState 
    {
        public CoordinatorAwaitingEndOfRecovery (ProtocolState state) : base (state) {}

        // Tolerate duplicate messages 
        public override void OnEvent(MsgDurablePrepareEvent e)
        { 
            return; 
        }
 
        public override void OnEvent(MsgDurableCommitEvent e)
        {
            state.TransactionManagerSend.Commit (e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorCommitting); 
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e) 
        {
            state.TransactionManagerSend.Rollback(e.Coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorAborted);
        }

        // This is a repost sent after the end of recovery, after our listeners were opened 
        public override void OnEvent(TmReplayEvent 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("Replay events should only be re-delivered after recovery");
            } 

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

        public override void OnEvent(TmCoordinatorForgetEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator;

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

    //==============================================================================
    // CoordinatorFailedRecovery
    // 
    // 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 CoordinatorFailedRecovery : DecidedState
    { 
        public CoordinatorFailedRecovery (ProtocolState state) : base (state) {}

        public override void OnEvent(TmReplayEvent e)
        { 
            // Ack the coordinator
            CoordinatorEnlistment coordinator = e.Coordinator; 
 
            coordinator.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.Replayed(coordinator); 
        }

        public override void OnEvent(TmCoordinatorForgetEvent e)
        { 
            CoordinatorEnlistment coordinator = e.Coordinator;
 
            coordinator.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.ForgetResponse(coordinator, Status.Success);
 
            e.StateMachine.ChangeState(state.States.CoordinatorForgotten);
        }
    }
 
    //==============================================================================
    // CoordinatorRecovered 
    // 
    // We are ready to send Replay to our coordinator
    //============================================================================= 
    class CoordinatorRecovered : DecidedState
    {
        public CoordinatorRecovered (ProtocolState state) : base (state) {}
 
        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine); 

            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) stateMachine.Enlistment; 

            // Ensure our proxy to our coordinator has a 'from'
            coordinator.CreateParticipantService();
 
            // Send our coordinator a replay
            state.TwoPhaseCommitParticipant.SendRecoverMessage(coordinator); 
 
            // Start a replay timer
            stateMachine.StartTimer (TimerProfile.Replaying); 
        }

        public override void Leave (StateMachine stateMachine)
        { 
            base.Leave (stateMachine);
 
            // Cancel the replay timer 
            stateMachine.CancelTimer();
        } 

        public override void OnEvent(MsgDurableCommitEvent e)
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 

            state.TransactionManagerSend.Commit (coordinator); 
            e.StateMachine.ChangeState(state.States.CoordinatorCommitting); 
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        {
            state.TransactionManagerSend.Rollback(e.Coordinator);
            e.StateMachine.ChangeState(state.States.CoordinatorAborted); 
        }
 
        public override void OnEvent(TmCoordinatorForgetEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator; 

            coordinator.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.ForgetResponse(coordinator, Status.Success);
 
            e.StateMachine.ChangeState(state.States.CoordinatorForgotten);
        } 
 
        // We just keep sending replay messages until we receive a response
        public override void OnEvent(TimerCoordinatorEvent e) 
        {
            CoordinatorEnlistment coordinator = e.Coordinator;

            if (ReplayMessageRetryRecord.ShouldTrace) 
            {
                coordinator.Retries ++; 
 
                ReplayMessageRetryRecord.Trace(
                    coordinator.EnlistmentId, 
                    coordinator.Enlistment.RemoteTransactionId,
                    coordinator.Retries
                    );
            } 

            state.Perf.ReplayRetryCountPerInterval.Increment(); 
 
            state.TwoPhaseCommitParticipant.SendRecoverMessage (e.Coordinator);
        } 
    }

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

        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine);
 
            if (CoordinatorStateMachineFinishedRecord.ShouldTrace) 
            {
                CoordinatorStateMachineFinishedRecord.Trace( 
                    stateMachine.Enlistment.EnlistmentId,
                    stateMachine.Enlistment.Enlistment.RemoteTransactionId,
                    TransactionOutcome.Committed
                    ); 
            }
        } 
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgVolatilePrepareEvent e) 
        {
            return;
        }
 
        // Tolerate duplicate messages
        public override void OnEvent(MsgDurablePrepareEvent e) 
        { 
            return;
        } 

        public override void OnEvent(MsgDurableRollbackEvent e)
        {
            // We implement this event because the spec's state tables dictate a non-standard response: 
            // we fault with InconsistentInternalState instead of InvalidState
            TraceInvalidEvent (e, false); 
            state.TwoPhaseCommitParticipant.SendFault(e.ReplyTo, e.MessageId, this.state.Faults.InconsistentInternalState); 
        }
 
        public override void OnEvent(MsgDurableCommitEvent e)
        {
            state.TwoPhaseCommitParticipant.SendCommitted(e.ReplyTo);
        } 

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

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

        public override void Enter (StateMachine stateMachine)
        { 
            if (CoordinatorStateMachineFinishedRecord.ShouldTrace)
            { 
                CoordinatorStateMachineFinishedRecord.Trace ( 
                    stateMachine.Enlistment.EnlistmentId,
                    stateMachine.Enlistment.Enlistment.RemoteTransactionId, 
                    TransactionOutcome.Aborted
                    );
            }
 
            // Send out some aborted notifications
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment)stateMachine.Enlistment; 
 
            TrySendAborted(coordinator);
            if (coordinator.RegisterVolatileCoordinator != null) 
                TrySendAborted(coordinator.RegisterVolatileCoordinator);
            if (coordinator.PreparingVolatileCoordinator != null)
                TrySendAborted(coordinator.PreparingVolatileCoordinator);
 
            // This may close proxies, so we do it last
            base.Enter(stateMachine); 
        } 

        public override void OnEvent(MsgRegisterDurableResponseEvent e) 
        {
            return;
        }
 
        public override void OnEvent(MsgRegisterVolatileResponseEvent e)
        { 
            return; 
        }
 
        public override void OnEvent(TmEnlistPrePrepareEvent e)
        {
            CoordinatorEnlistment coordinator = e.Coordinator;
 
            coordinator.SetCallback(e.Callback, e.CallbackState);
            state.TransactionManagerSend.EnlistPrePrepareResponse (coordinator, Status.Aborted); 
        } 

        public override void OnEvent(MsgVolatilePrepareEvent e) 
        {
            state.TwoPhaseCommitParticipant.SendAborted(e.ReplyTo);
        }
 
        public override void OnEvent(MsgDurablePrepareEvent e)
        { 
            state.TwoPhaseCommitParticipant.SendAborted(e.ReplyTo); 
        }
 
        public override void OnEvent(MsgDurableCommitEvent e)
        {
            // We implement this event because the spec's state tables dictate a non-standard response:
            // we fault with InconsistentInternalState instead of InvalidState 
            TraceInvalidEvent (e, false);
            state.TwoPhaseCommitParticipant.SendFault(e.FaultTo, e.MessageId, this.state.Faults.InconsistentInternalState); 
        } 

        public override void OnEvent(MsgVolatileRollbackEvent e) 
        {
            state.TwoPhaseCommitParticipant.SendAborted(e.ReplyTo);
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        { 
            state.TwoPhaseCommitParticipant.SendAborted(e.ReplyTo); 
        }
 
        public override void OnEvent(TmPrePrepareResponseEvent e)
        {
            return;
        } 

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

        public override void OnEvent(TmRollbackResponseEvent e)
        {
            return; 
        }
 
        public override void OnEvent(TmAsyncRollbackEvent e) 
        {
            CoordinatorEnlistment coordinator = (CoordinatorEnlistment) e.Enlistment; 

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

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

        public override void OnEvent(TmCoordinatorForgetEvent e)
        {
            // Just ack the TM 
            CoordinatorEnlistment coordinator = e.Coordinator;
            coordinator.SetCallback(e.Callback, e.CallbackState); 
            state.TransactionManagerSend.ForgetResponse(coordinator, Status.Success); 
        }
 
        public override void OnEvent(TimerCoordinatorEvent e)
        {
            return;
        } 
    }
 
    //============================================================================== 
    // CoordinatorForgotten
    // 
    // We were asked to forget the transaction
    // This happens as a result of an administrative action
    //==============================================================================
    class CoordinatorForgotten : TerminalState 
    {
        public CoordinatorForgotten(ProtocolState state) : base(state) { } 
 
        public override void Enter(StateMachine stateMachine)
        { 
            base.Enter (stateMachine);

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

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

        public override void OnEvent(MsgVolatileRollbackEvent e) 
        {
            return;
        }
 
        public override void OnEvent(MsgDurablePrepareEvent e)
        { 
            return; 
        }
 
        public override void OnEvent(MsgDurableCommitEvent e)
        {
            return;
        } 

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

        public override void OnEvent(TimerCoordinatorEvent e)
        {
            return; 
        }
    } 
 
    //=============================================================================
    // CoordinatorReadOnlyInDoubt 
    //
    // We think we're done because we sent a durable readonly
    //==============================================================================
    class CoordinatorReadOnlyInDoubt : TerminalState 
    {
        public CoordinatorReadOnlyInDoubt (ProtocolState state) : base (state) {} 
 
        public override void Enter (StateMachine stateMachine)
        { 
            base.Enter (stateMachine);

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

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

        public override void OnEvent(MsgDurablePrepareEvent e) 
        {
            state.TwoPhaseCommitParticipant.SendReadOnly(e.ReplyTo);
        }
 
        public override void OnEvent(MsgDurableRollbackEvent e)
        { 
            state.TwoPhaseCommitParticipant.SendAborted(e.ReplyTo); 
        }
    } 

    //=============================================================================
    // CoordinatorInitializationFailed
    // 
    // We think we're done because we couldn't create a superior enlistment
    //============================================================================= 
    class CoordinatorInitializationFailed : TerminalState 
    {
        public CoordinatorInitializationFailed(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