TransactionState.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / tx / System / Transactions / TransactionState.cs / 1305376 / TransactionState.cs

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

namespace System.Transactions 
{ 

    using System; 
    using System.Collections;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.Serialization; 
    using System.Threading;
    using System.Transactions.Diagnostics; 
 
    // The TransactionState object defines the basic set of operations that
    // are available for a transaction.  It is a base type and the base 
    // implementations all throw exceptions.  For a particular state a derived
    // implementation will inheret from this object and implement the appropriate
    // operations for that state.
    internal abstract class TransactionState 
    {
        // The state machines themselves are designed to be internally consistent.  So the only externally visable 
        // state transition is to active.  All other state transitions must happen within the state machines 
        // themselves.
        private static TransactionStateActive             _transactionStateActive; 
        private static TransactionStateSubordinateActive  _transactionStateSubordinateActive;
        private static TransactionStatePhase0             _transactionStatePhase0;
        private static TransactionStateVolatilePhase1     _transactionStateVolatilePhase1;
        private static TransactionStateVolatileSPC        _transactionStateVolatileSPC; 
        private static TransactionStateSPC                _transactionStateSPC;
        private static TransactionStateAborted            _transactionStateAborted; 
        private static TransactionStateCommitted          _transactionStateCommitted; 
        private static TransactionStateInDoubt            _transactionStateInDoubt;
 
        private static TransactionStatePromoted           _transactionStatePromoted;
        private static TransactionStateNonCommittablePromoted _transactionStateNonCommittablePromoted;
        private static TransactionStatePromotedP0Wave     _transactionStatePromotedP0Wave;
        private static TransactionStatePromotedCommitting _transactionStatePromotedCommitting; 
        private static TransactionStatePromotedPhase0     _transactionStatePromotedPhase0;
        private static TransactionStatePromotedPhase1     _transactionStatePromotedPhase1; 
        private static TransactionStatePromotedP0Aborting _transactionStatePromotedP0Aborting; 
        private static TransactionStatePromotedP1Aborting _transactionStatePromotedP1Aborting;
        private static TransactionStatePromotedAborted    _transactionStatePromotedAborted; 
        private static TransactionStatePromotedCommitted  _transactionStatePromotedCommitted;
        private static TransactionStatePromotedIndoubt    _transactionStatePromotedIndoubt;

        private static TransactionStateDelegated          _transactionStateDelegated; 
        private static TransactionStateDelegatedSubordinate _transactionStateDelegatedSubordinate;
        private static TransactionStateDelegatedP0Wave    _transactionStateDelegatedP0Wave; 
        private static TransactionStateDelegatedCommitting _transactionStateDelegatedCommitting; 
        private static TransactionStateDelegatedAborting  _transactionStateDelegatedAborting;
        private static TransactionStatePSPEOperation      _transactionStatePSPEOperation; 


        // Object for synchronizing access to the entire class( avoiding lock( typeof( ... )) )
        private static object classSyncObject; 

 
        internal static TransactionStateActive _TransactionStateActive 
        {
            get 
            {
                if (_transactionStateActive == null)
                {
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStateActive == null) 
                        { 
                            TransactionStateActive temp = new TransactionStateActive();
                            Thread.MemoryBarrier(); 
                            _transactionStateActive = temp;
                        }
                    }
                } 

                return _transactionStateActive; 
            } 
        }
 

        internal static TransactionStateSubordinateActive _TransactionStateSubordinateActive
        {
            get 
            {
                if (_transactionStateSubordinateActive == null) 
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStateSubordinateActive == null)
                        {
                            TransactionStateSubordinateActive temp = new TransactionStateSubordinateActive();
                            Thread.MemoryBarrier(); 
                            _transactionStateSubordinateActive = temp;
                        } 
                    } 
                }
 
                return _transactionStateSubordinateActive;
            }
        }
 

        internal static TransactionStatePSPEOperation _TransactionStatePSPEOperation 
        { 
            get
            { 
                if (_transactionStatePSPEOperation == null)
                {
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStatePSPEOperation == null)
                        { 
                            TransactionStatePSPEOperation temp = new TransactionStatePSPEOperation(); 
                            Thread.MemoryBarrier();
                            _transactionStatePSPEOperation = temp; 
                        }
                    }
                }
 
                return _transactionStatePSPEOperation;
            } 
        } 

 
        protected static TransactionStatePhase0 _TransactionStatePhase0
        {
            get
            { 
                if (_transactionStatePhase0 == null)
                { 
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStatePhase0 == null) 
                        {
                            TransactionStatePhase0 temp = new TransactionStatePhase0();
                            Thread.MemoryBarrier();
                            _transactionStatePhase0 = temp; 
                        }
                    } 
                } 

                return _transactionStatePhase0; 
            }
        }

 
        protected static TransactionStateVolatilePhase1 _TransactionStateVolatilePhase1
        { 
            get 
            {
                if (_transactionStateVolatilePhase1 == null) 
                {
                    lock (ClassSyncObject)
                    {
                        if (_transactionStateVolatilePhase1 == null) 
                        {
                            TransactionStateVolatilePhase1 temp = new TransactionStateVolatilePhase1(); 
                            Thread.MemoryBarrier(); 
                            _transactionStateVolatilePhase1 = temp;
                        } 
                    }
                }

                return _transactionStateVolatilePhase1; 
            }
        } 
 

        protected static TransactionStateVolatileSPC _TransactionStateVolatileSPC 
        {
            get
            {
                if (_transactionStateVolatileSPC == null) 
                {
                    lock (ClassSyncObject) 
                    { 
                        if (_transactionStateVolatileSPC == null)
                        { 
                            TransactionStateVolatileSPC temp = new TransactionStateVolatileSPC();
                            Thread.MemoryBarrier();
                            _transactionStateVolatileSPC = temp;
                        } 
                    }
                } 
 
                return _transactionStateVolatileSPC;
            } 
        }


        protected static TransactionStateSPC _TransactionStateSPC 
        {
            get 
            { 
                if (_transactionStateSPC == null)
                { 
                    lock (ClassSyncObject)
                    {
                        if (_transactionStateSPC == null)
                        { 
                            TransactionStateSPC temp = new TransactionStateSPC();
                            Thread.MemoryBarrier(); 
                            _transactionStateSPC = temp; 
                        }
                    } 
                }

                return _transactionStateSPC;
            } 
        }
 
 
        protected static TransactionStateAborted _TransactionStateAborted
        { 
            get
            {
                if (_transactionStateAborted == null)
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStateAborted == null) 
                        {
                            TransactionStateAborted temp = new TransactionStateAborted(); 
                            Thread.MemoryBarrier();
                            _transactionStateAborted = temp;
                        }
                    } 
                }
 
                return _transactionStateAborted; 
            }
        } 


        protected static TransactionStateCommitted _TransactionStateCommitted
        { 
            get
            { 
                if (_transactionStateCommitted == null) 
                {
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStateCommitted == null)
                        {
                            TransactionStateCommitted temp = new TransactionStateCommitted(); 
                            Thread.MemoryBarrier();
                            _transactionStateCommitted =  temp; 
                        } 
                    }
                } 

                return _transactionStateCommitted;
            }
        } 

 
        protected static TransactionStateInDoubt _TransactionStateInDoubt 
        {
            get 
            {
                if (_transactionStateInDoubt == null)
                {
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStateInDoubt == null) 
                        { 
                            TransactionStateInDoubt temp = new TransactionStateInDoubt();
                            Thread.MemoryBarrier(); 
                            _transactionStateInDoubt = temp;
                        }
                    }
                } 

                return _transactionStateInDoubt; 
            } 
        }
 

        internal  static TransactionStatePromoted _TransactionStatePromoted
        {
            get 
            {
                if (_transactionStatePromoted == null) 
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStatePromoted == null)
                        {
                            TransactionStatePromoted temp = new TransactionStatePromoted();
                            Thread.MemoryBarrier(); 
                            _transactionStatePromoted = temp;
                        } 
                    } 
                }
 
                return _transactionStatePromoted;
            }
        }
 

        internal static TransactionStateNonCommittablePromoted _TransactionStateNonCommittablePromoted 
        { 
            get
            { 
                if (_transactionStateNonCommittablePromoted == null)
                {
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStateNonCommittablePromoted == null)
                        { 
                            TransactionStateNonCommittablePromoted temp = new TransactionStateNonCommittablePromoted(); 
                            Thread.MemoryBarrier();
                            _transactionStateNonCommittablePromoted = temp; 
                        }
                    }
                }
 
                return _transactionStateNonCommittablePromoted;
            } 
        } 

 
        protected static TransactionStatePromotedP0Wave _TransactionStatePromotedP0Wave
        {
            get
            { 
                if (_transactionStatePromotedP0Wave == null)
                { 
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStatePromotedP0Wave == null) 
                        {
                            TransactionStatePromotedP0Wave temp = new TransactionStatePromotedP0Wave();
                            Thread.MemoryBarrier();
                            _transactionStatePromotedP0Wave = temp; 
                        }
                    } 
                } 

                return _transactionStatePromotedP0Wave; 
            }
        }

 
        protected static TransactionStatePromotedCommitting _TransactionStatePromotedCommitting
        { 
            get 
            {
                if (_transactionStatePromotedCommitting == null) 
                {
                    lock (ClassSyncObject)
                    {
                        if (_transactionStatePromotedCommitting == null) 
                        {
                            TransactionStatePromotedCommitting temp = new TransactionStatePromotedCommitting(); 
                            Thread.MemoryBarrier(); 
                            _transactionStatePromotedCommitting = temp;
                        } 
                    }
                }

                return _transactionStatePromotedCommitting; 
            }
        } 
 

        protected static TransactionStatePromotedPhase0 _TransactionStatePromotedPhase0 
        {
            get
            {
                if (_transactionStatePromotedPhase0 == null) 
                {
                    lock (ClassSyncObject) 
                    { 
                        if (_transactionStatePromotedPhase0 == null)
                        { 
                            TransactionStatePromotedPhase0 temp = new TransactionStatePromotedPhase0();
                            Thread.MemoryBarrier();
                            _transactionStatePromotedPhase0 = temp;
                        } 
                    }
                } 
 
                return _transactionStatePromotedPhase0;
            } 
        }


        protected static TransactionStatePromotedPhase1 _TransactionStatePromotedPhase1 
        {
            get 
            { 
                if (_transactionStatePromotedPhase1 == null)
                { 
                    lock (ClassSyncObject)
                    {
                        if (_transactionStatePromotedPhase1 == null)
                        { 
                            TransactionStatePromotedPhase1 temp = new TransactionStatePromotedPhase1();
                            Thread.MemoryBarrier(); 
                            _transactionStatePromotedPhase1 = temp; 
                        }
                    } 
                }

                return _transactionStatePromotedPhase1;
            } 
        }
 
 
        protected static TransactionStatePromotedP0Aborting _TransactionStatePromotedP0Aborting
        { 
            get
            {
                if (_transactionStatePromotedP0Aborting == null)
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStatePromotedP0Aborting == null) 
                        {
                            TransactionStatePromotedP0Aborting temp = new TransactionStatePromotedP0Aborting(); 
                            Thread.MemoryBarrier();
                            _transactionStatePromotedP0Aborting = temp;
                        }
                    } 
                }
 
                return _transactionStatePromotedP0Aborting; 
            }
        } 


        protected static TransactionStatePromotedP1Aborting _TransactionStatePromotedP1Aborting
        { 
            get
            { 
                if (_transactionStatePromotedP1Aborting == null) 
                {
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStatePromotedP1Aborting == null)
                        {
                            TransactionStatePromotedP1Aborting temp = new TransactionStatePromotedP1Aborting(); 
                            Thread.MemoryBarrier();
                            _transactionStatePromotedP1Aborting = temp; 
                        } 
                    }
                } 

                return _transactionStatePromotedP1Aborting;
            }
        } 

 
        protected static TransactionStatePromotedAborted _TransactionStatePromotedAborted 
        {
            get 
            {
                if (_transactionStatePromotedAborted == null)
                {
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStatePromotedAborted == null) 
                        { 
                            TransactionStatePromotedAborted temp = new TransactionStatePromotedAborted();
                            Thread.MemoryBarrier(); 
                            _transactionStatePromotedAborted = temp;
                        }
                    }
                } 

                return _transactionStatePromotedAborted; 
            } 
        }
 

        protected static TransactionStatePromotedCommitted _TransactionStatePromotedCommitted
        {
            get 
            {
                if (_transactionStatePromotedCommitted == null) 
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStatePromotedCommitted == null)
                        {
                            TransactionStatePromotedCommitted temp = new TransactionStatePromotedCommitted();
                            Thread.MemoryBarrier(); 
                            _transactionStatePromotedCommitted = temp;
                        } 
                    } 
                }
 
                return _transactionStatePromotedCommitted;
            }
        }
 

        protected static TransactionStatePromotedIndoubt _TransactionStatePromotedIndoubt 
        { 
            get
            { 
                if (_transactionStatePromotedIndoubt == null)
                {
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStatePromotedIndoubt == null)
                        { 
                            TransactionStatePromotedIndoubt temp = new TransactionStatePromotedIndoubt(); 
                            Thread.MemoryBarrier();
                            _transactionStatePromotedIndoubt = temp; 
                        }
                    }
                }
 
                return _transactionStatePromotedIndoubt;
            } 
        } 

 
        protected static TransactionStateDelegated _TransactionStateDelegated
        {
            get
            { 
                if (_transactionStateDelegated == null)
                { 
                    lock (ClassSyncObject) 
                    {
                        if (_transactionStateDelegated == null) 
                        {
                            TransactionStateDelegated temp = new TransactionStateDelegated();
                            Thread.MemoryBarrier();
                            _transactionStateDelegated = temp; 
                        }
                    } 
                } 

                return _transactionStateDelegated; 
            }
        }

 
        internal static TransactionStateDelegatedSubordinate _TransactionStateDelegatedSubordinate
        { 
            get 
            {
                if (_transactionStateDelegatedSubordinate == null) 
                {
                    lock (ClassSyncObject)
                    {
                        if (_transactionStateDelegatedSubordinate == null) 
                        {
                            TransactionStateDelegatedSubordinate temp = new TransactionStateDelegatedSubordinate(); 
                            Thread.MemoryBarrier(); 
                            _transactionStateDelegatedSubordinate = temp;
                        } 
                    }
                }

                return _transactionStateDelegatedSubordinate; 
            }
        } 
 

        protected static TransactionStateDelegatedP0Wave _TransactionStateDelegatedP0Wave 
        {
            get
            {
                if (_transactionStateDelegatedP0Wave == null) 
                {
                    lock (ClassSyncObject) 
                    { 
                        if (_transactionStateDelegatedP0Wave == null)
                        { 
                            TransactionStateDelegatedP0Wave temp = new TransactionStateDelegatedP0Wave();
                            Thread.MemoryBarrier();
                            _transactionStateDelegatedP0Wave = temp;
                        } 
                    }
                } 
 
                return _transactionStateDelegatedP0Wave;
            } 
        }


        protected static TransactionStateDelegatedCommitting _TransactionStateDelegatedCommitting 
        {
            get 
            { 
                if (_transactionStateDelegatedCommitting == null)
                { 
                    lock (ClassSyncObject)
                    {
                        if (_transactionStateDelegatedCommitting == null)
                        { 
                            TransactionStateDelegatedCommitting temp = new TransactionStateDelegatedCommitting();
                            Thread.MemoryBarrier(); 
                            _transactionStateDelegatedCommitting = temp; 
                        }
                    } 
                }

                return _transactionStateDelegatedCommitting;
            } 
        }
 
 
        protected static TransactionStateDelegatedAborting _TransactionStateDelegatedAborting
        { 
            get
            {
                if (_transactionStateDelegatedAborting == null)
                { 
                    lock (ClassSyncObject)
                    { 
                        if (_transactionStateDelegatedAborting == null) 
                        {
                            TransactionStateDelegatedAborting temp = new TransactionStateDelegatedAborting(); 
                            Thread.MemoryBarrier();
                            _transactionStateDelegatedAborting = temp;
                        }
                    } 
                }
 
                return _transactionStateDelegatedAborting; 
            }
        } 


        // Helper object for static synchronization
        internal static object ClassSyncObject 
        {
            get 
            { 
                if( classSyncObject == null )
                { 
                    object o = new object();
                    Interlocked.CompareExchange( ref classSyncObject, o, null );
                }
                return classSyncObject; 
            }
        } 
 

        internal void CommonEnterState( InternalTransaction tx ) 
        {
            Debug.Assert( tx.State != this, "Changing to the same state." );
            tx.State = this;
 
#if DEBUG
            tx.stateHistory [tx.currentStateHist] = this; 
            if( ++tx.currentStateHist > InternalTransaction.MaxStateHist ) 
            {
                tx.currentStateHist = 0; 
            }
#endif
        }
 

 
        // Every state must override EnterState 
        internal abstract void EnterState( InternalTransaction tx );
 

        internal virtual void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
 
        internal virtual void EndCommit( InternalTransaction tx )
        { 
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() ));

            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 

 
        internal virtual void Rollback( InternalTransaction tx, Exception e ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }


        internal virtual Enlistment EnlistDurable( 
            InternalTransaction tx,
            Guid resourceManagerIdentifier, 
            IEnlistmentNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 

 
        internal virtual Enlistment EnlistDurable( 
            InternalTransaction tx,
            Guid resourceManagerIdentifier, 
            ISinglePhaseNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction
            ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        } 

 
        internal virtual Enlistment EnlistVolatile(
            InternalTransaction tx,
            IEnlistmentNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 


        internal virtual Enlistment EnlistVolatile(
            InternalTransaction tx, 
            ISinglePhaseNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction 
            )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }

 
        internal virtual void CheckForFinishedTransaction( InternalTransaction tx )
        { 
            // Aborted & InDoubt states should throw exceptions. 
        }
 

        // If a specific state does not have a story for identifiers then
        // it simply gets a guid.  This would be to handle cases like aborted
        // and committed where the transaction has not been promoted and 
        // cannot be promoted so it doesn't matter what guid is returned.
        // 
        // This leaves two specific sets of states that MUST override this... 
        // 1) Any state where the transaction could be promoted.
        // 2) Any state where the transaction is already promoted. 
        internal virtual Guid get_Identifier( InternalTransaction tx )
        {
            return Guid.Empty;
        } 

 
        // Every state derived from the base must override status 
        internal abstract TransactionStatus get_Status( InternalTransaction tx );
 

        internal virtual void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
 
        internal virtual void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }

 
        internal virtual bool EnlistPromotableSinglePhase(
            InternalTransaction tx, 
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification, 
            Transaction atomicTransaction
            ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }
 

        internal virtual void CompleteBlockingClone( InternalTransaction tx ) 
        { 
        }
 

        internal virtual void CompleteAbortingClone( InternalTransaction tx )
        {
        } 

 
        internal virtual void CreateBlockingClone( InternalTransaction tx ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }


        internal virtual void CreateAbortingClone( InternalTransaction tx ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        } 

 
        internal virtual void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() ));
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            } 

            throw new InvalidOperationException(); 
        }


        internal virtual void ChangeStateTransactionCommitted( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            }

            throw new InvalidOperationException();
        } 

 
        internal virtual void InDoubtFromEnlistment( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error )
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" );
            } 

            throw new InvalidOperationException(); 
        } 

 
        internal virtual void ChangeStatePromotedAborted( InternalTransaction tx )
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() ));
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            } 

            throw new InvalidOperationException(); 
        }


        internal virtual void ChangeStatePromotedCommitted( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            }

            throw new InvalidOperationException();
        } 

 
        internal virtual void InDoubtFromDtc( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error )
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" );
            } 

            throw new InvalidOperationException(); 
        } 

 
        internal virtual void ChangeStatePromotedPhase0( InternalTransaction tx )
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() ));
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            } 

            throw new InvalidOperationException(); 
        }


        internal virtual void ChangeStatePromotedPhase1( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error ) 
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            }

            throw new InvalidOperationException();
        } 

 
        internal virtual void ChangeStateAbortedDuringPromotion( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error )
            {
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" );
            } 

            throw new InvalidOperationException(); 
        } 

 
        internal virtual void Timeout( InternalTransaction tx )
        {
        }
 

        internal virtual void Phase0VolatilePrepareDone( InternalTransaction tx ) 
        { 
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() ));
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }


        internal virtual void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 

        internal virtual void RestartCommitIfNeeded( InternalTransaction tx )
        {
            Debug.Assert( false, string.Format( null, "Invalid Event for State; Current State: {0}", this.GetType() )); 
            if ( DiagnosticTrace.Error )
            { 
                InvalidOperationExceptionTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), "" ); 
            }
 
            throw new InvalidOperationException( );
        }

 
        internal virtual bool ContinuePhase0Prepares()
        { 
            return false; 
        }
 

        internal virtual bool ContinuePhase1Prepares()
        {
            return false; 
        }
 
 
        internal virtual void Promote( InternalTransaction tx )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }

 
        internal virtual void DisposeRoot( InternalTransaction tx )
        { 
        } 

 
        internal virtual bool IsCompleted( InternalTransaction tx )
        {
            tx.needPulse = true;
 
            return false;
        } 
 
        protected void AddVolatileEnlistment( ref VolatileEnlistmentSet enlistments, Enlistment enlistment )
        { 
            // Grow the enlistment array if necessary.
            if( enlistments.volatileEnlistmentCount == enlistments.volatileEnlistmentSize )
            {
                InternalEnlistment[] newEnlistments = 
                    new InternalEnlistment [enlistments.volatileEnlistmentSize + InternalTransaction.volatileArrayIncrement];
 
                if( enlistments.volatileEnlistmentSize > 0 ) 
                {
                    Array.Copy( 
                        enlistments.volatileEnlistments,
                        newEnlistments,
                        enlistments.volatileEnlistmentSize
                        ); 
                }
 
                enlistments.volatileEnlistmentSize += InternalTransaction.volatileArrayIncrement; 
                enlistments.volatileEnlistments = newEnlistments;
            } 

            // Add a new element to the end of the list
            enlistments.volatileEnlistments [enlistments.volatileEnlistmentCount] = enlistment.InternalEnlistment;
            enlistments.volatileEnlistmentCount++; 

            // Make it's state active. 
            VolatileEnlistmentState._VolatileEnlistmentActive.EnterState( 
                enlistments.volatileEnlistments [enlistments.volatileEnlistmentCount-1] );
        } 
    }


 
    // ActiveStates
    // 
    // All states for which the transaction is not done should derive from this state. 
    internal abstract class ActiveStates : TransactionState
    { 
        internal override TransactionStatus get_Status( InternalTransaction tx )
        {
            return TransactionStatus.Active;
        } 

 
        internal override void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate ) 
        {
            tx.transactionCompletedDelegate = (TransactionCompletedEventHandler) 
                System.Delegate.Combine( tx.transactionCompletedDelegate, transactionCompletedDelegate );
        }
    }
 

 
    // EnlistableStates 
    //
    // States for which it is ok to enlist. 
    internal abstract class EnlistableStates : ActiveStates
    {
        internal override Enlistment EnlistDurable(
            InternalTransaction tx, 
            Guid resourceManagerIdentifier,
            IEnlistmentNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        {
            // Can't support an enlistment that dosn't support SPC
            tx.promoteState.EnterState( tx );
            // Note that just because we did an EnterState above does not mean that the state will be 
            // the same when the next method is called.
            return tx.State.EnlistDurable( tx, resourceManagerIdentifier, enlistmentNotification, enlistmentOptions, atomicTransaction ); 
        } 

 
        internal override Enlistment EnlistDurable(
            InternalTransaction tx,
            Guid resourceManagerIdentifier,
            ISinglePhaseNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            ) 
        {
            if( tx.durableEnlistment != null || (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) 
            {
                // These circumstances cause promotion
                tx.promoteState.EnterState( tx );
                return tx.State.EnlistDurable( tx, resourceManagerIdentifier, enlistmentNotification, enlistmentOptions, atomicTransaction ); 
            }
 
            // Create a durable enlistment 
            Enlistment en = new Enlistment( resourceManagerIdentifier, tx, enlistmentNotification, enlistmentNotification, atomicTransaction );
            tx.durableEnlistment = en.InternalEnlistment; 
            DurableEnlistmentState._DurableEnlistmentActive.EnterState( tx.durableEnlistment );

            if ( DiagnosticTrace.Information )
            { 
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.durableEnlistment.EnlistmentTraceId, 
                    EnlistmentType.Durable, 
                    EnlistmentOptions.None
                    ); 
            }

            return en;
        } 

 
        internal override void Timeout( InternalTransaction tx ) 
        {
            if ( DiagnosticTrace.Warning ) 
            {
                TransactionTimeoutTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.TransactionTraceId
                    ); 
            }
 
            TimeoutException e = new TimeoutException( SR.GetString( SR.TraceTransactionTimeout )); 
            this.Rollback( tx, e );
        } 


        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context )
        { 
            // Promote the transaction.
            tx.promoteState.EnterState( tx ); 
 
            // Forward this call
            tx.State.GetObjectData( tx, serializationInfo, context ); 
        }


        internal override void CompleteBlockingClone( InternalTransaction tx ) 
        {
            // A blocking clone simulates a phase 0 volatile 
 
            // decrement the number of dependentClones
            tx.phase0Volatiles.dependentClones--; 
            Debug.Assert( tx.phase0Volatiles.dependentClones >= 0 );

            // Make certain we increment the right list.
            Debug.Assert( tx.phase0Volatiles.preparedVolatileEnlistments <= 
                tx.phase0Volatiles.volatileEnlistmentCount + tx.phase0Volatiles.dependentClones );
 
            // Check to see if all of the volatile enlistments are done. 
            if( tx.phase0Volatiles.preparedVolatileEnlistments ==
                tx.phase0VolatileWaveCount + tx.phase0Volatiles.dependentClones ) 
            {
                tx.State.Phase0VolatilePrepareDone( tx );
            }
        } 

 
        internal override void CompleteAbortingClone( InternalTransaction tx ) 
        {
            // A blocking clone simulates a phase 1 volatile 
            //
            // Unlike a blocking clone however the aborting clones need to be accounted
            // for specifically.  So when one is complete remove it from the list.
            tx.phase1Volatiles.dependentClones--; 
            Debug.Assert( tx.phase1Volatiles.dependentClones >= 0 );
        } 
 

        internal override void CreateBlockingClone( InternalTransaction tx ) 
        {
            // A blocking clone simulates a phase 0 volatile
            tx.phase0Volatiles.dependentClones++;
        } 

 
        internal override void CreateAbortingClone( InternalTransaction tx ) 
        {
            // An aborting clone simulates a phase 1 volatile 
            tx.phase1Volatiles.dependentClones++;
        }

 
        internal override void Promote( InternalTransaction tx )
        { 
 
            tx.promoteState.EnterState( tx );
            tx.State.CheckForFinishedTransaction( tx ); 
        }
    }

 

    // TransactionStateActive 
    // 
    // Transaction state before commit has been called
    internal class TransactionStateActive : EnlistableStates 
    {
        internal override void EnterState( InternalTransaction tx )
        {
            // Set the transaction state 
            CommonEnterState( tx );
 
            // Yeah it's active. 
        }
 

        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        {
            // Store the given values 
            tx.asyncCommit = asyncCommit;
            tx.asyncCallback = asyncCallback; 
            tx.asyncState = asyncState; 

            // Start the process for commit. 
            _TransactionStatePhase0.EnterState( tx );
        }

 
        internal override void Rollback( InternalTransaction tx, Exception e )
        { 
            // Start the process for abort.  From the active state we can transition directly 
            // to the aborted state.
 
            if( tx.innerException == null )
            {
                tx.innerException = e;
            } 

            _TransactionStateAborted.EnterState( tx ); 
        } 

 
        internal override Enlistment EnlistVolatile(
            InternalTransaction tx,
            IEnlistmentNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        { 
            Enlistment enlistment = new Enlistment( tx, enlistmentNotification, null, atomicTransaction, enlistmentOptions );
            if( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) 
            {
                AddVolatileEnlistment( ref tx.phase0Volatiles, enlistment );
            }
            else 
            {
                AddVolatileEnlistment( ref tx.phase1Volatiles, enlistment ); 
            } 

            if ( DiagnosticTrace.Information ) 
            {
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    enlistment.InternalEnlistment.EnlistmentTraceId,
                    EnlistmentType.Volatile, 
                    enlistmentOptions
                    ); 
            } 

            return enlistment; 
        }


        internal override Enlistment EnlistVolatile( 
            InternalTransaction tx,
            ISinglePhaseNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        {
            Enlistment enlistment = new Enlistment( tx, enlistmentNotification, enlistmentNotification, atomicTransaction, enlistmentOptions );
            if( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 )
            { 
                AddVolatileEnlistment( ref tx.phase0Volatiles, enlistment );
            } 
            else 
            {
                AddVolatileEnlistment( ref tx.phase1Volatiles, enlistment ); 
            }

            if ( DiagnosticTrace.Information )
            { 
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    enlistment.InternalEnlistment.EnlistmentTraceId, 
                    EnlistmentType.Volatile, 
                    enlistmentOptions
                    ); 
            }

            return enlistment;
        } 

 
        internal override bool EnlistPromotableSinglePhase( 
            InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification,
            Transaction atomicTransaction 
            )
        {
            // Delegation will fail if there is a durable enlistment
            if( tx.durableEnlistment != null ) 
            {
                return false; 
            } 

            _TransactionStatePSPEOperation.PSPEInitialize( tx, promotableSinglePhaseNotification ); 

            // Create a durable enlistment.
            Enlistment en = new Enlistment( tx, promotableSinglePhaseNotification, atomicTransaction );
            tx.durableEnlistment = en.InternalEnlistment; 
            if ( DiagnosticTrace.Information )
            { 
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.durableEnlistment.EnlistmentTraceId,
                    EnlistmentType.PromotableSinglePhase, 
                    EnlistmentOptions.None
                    );
            }
 
            // Specify the promoter for the transaction.
            tx.promoter = promotableSinglePhaseNotification; 
 
            // Change the state that the transaction will promote to.  Normally this would be simply
            // be TransactionStatePromoted.  However it now needs to promote to a delegated state. 
            tx.promoteState = _TransactionStateDelegated;

            // Pud the enlistment in an active state
            DurableEnlistmentState._DurableEnlistmentActive.EnterState( tx.durableEnlistment ); 

            // Hand back the enlistment. 
            return true; 
        }
 

        // Volatile prepare is done for
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        { 
            // Ignore this event at the moment.  It can be checked again in Phase0
        } 
 

        internal override void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        {
            // Ignore this event at the moment.  It can be checked again in Phase1
        }
 

        internal override void DisposeRoot( InternalTransaction tx ) 
        { 
            tx.State.Rollback( tx, null );
        } 

    }

 
    // TransactionStateSubordinateActive
    // 
    // This is a transaction that is a very basic subordinate to some external TM. 
    internal class TransactionStateSubordinateActive : TransactionStateActive
    { 
        // Every state must override EnterState
        internal override void EnterState( InternalTransaction tx )
        {
            // Set the transaction state 
            CommonEnterState( tx );
 
            Debug.Assert( tx.promoter != null, "Transaction Promoter is Null entering SubordinateActive" ); 
        }
 

        internal override void Rollback( InternalTransaction tx, Exception e )
        {
            // Start the process for abort.  From the active state we can transition directly 
            // to the aborted state.
 
            if( tx.innerException == null ) 
            {
                tx.innerException = e; 
            }

            ((ISimpleTransactionSuperior)tx.promoter).Rollback();
            _TransactionStateAborted.EnterState( tx ); 
        }
 
 
        internal override Enlistment EnlistVolatile(
            InternalTransaction tx, 
            IEnlistmentNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction
            ) 
        {
            tx.promoteState.EnterState( tx ); 
            return tx.State.EnlistVolatile( tx, enlistmentNotification, enlistmentOptions, atomicTransaction ); 
        }
 

        internal override Enlistment EnlistVolatile(
            InternalTransaction tx,
            ISinglePhaseNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            ) 
        {
            tx.promoteState.EnterState( tx ); 
            return tx.State.EnlistVolatile( tx, enlistmentNotification, enlistmentOptions, atomicTransaction );
        }

 
        // Every state derived from the base must override status
        internal override TransactionStatus get_Status( InternalTransaction tx ) 
        { 
            tx.promoteState.EnterState( tx );
            return tx.State.get_Status( tx ); 
        }


        internal override void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate ) 
        {
            tx.promoteState.EnterState( tx ); 
            tx.State.AddOutcomeRegistrant( tx, transactionCompletedDelegate ); 
        }
 

        internal override bool EnlistPromotableSinglePhase(
            InternalTransaction tx,
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification, 
            Transaction atomicTransaction
            ) 
        { 
            return false;
        } 


        internal override void CreateBlockingClone( InternalTransaction tx )
        { 
            tx.promoteState.EnterState( tx );
            tx.State.CreateBlockingClone( tx ); 
        } 

 
        internal override void CreateAbortingClone( InternalTransaction tx )
        {
            tx.promoteState.EnterState( tx );
            tx.State.CreateAbortingClone( tx ); 
        }
    } 
 

    // TransactionStatePhase0 
    //
    // A transaction that is in the beginning stage of committing.
    internal class TransactionStatePhase0 : EnlistableStates
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            // Set the transaction state 
            CommonEnterState( tx );
 
            // Get a copy of the current volatile enlistment count before entering this loop so that other
            // threads don't affect the operation of this loop.
            int volatileCount = tx.phase0Volatiles.volatileEnlistmentCount;
            int dependentCount = tx.phase0Volatiles.dependentClones; 

            // Store the number of phase0 volatiles for this wave. 
            tx.phase0VolatileWaveCount = volatileCount; 

            // Check for volatile enlistments 
            if( tx.phase0Volatiles.preparedVolatileEnlistments < volatileCount + dependentCount )
            {
                // Broadcast prepare to the phase 0 enlistments
                for( int i = 0; i < volatileCount; i++ ) 
                {
                    tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.ChangeStatePreparing( tx.phase0Volatiles.volatileEnlistments [i] ); 
                    if( !tx.State.ContinuePhase0Prepares() ) 
                    {
                        break; 
                    }
                }
            }
            else 
            {
                // No volatile enlistments.  Start phase 1. 
                _TransactionStateVolatilePhase1.EnterState( tx ); 
            }
        } 


        internal override Enlistment EnlistDurable(
            InternalTransaction tx, 
            Guid resourceManagerIdentifier,
            IEnlistmentNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        {
            Enlistment en = base.EnlistDurable( tx, resourceManagerIdentifier, enlistmentNotification,
                enlistmentOptions, atomicTransaction );
 
            // Calling durable enlist in Phase0 may cause the transaction to promote.  Leverage the promoted
            tx.State.RestartCommitIfNeeded( tx ); 
            return en; 
        }
 

        internal override Enlistment EnlistDurable(
            InternalTransaction tx,
            Guid resourceManagerIdentifier, 
            ISinglePhaseNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction 
            )
        { 
            Enlistment en = base.EnlistDurable( tx, resourceManagerIdentifier, enlistmentNotification,
                enlistmentOptions, atomicTransaction );

            // Calling durable enlist in Phase0 may cause the transaction to promote.  Leverage the promoted 
            tx.State.RestartCommitIfNeeded( tx );
            return en; 
        } 

 
        internal override Enlistment EnlistVolatile(
            InternalTransaction tx,
            IEnlistmentNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        { 
            Enlistment enlistment = new Enlistment( tx, enlistmentNotification, null, atomicTransaction, enlistmentOptions );
            if( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) 
            {
                AddVolatileEnlistment( ref tx.phase0Volatiles, enlistment );
            }
            else 
            {
                AddVolatileEnlistment( ref tx.phase1Volatiles, enlistment ); 
            } 

            if ( DiagnosticTrace.Information ) 
            {
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    enlistment.InternalEnlistment.EnlistmentTraceId,
                    EnlistmentType.Volatile, 
                    enlistmentOptions
                    ); 
            } 

            return enlistment; 
        }


        internal override Enlistment EnlistVolatile( 
            InternalTransaction tx,
            ISinglePhaseNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions, 
            Transaction atomicTransaction
            ) 
        {
            Enlistment enlistment = new Enlistment( tx, enlistmentNotification, enlistmentNotification, atomicTransaction, enlistmentOptions );

            if( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) 
            {
                AddVolatileEnlistment( ref tx.phase0Volatiles, enlistment ); 
            } 
            else
            { 
                AddVolatileEnlistment( ref tx.phase1Volatiles, enlistment );
            }

            if ( DiagnosticTrace.Information ) 
            {
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    enlistment.InternalEnlistment.EnlistmentTraceId, 
                    EnlistmentType.Volatile,
                    enlistmentOptions 
                    );
            }

            return enlistment; 
        }
 
 
        internal override void Rollback( InternalTransaction tx, Exception e )
        { 
            ChangeStateTransactionAborted( tx, e );
        }

 
        // Support PSPE enlistment during Phase0 prepare notification.
 
        internal override bool EnlistPromotableSinglePhase( 
            InternalTransaction tx,
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification, 
            Transaction atomicTransaction
            )
        {
 
            // Delegation will fail if there is a durable enlistment
            if( tx.durableEnlistment != null ) 
            { 
                return false;
            } 

            // Initialize PSPE Operation and call initialize on IPromotableSinglePhaseNotification
            _TransactionStatePSPEOperation.Phase0PSPEInitialize( tx, promotableSinglePhaseNotification );
 
            // Create a durable enlistment.
            Enlistment en = new Enlistment( tx, promotableSinglePhaseNotification, atomicTransaction ); 
            tx.durableEnlistment = en.InternalEnlistment; 
            if ( DiagnosticTrace.Information )
            { 
                EnlistmentTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.durableEnlistment.EnlistmentTraceId,
                    EnlistmentType.PromotableSinglePhase,
                    EnlistmentOptions.None 
                    );
            } 
 
            // Specify the promoter for the transaction.
            tx.promoter = promotableSinglePhaseNotification; 

            // Change the state that the transaction will promote to.  Normally this would be simply
            // be TransactionStatePromoted.  However it now needs to promote to a delegated state.
            tx.promoteState = _TransactionStateDelegated; 

            // Put the enlistment in an active state 
            DurableEnlistmentState._DurableEnlistmentActive.EnterState( tx.durableEnlistment ); 

            // Hand back the enlistment. 
            return true;
        }

        // Volatile prepare is done for 
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        { 
            // Check to see if any Phase0Volatiles have been added in Phase0. 
            // If so go through the list again.
 
            // Get a copy of the current volatile enlistment count before entering this loop so that other
            // threads don't affect the operation of this loop.
            int volatileCount = tx.phase0Volatiles.volatileEnlistmentCount;
            int dependentCount = tx.phase0Volatiles.dependentClones; 

            // Store the number of phase0 volatiles for this wave. 
            tx.phase0VolatileWaveCount = volatileCount; 

            // Check for volatile enlistments 
            if( tx.phase0Volatiles.preparedVolatileEnlistments < volatileCount + dependentCount )
            {
                // Broadcast prepare to the phase 0 enlistments
                for( int i = 0; i < volatileCount; i++ ) 
                {
                    tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.ChangeStatePreparing( tx.phase0Volatiles.volatileEnlistments [i] ); 
                    if( !tx.State.ContinuePhase0Prepares() ) 
                    {
                        break; 
                    }
                }
            }
            else 
            {
                // No volatile enlistments.  Start phase 1. 
                _TransactionStateVolatilePhase1.EnterState( tx ); 
            }
        } 


        internal override void Phase1VolatilePrepareDone( InternalTransaction tx )
        { 
            // Ignore this for now it can be checked again in Phase 1
        } 
 

        internal override void RestartCommitIfNeeded( InternalTransaction tx ) 
        {
            // Commit does not need to be restarted
        }
 
        internal override bool ContinuePhase0Prepares()
        { 
            return true; 
        }
 
        internal override void Promote( InternalTransaction tx )
        {

            tx.promoteState.EnterState( tx ); 
            tx.State.CheckForFinishedTransaction( tx );
            tx.State.RestartCommitIfNeeded( tx ); 
        } 

 
        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        {
            if( tx.innerException == null )
            { 
                tx.innerException = e;
            } 
 
            _TransactionStateAborted.EnterState( tx );
        } 


        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context )
        { 
            // Promote the transaction.
            tx.promoteState.EnterState( tx ); 
 
            // Forward this call
            tx.State.GetObjectData( tx, serializationInfo, context ); 

            // Restart the commit process.
            tx.State.RestartCommitIfNeeded( tx );
        } 

    } 
 
    // TransactionStateVolatilePhase1
    // 
    // Represents the transaction state during phase 1 preparing volatile enlistments
    internal class TransactionStateVolatilePhase1 : ActiveStates
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            // Set the transaction state 
            CommonEnterState( tx ); 

            // Mark the committable transaction as complete. 
            tx.committableTransaction.complete = true;

            // If at this point there are phase1 dependent clones abort the transaction
            if( tx.phase1Volatiles.dependentClones != 0 ) 
            {
                _TransactionStateAborted.EnterState( tx ); 
                return; 
            }
 
            if( tx.phase1Volatiles.volatileEnlistmentCount == 1 && tx.durableEnlistment == null
                && tx.phase1Volatiles.volatileEnlistments [0].SinglePhaseNotification != null )
            {
                // This is really a case of SPC for volatiles 
                _TransactionStateVolatileSPC.EnterState( tx );
            } 
            else if( tx.phase1Volatiles.volatileEnlistmentCount > 0 ) 
            {
                // Broadcast prepare to the phase 0 enlistments 
                for( int i = 0; i < tx.phase1Volatiles.volatileEnlistmentCount; i++ )
                {
                    tx.phase1Volatiles.volatileEnlistments [i].twoPhaseState.ChangeStatePreparing( tx.phase1Volatiles.volatileEnlistments [i] );
                    if( !tx.State.ContinuePhase1Prepares() ) 
                    {
                        break; 
                    } 
                }
            } 
            else
            {
                // No volatile phase 1 enlistments.  Start phase durable SPC.
                _TransactionStateSPC.EnterState( tx ); 
            }
        } 
 

        internal override void Rollback( InternalTransaction tx, Exception e ) 
        {
            ChangeStateTransactionAborted( tx, e );
        }
 

        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e ) 
        { 
            if( tx.innerException == null )
            { 
                tx.innerException = e;
            }

            _TransactionStateAborted.EnterState( tx ); 
        }
 
 
        // Volatile prepare is done for
        internal override void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        {
            _TransactionStateSPC.EnterState( tx );
        }
 

        internal override bool ContinuePhase1Prepares() 
        { 
            return true;
        } 

        internal override void Timeout( InternalTransaction tx )
        {
            if ( DiagnosticTrace.Warning ) 
            {
                TransactionTimeoutTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.TransactionTraceId 
                    );
            } 

            TimeoutException e = new TimeoutException( SR.GetString( SR.TraceTransactionTimeout ));
            this.Rollback( tx, e );
        } 
    }
 
 
    // TransactionStateVolatileSPC
    // 
    // Represents the transaction state during phase 1 when issuing SPC to a volatile enlistment
    internal class TransactionStateVolatileSPC : ActiveStates
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            // Set the transaction state 
            CommonEnterState( tx ); 

            Debug.Assert( tx.phase1Volatiles.volatileEnlistmentCount == 1, 
                "There must be exactly 1 phase 1 volatile enlistment for TransactionStateVolatileSPC" );

            tx.phase1Volatiles.volatileEnlistments [0].twoPhaseState.ChangeStateSinglePhaseCommit(
                tx.phase1Volatiles.volatileEnlistments [0] ); 
        }
 
 
        internal override void ChangeStateTransactionCommitted( InternalTransaction tx )
        { 
            // The durable enlistment must have committed.  Go to the committed state.
            _TransactionStateCommitted.EnterState( tx );
        }
 

        internal override void InDoubtFromEnlistment( InternalTransaction tx ) 
        { 
            // The transaction is indoubt
            _TransactionStateInDoubt.EnterState( tx ); 
        }


        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e ) 
        {
            if( tx.innerException == null ) 
            { 
                tx.innerException = e;
            } 

            // The durable enlistment must have aborted.  Go to the aborted state.
            _TransactionStateAborted.EnterState( tx );
        } 
    }
 
 

    // TransactionStateSPC 
    //
    // Represents the transaction state during phase 1
    internal class TransactionStateSPC : ActiveStates
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            // Set the transaction state 
            CommonEnterState( tx );
 
            // Check for a durable enlistment
            if( tx.durableEnlistment != null )
            {
                // Send SPC to the durable enlistment 
                tx.durableEnlistment.State.ChangeStateCommitting( tx.durableEnlistment );
            } 
            else 
            {
                // No durable enlistments.  Go to the committed state. 
                _TransactionStateCommitted.EnterState( tx );
            }
        }
 

        internal override void ChangeStateTransactionCommitted( InternalTransaction tx ) 
        { 
            // The durable enlistment must have committed.  Go to the committed state.
            _TransactionStateCommitted.EnterState( tx ); 
        }


        internal override void InDoubtFromEnlistment( InternalTransaction tx ) 
        {
            // The transaction is indoubt 
            _TransactionStateInDoubt.EnterState( tx ); 
        }
 

        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        {
            if( tx.innerException == null ) 
            {
                tx.innerException = e; 
            } 

            // The durable enlistment must have aborted.  Go to the aborted state. 
            _TransactionStateAborted.EnterState( tx );
        }
    }
 

    // TransactionStateEnded 
    // 
    // This state indicates that the transaction is in some form of ended state.
    internal abstract class TransactionStateEnded : TransactionState 
    {
        internal override void EnterState( InternalTransaction tx )
        {
            if( tx.needPulse ) 
            {
                System.Threading.Monitor.Pulse( tx ); 
            } 
        }
 

        internal override void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate )
        {
            if( transactionCompletedDelegate != null ) 
            {
                TransactionEventArgs args = new TransactionEventArgs(); 
                args.transaction = tx.outcomeSource.InternalClone(); 
                transactionCompletedDelegate( args.transaction, args );
            } 
        }


        internal override bool IsCompleted( InternalTransaction tx ) 
        {
            return true; 
        } 
    }
 

    // TransactionStateAborted
    //
    // The transaction has been aborted.  Abort is itempotent and can be called again but any 
    // other operations on the transaction should fail.
    internal class TransactionStateAborted : TransactionStateEnded 
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            base.EnterState( tx );

            // Set the transaction state
            CommonEnterState( tx ); 

            // Do NOT mark the committable transaction as complete because it is aborting. 
 
            // Notify the enlistments that the transaction has aborted
            for( int i = 0; i < tx.phase0Volatiles.volatileEnlistmentCount; i++ ) 
            {
                tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.InternalAborted( tx.phase0Volatiles.volatileEnlistments [i] );
            }
 
            for( int i = 0; i < tx.phase1Volatiles.volatileEnlistmentCount; i++ )
            { 
                tx.phase1Volatiles.volatileEnlistments [i].twoPhaseState.InternalAborted( tx.phase1Volatiles.volatileEnlistments [i] ); 
            }
 
            // Notify the durable enlistment
            if( tx.durableEnlistment != null )
            {
                tx.durableEnlistment.State.InternalAborted( tx.durableEnlistment ); 
            }
 
            // Remove this from the timeout list 
            TransactionManager.TransactionTable.Remove( tx );
 
            if ( DiagnosticTrace.Warning )
            {
                TransactionAbortedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.TransactionTraceId 
                    );
            } 
 
            // Fire Completion for anyone listening
            tx.FireCompletion( ); 

            // Check to see if we need to release some waiter.
            if( tx.asyncCommit )
            { 
                tx.SignalAsyncCompletion();
            } 
        } 

 
        internal override TransactionStatus get_Status( InternalTransaction tx )
        {
            return TransactionStatus.Aborted;
        } 

 
        internal override void Rollback( InternalTransaction tx, Exception e ) 
        {
            // Abort is itempotent.  Ignore this if the transaction is already aborted. 
        }


        internal override void BeginCommit(InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState) 
        {
            // End Commit Must throw a TransactionAbortedException to let the caller know that the tx aborted. 
            throw CreateTransactionAbortedException( tx ); 
        }
 

        internal override void EndCommit( InternalTransaction tx )
        {
            // End Commit Must throw a TransactionAbortedException to let the caller know that the tx aborted. 
            throw CreateTransactionAbortedException( tx );
        } 
 

        internal override void RestartCommitIfNeeded( InternalTransaction tx ) 
        {
            // Commit does not need to be restarted.
        }
 

        internal override void Timeout( InternalTransaction tx ) 
        { 
            // The transaction has aborted already
        } 


        // When all enlisments respond to prepare this event will fire.
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx ) 
        {
            // Since the transaction is aborted ignore it. 
        } 

 
        internal override void Phase1VolatilePrepareDone( InternalTransaction tx )
        {
            // Since the transaction is aborted ignore it.
        } 

 
        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e ) 
        {
            // Yes, yes, yes... I already know. 
        }


        internal override void ChangeStatePromotedAborted(InternalTransaction tx) 
        {
            // The transaction must have aborted during promotion 
        } 

 
        internal override void ChangeStateAbortedDuringPromotion(InternalTransaction tx)
        {
            // This is fine too.
        } 

 
        internal override void CreateBlockingClone( InternalTransaction tx ) 
        {
            throw CreateTransactionAbortedException( tx ); 
        }


        internal override void CreateAbortingClone( InternalTransaction tx ) 
        {
            throw CreateTransactionAbortedException( tx ); 
        } 

 
        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context )
        {
            throw CreateTransactionAbortedException( tx );
        } 

 
        internal override void CheckForFinishedTransaction( InternalTransaction tx ) 
        {
            throw CreateTransactionAbortedException( tx ); 
        }


        private TransactionException CreateTransactionAbortedException( InternalTransaction tx ) 
        {
            return TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), SR.GetString( SR.TransactionAborted ), tx.innerException ); 
        } 
    }
 


    // TransactionStateCommitted
    // 
    // This state indicates that the transaction has been committed.  Basically any
    // operations on the transaction should fail at this point. 
    internal class TransactionStateCommitted : TransactionStateEnded 
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            base.EnterState( tx );

            // Set the transaction state 
            CommonEnterState( tx );
 
            // Notify the phase 0 enlistments that the transaction has aborted 
            for( int i = 0; i < tx.phase0Volatiles.volatileEnlistmentCount; i++ )
            { 
                tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.InternalCommitted( tx.phase0Volatiles.volatileEnlistments [i] );
            }

            // Notify the phase 1 enlistments that the transaction has aborted 
            for( int i = 0; i < tx.phase1Volatiles.volatileEnlistmentCount; i++ )
            { 
                tx.phase1Volatiles.volatileEnlistments [i].twoPhaseState.InternalCommitted( tx.phase1Volatiles.volatileEnlistments [i] ); 
            }
 
            // Remove this from the timeout list
            TransactionManager.TransactionTable.Remove( tx );

            if ( DiagnosticTrace.Verbose ) 
            {
                TransactionCommittedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.TransactionTraceId 
                    );
            } 

            // Fire Completion for anyone listening
            tx.FireCompletion( );
 
            // Check to see if we need to release some waiter.
            if( tx.asyncCommit ) 
            { 
                tx.SignalAsyncCompletion();
            } 
        }


        internal override TransactionStatus get_Status( InternalTransaction tx ) 
        {
            return TransactionStatus.Committed; 
        } 

 
        internal override void Rollback( InternalTransaction tx, Exception e )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 

 
        internal override void EndCommit(InternalTransaction tx) 
        {
            // End Commit does nothing because life is wonderful and we are happy! 
        }
    }

 
    // TransactionStateInDoubt
    // 
    // This state indicates that the transaction is in doubt 
    internal class TransactionStateInDoubt : TransactionStateEnded
    { 
        internal override void EnterState( InternalTransaction tx )
        {
            base.EnterState( tx );
 
            // Set the transaction state
            CommonEnterState( tx ); 
 
            // Notify the phase 0 enlistments that the transaction has aborted
            for( int i = 0; i < tx.phase0Volatiles.volatileEnlistmentCount; i++ ) 
            {
                tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.InternalIndoubt( tx.phase0Volatiles.volatileEnlistments [i] );
            }
 
            // Notify the phase 1 enlistments that the transaction has aborted
            for( int i = 0; i < tx.phase1Volatiles.volatileEnlistmentCount; i++ ) 
            { 
                tx.phase1Volatiles.volatileEnlistments [i].twoPhaseState.InternalIndoubt( tx.phase1Volatiles.volatileEnlistments [i] );
            } 

            // Remove this from the timeout list
            TransactionManager.TransactionTable.Remove( tx );
 
            if ( DiagnosticTrace.Warning )
            { 
                TransactionInDoubtTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.TransactionTraceId
                    ); 
            }

            // Fire Completion for anyone listening
            tx.FireCompletion( ); 

            // Check to see if we need to release some waiter. 
            if( tx.asyncCommit ) 
            {
                tx.SignalAsyncCompletion(); 
            }
        }

 
        internal override TransactionStatus get_Status( InternalTransaction tx )
        { 
            return TransactionStatus.InDoubt; 
        }
 

        internal override void Rollback( InternalTransaction tx, Exception e )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
 
        internal override void EndCommit(InternalTransaction tx)
        { 
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException );
        }

 
        internal override void CheckForFinishedTransaction( InternalTransaction tx )
        { 
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException ); 
        }
 

        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context )
        {
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException ); 
        }
    } 
 

 
    // TransactionStatePromotedBase
    //
    // This is the base class for promoted states.  It's main function is to pass calls
    // through to the distributed transaction. 
    internal abstract class TransactionStatePromotedBase : TransactionState
    { 
        internal override TransactionStatus get_Status( InternalTransaction tx ) 
        {
            // Since the distributed transaction manager will always tell the ltm about state 
            // changes via the enlistment that the Ltm has with it, the Ltm can tell client
            // code what it thinks the state is on behalf of the distributed tm.  Doing so
            // prevents ----s with state changes of the promoted tx to the Ltm being
            // told about those changes. 
            return TransactionStatus.Active;
        } 
 

        internal override Enlistment EnlistVolatile( 
            InternalTransaction tx,
            IEnlistmentNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            )
        { 
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." ); 
            // Don't get in the way for new volatile enlistments
 
            // Don't hold locks while calling into the promoted tx
            System.Threading.Monitor.Exit( tx );
            try
            { 
                Enlistment en = new Enlistment( enlistmentNotification, tx, atomicTransaction );
                EnlistmentState._EnlistmentStatePromoted.EnterState( en.InternalEnlistment ); 
 
                en.InternalEnlistment.PromotedEnlistment =
                    tx.PromotedTransaction.EnlistVolatile( 
                        en.InternalEnlistment, enlistmentOptions );
                return en;
            }
            finally 
            {
#pragma warning disable 0618 
                //@ 
                System.Threading.Monitor.Enter(tx);
#pragma warning restore 0618 
            }
        }

 
        internal override Enlistment EnlistVolatile(
            InternalTransaction tx, 
            ISinglePhaseNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            )
        {
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." );
            // Don't get in the way for new volatile enlistments 

            // Don't hold locks while calling into the promoted tx 
            System.Threading.Monitor.Exit( tx ); 
            try
            { 
                Enlistment en = new Enlistment( enlistmentNotification, tx, atomicTransaction );
                EnlistmentState._EnlistmentStatePromoted.EnterState( en.InternalEnlistment );

                en.InternalEnlistment.PromotedEnlistment = 
                    tx.PromotedTransaction.EnlistVolatile(
                        en.InternalEnlistment, enlistmentOptions ); 
                return en; 
            }
            finally 
            {
#pragma warning disable 0618
                //@
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
            } 
        } 

 
        internal override Enlistment EnlistDurable(
            InternalTransaction tx,
            Guid resourceManagerIdentifier,
            IEnlistmentNotification enlistmentNotification, 
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction 
            ) 
        {
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." ); 

            // Don't hold locks while calling into the promoted tx
            System.Threading.Monitor.Exit( tx );
            try 
            {
                Enlistment en = new Enlistment( 
                    resourceManagerIdentifier, 
                    tx,
                    enlistmentNotification, 
                    null,
                    atomicTransaction
                    );
                EnlistmentState._EnlistmentStatePromoted.EnterState( en.InternalEnlistment ); 

                en.InternalEnlistment.PromotedEnlistment = 
                    tx.PromotedTransaction.EnlistDurable( 
                        resourceManagerIdentifier,
                        (DurableInternalEnlistment)en.InternalEnlistment, 
                        false,
                        enlistmentOptions
                        );
                return en; 
            }
            finally 
            { 
#pragma warning disable 0618
                //@ 
                System.Threading.Monitor.Enter(tx);
#pragma warning restore 0618
            }
        } 

 
        internal override Enlistment EnlistDurable( 
            InternalTransaction tx,
            Guid resourceManagerIdentifier, 
            ISinglePhaseNotification enlistmentNotification,
            EnlistmentOptions enlistmentOptions,
            Transaction atomicTransaction
            ) 
        {
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." ); 
 
            // Don't hold locks while calling into the promoted tx
            System.Threading.Monitor.Exit( tx ); 
            try
            {
                Enlistment en = new Enlistment(
                    resourceManagerIdentifier, 
                    tx,
                    enlistmentNotification, 
                    enlistmentNotification, 
                    atomicTransaction
                    ); 
                EnlistmentState._EnlistmentStatePromoted.EnterState( en.InternalEnlistment );

                en.InternalEnlistment.PromotedEnlistment =
                    tx.PromotedTransaction.EnlistDurable( 
                        resourceManagerIdentifier,
                        (DurableInternalEnlistment)en.InternalEnlistment, 
                        true, 
                        enlistmentOptions
                        ); 
                return en;
            }
            finally
            { 
#pragma warning disable 0618
                //@ 
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
            } 
        }


        internal override void Rollback( InternalTransaction tx, Exception e ) 
        {
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." ); 
            // Forward this on to the promoted transaction. 

            if( tx.innerException == null ) 
            {
                tx.innerException = e;
            }
 
            // Don't hold locks while calling into the promoted tx
            System.Threading.Monitor.Exit( tx ); 
            try 
            {
                tx.PromotedTransaction.Rollback( ); 
            }
            finally
            {
#pragma warning disable 0618 
                //@
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618 
            }
        } 


        internal override Guid get_Identifier( InternalTransaction tx )
        { 
            return tx.PromotedTransaction.Identifier;
        } 
 

        internal override void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate ) 
        {
            // Add this guy to the list of people to be notified of the outcome.
            tx.transactionCompletedDelegate = (TransactionCompletedEventHandler)
                System.Delegate.Combine( tx.transactionCompletedDelegate, transactionCompletedDelegate ); 
        }
 
 
        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        { 
            // Store the given values
            tx.asyncCommit = asyncCommit;
            tx.asyncCallback = asyncCallback;
            tx.asyncState = asyncState; 

            // Start the commit process. 
            _TransactionStatePromotedCommitting.EnterState( tx ); 
        }
 

        internal override void RestartCommitIfNeeded( InternalTransaction tx )
        {
            _TransactionStatePromotedP0Wave.EnterState( tx ); 
        }
 
 
        internal override bool EnlistPromotableSinglePhase(
            InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, 
            Transaction atomicTransaction
            )
        {
            // The transaction has been promoted and cannot support a promotable singe phase enlistment 
            return false;
        } 
 

        internal override void CompleteBlockingClone( InternalTransaction tx ) 
        {
            // First try to complete one of the internal blocking clones
            if( tx.phase0Volatiles.dependentClones > 0 )
            { 
                // decrement the number of clones
                tx.phase0Volatiles.dependentClones--; 
 
                // Make certain we increment the right list.
                Debug.Assert( tx.phase0Volatiles.preparedVolatileEnlistments <= 
                    tx.phase0Volatiles.volatileEnlistmentCount + tx.phase0Volatiles.dependentClones );

                // Check to see if all of the volatile enlistments are done.
                if( tx.phase0Volatiles.preparedVolatileEnlistments == 
                    tx.phase0VolatileWaveCount + tx.phase0Volatiles.dependentClones )
                { 
                    tx.State.Phase0VolatilePrepareDone( tx ); 
                }
            } 
            else
            {
                // Otherwise this must be a dependent clone created after promotion
                tx.phase0WaveDependentCloneCount--; 
                Debug.Assert( tx.phase0WaveDependentCloneCount >= 0 );
                if( tx.phase0WaveDependentCloneCount == 0 ) 
                { 
                    Oletx.OletxDependentTransaction dtx = tx.phase0WaveDependentClone;
                    tx.phase0WaveDependentClone = null; 

                    System.Threading.Monitor.Exit( tx );
                    try
                    { 
                        try
                        { 
                            dtx.Complete(); 
                        }
                        finally 
                        {
                            dtx.Dispose();
                        }
                    } 
                    finally
                    { 
#pragma warning disable 0618 
                        //@
                        System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
                    }
                }
            } 
        }
 
 
        internal override void CompleteAbortingClone( InternalTransaction tx )
        { 
            // If we have a phase1Volatile.VolatileDemux, we have a phase1 volatile enlistment
            // on the promoted transaction and it will take care of checking for incomplete aborting
            // dependent clones in its Prepare processing.
            if ( null != tx.phase1Volatiles.VolatileDemux ) 
            {
                tx.phase1Volatiles.dependentClones--; 
                Debug.Assert( tx.phase1Volatiles.dependentClones >= 0 ); 
            }
            else 
                // We need to deal with the aborting clones ourself, possibly completing the aborting
                // clone we have on the promoted transaction.
            {
                tx.abortingDependentCloneCount--; 
                Debug.Assert( 0 <= tx.abortingDependentCloneCount );
                if ( 0 == tx.abortingDependentCloneCount ) 
                { 
                    // We need to complete our dependent clone on the promoted transaction and null it out
                    // so if we get a new one, a new one will be created on the promoted transaction. 
                    Oletx.OletxDependentTransaction dtx = tx.abortingDependentClone;
                    tx.abortingDependentClone = null;

                    System.Threading.Monitor.Exit( tx ); 
                    try
                    { 
                        try 
                        {
                            dtx.Complete(); 
                        }
                        finally
                        {
                            dtx.Dispose(); 
                        }
                    } 
                    finally 
                    {
#pragma warning disable 0618 
                        //@
                        System.Threading.Monitor.Enter(tx);
#pragma warning restore 0618
                    } 
                }
            } 
        } 

 
        internal override void CreateBlockingClone( InternalTransaction tx )
        {
            // Once the transaction is promoted leverage the distributed
            // transaction manager for blocking dependent clones so that they 
            // will handle phase 0 waves.
            if( tx.phase0WaveDependentClone == null ) 
            { 
                tx.phase0WaveDependentClone = tx.PromotedTransaction.DependentClone( true );
            } 

            tx.phase0WaveDependentCloneCount++;
        }
 

        internal override void CreateAbortingClone( InternalTransaction tx ) 
        { 
            // If we have a VolatileDemux in phase1Volatiles, then we have a phase1 volatile enlistment
            // on the promoted transaction, so we can depend on that to deal with our aborting dependent clones. 
            if ( null != tx.phase1Volatiles.VolatileDemux )
            {
                tx.phase1Volatiles.dependentClones++;
            } 
            else
                // We promoted without creating a phase1 volatile enlistment on the promoted transaction, 
                // so we let the promoted transaction deal with the aboring clone. 
            {
                if ( null == tx.abortingDependentClone ) 
                {
                    tx.abortingDependentClone = tx.PromotedTransaction.DependentClone( false );
                }
                tx.abortingDependentCloneCount++; 
            }
        } 
 

        internal override bool ContinuePhase0Prepares() 
        {
            return true;
        }
 

        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context ) 
        { 
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." );
            // Simply get call get object data for the promoted transaction. 
            ISerializable serializableTx = tx.PromotedTransaction as ISerializable;
            if( serializableTx == null )
            {
                // The LTM can only support this if the Distributed TM Supports it. 
                throw new NotSupportedException();
            } 
 
            // Before forwarding this call to the promoted tx make sure to change
            // the full type info so that only if the promoted tx does not set this 
            // then it should be set correctly.
            serializationInfo.FullTypeName = tx.PromotedTransaction.GetType().FullName;

            // Now forward the call. 
            serializableTx.GetObjectData( serializationInfo, context );
        } 
 

        internal override void ChangeStatePromotedAborted( InternalTransaction tx ) 
        {
            _TransactionStatePromotedAborted.EnterState( tx );
        }
 

        internal override void ChangeStatePromotedCommitted( InternalTransaction tx ) 
        { 
            _TransactionStatePromotedCommitted.EnterState( tx );
        } 


        internal override void InDoubtFromDtc( InternalTransaction tx )
        { 
            _TransactionStatePromotedIndoubt.EnterState( tx );
        } 
 

        internal override void InDoubtFromEnlistment(InternalTransaction tx) 
        {
            _TransactionStatePromotedIndoubt.EnterState( tx );
        }
 

        internal override void ChangeStateAbortedDuringPromotion( InternalTransaction tx ) 
        { 
            _TransactionStateAborted.EnterState( tx );
        } 


        internal override void Timeout( InternalTransaction tx )
        { 
            // LTM gives up the ability to control Tx timeout when it promotes.
            try 
            { 
                if( tx.innerException == null )
                { 
                    tx.innerException = new TimeoutException( SR.GetString( SR.TraceTransactionTimeout ));;
                }
                tx.PromotedTransaction.Rollback();
 
                if ( DiagnosticTrace.Warning )
                { 
                    TransactionTimeoutTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        tx.TransactionTraceId
                        ); 
                }
            }
            catch( TransactionException te )
            { 
                // This could fail for any number of reasons based on the state of the transaction.
                // The Ltm tries anyway because PSPE transactions have no timeout specified and some 
                // distributed transaction managers may not honer the timeout correctly. 

                // The exception needs to be caught because we don't want it to go unhandled on the 
                // timer thread.
                if ( DiagnosticTrace.Verbose )
                {
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        te );
                } 
            } 
        }
 

        internal override void Promote( InternalTransaction tx )
        {
            // do nothing, we are already promoted 
        }
 
 
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        { 
            // Early done notifications may come from volatiles at any time.
            // The state machine will handle all enlistments being complete in later phases.
        }
 

        internal override void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        { 
            // Early done notifications may come from volatiles at any time.
            // The state machine will handle all enlistments being complete in later phases. 
        }
    }

 
    // TransactionStateNonCommittablePromoted
    // 
    // This state indicates that the transaction has been promoted and all further actions on 
    // the transaction should be forwarded to the promoted transaction.
    internal class TransactionStateNonCommittablePromoted : TransactionStatePromotedBase 
    {
        internal override void EnterState( InternalTransaction tx )
        {
            // Set the transaction state 
            CommonEnterState( tx );
 
            // Let the distributed transaction know that we want to know about the outcome. 
            tx.PromotedTransaction.realOletxTransaction.InternalTransaction = tx;
        } 
    }

    // TransactionStatePromoted
    // 
    // This state indicates that the transaction has been promoted and all further actions on
    // the transaction should be forwarded to the promoted transaction. 
    internal class TransactionStatePromoted : TransactionStatePromotedBase 
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            if( tx.outcomeSource.isoLevel == IsolationLevel.Snapshot )
            {
                throw TransactionException.CreateInvalidOperationException( SR.GetString( SR.TraceSourceLtm ), 
                    SR.GetString( SR.CannotPromoteSnapshot ), null );
            } 
 
            // Set the transaction state
            CommonEnterState( tx ); 

            // Create a transaction with the distributed transaction manager
            Oletx.OletxCommittableTransaction distributedTx = null;
            try 
            {
                TimeSpan newTimeout; 
                if( tx.AbsoluteTimeout == long.MaxValue ) 
                {
                    // The transaction has no timeout 
                    newTimeout = TimeSpan.Zero;
                }
                else
                { 
                    newTimeout = TransactionManager.TransactionTable.RecalcTimeout( tx );
                    if( newTimeout <= TimeSpan.Zero ) 
                    { 
                        return;
                    } 
                }

                // Just create a new transaction.
                TransactionOptions options = new TransactionOptions(); 

                options.IsolationLevel = tx.outcomeSource.isoLevel; 
                options.Timeout = newTimeout; 

                // Create a new distributed transaction. 
                distributedTx =
                    TransactionManager.DistributedTransactionManager.CreateTransaction( options );
                distributedTx.savedLtmPromotedTransaction = tx.outcomeSource;
 
                if ( DiagnosticTrace.Information )
                { 
                    TransactionPromotedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        tx.TransactionTraceId,
                        distributedTx.TransactionTraceId 
                        );
                }
            }
            catch( TransactionException te ) 
            {
                // There was an exception trying to create the distributed transaction. 
                // Save the exception and let the transaction get aborted by the finally block. 
                tx.innerException = te;
                if ( DiagnosticTrace.Verbose ) 
                {
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                        te );
                } 
                return;
            } 
            finally 
            {
                if( distributedTx == null ) 
                {
                    // There was an exception trying to create the distributed transaction abort
                    // the local transaction and exit.
                    tx.State.ChangeStateAbortedDuringPromotion( tx ); 
                }
            } 
 
            // Associate the distributed transaction with the local transaction.
            tx.PromotedTransaction = distributedTx; 

            // Add a weak reference to the transaction to the promotedTransactionTable.
            Hashtable promotedTransactionTable = TransactionManager.PromotedTransactionTable;
            lock( promotedTransactionTable ) 
            {
                // Since we are adding this reference to the table create an object that will clean that 
                // entry up. 
                tx.finalizedObject = new FinalizedObject( tx, distributedTx.Identifier );
 
                WeakReference weakRef = new WeakReference( tx.outcomeSource, false );
                promotedTransactionTable[ distributedTx.Identifier ] = weakRef;
            }
            TransactionManager.FireDistributedTransactionStarted( tx.outcomeSource ); 

            // Once we have a promoted transaction promote the enlistments. 
            PromoteEnlistmentsAndOutcome( tx ); 
        }
 

        protected bool PromotePhaseVolatiles(
            InternalTransaction tx,
            ref VolatileEnlistmentSet volatiles, 
            bool phase0 )
        { 
            if( volatiles.volatileEnlistmentCount + volatiles.dependentClones > 0 ) 
            {
                if( phase0 ) 
                {
                    // Create a volatile demultiplexer for the transaction
                    volatiles.VolatileDemux = new Phase0VolatileDemultiplexer( tx );
                } 
                else
                { 
                    // Create a volatile demultiplexer for the transaction 
                    volatiles.VolatileDemux = new Phase1VolatileDemultiplexer( tx );
                } 

                volatiles.VolatileDemux.oletxEnlistment = tx.PromotedTransaction.EnlistVolatile( volatiles.VolatileDemux,
                    phase0 ? EnlistmentOptions.EnlistDuringPrepareRequired : EnlistmentOptions.None );
            } 

            return true; 
        } 

 
        internal virtual bool PromoteDurable( InternalTransaction tx )
        {
            // Promote the durable enlistment if one exists.
            if( tx.durableEnlistment != null ) 
            {
                // Directly enlist the durable enlistment with the resource manager. 
                InternalEnlistment enlistment = tx.durableEnlistment; 
                IPromotedEnlistment oletxEnlistment = tx.PromotedTransaction.EnlistDurable(
                    enlistment.ResourceManagerIdentifier, 
                    (DurableInternalEnlistment)enlistment,
                    enlistment.SinglePhaseNotification != null,
                    EnlistmentOptions.None
                    ); 

                // Promote the enlistment. 
                tx.durableEnlistment.State.ChangeStatePromoted( tx.durableEnlistment, oletxEnlistment ); 
            }
 
            return true;
        }

 
        internal virtual void PromoteEnlistmentsAndOutcome( InternalTransaction tx )
        { 
            // Failures from this point on will simply abort the two types of transaction 
            // seperately.  Note that this may cause duplicate internal aborted events to
            // be sent to some of the enlistments however the enlistment state machines 
            // can handle the duplicate notification.

            bool enlistmentsPromoted = false;
 
            // Tell the RealOletxTransaction that we want a callback for the outcome.
            tx.PromotedTransaction.RealTransaction.InternalTransaction = tx; 
 
            // Promote Phase 0 Volatiles
            try 
            {
                enlistmentsPromoted = PromotePhaseVolatiles( tx, ref tx.phase0Volatiles, true );
            }
            catch( TransactionException te ) 
            {
                // 
 
                // Record the exception information.
                tx.innerException = te; 
                if ( DiagnosticTrace.Verbose )
                {
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                        te ); 
                }
 
                return; 
            }
            finally 
            {
                if( !enlistmentsPromoted )
                {
                    tx.PromotedTransaction.Rollback( ); 

                    // Now abort this transaction. 
                    tx.State.ChangeStateAbortedDuringPromotion( tx ); 
                }
            } 

            enlistmentsPromoted = false;

            try 
            {
                enlistmentsPromoted = PromotePhaseVolatiles( tx, ref tx.phase1Volatiles, false ); 
            } 
            catch( TransactionException te )
            { 
                // Record the exception information.
                tx.innerException = te;
                if ( DiagnosticTrace.Verbose )
                { 
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                        te ); 
                } 

                return; 
            }
            finally
            {
                if( !enlistmentsPromoted ) 
                {
                    tx.PromotedTransaction.Rollback( ); 
 
                    // Now abort this transaction.
                    tx.State.ChangeStateAbortedDuringPromotion( tx ); 
                }
            }

            enlistmentsPromoted = false; 

            // Promote the durable enlistment 
            try 
            {
                enlistmentsPromoted = PromoteDurable( tx ); 
            }
            catch( TransactionException te )
            {
                // Record the exception information. 
                tx.innerException = te;
                if ( DiagnosticTrace.Verbose ) 
                { 
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                        te ); 
                }

                return;
            } 
            finally
            { 
                if( !enlistmentsPromoted ) 
                {
                    tx.PromotedTransaction.Rollback( ); 

                    // Now abort this transaction.
                    tx.State.ChangeStateAbortedDuringPromotion( tx );
                } 
            }
        } 
 

        internal override void DisposeRoot( InternalTransaction tx ) 
        {
            tx.State.Rollback( tx, null );
        }
    } 

 
    // TransactionStatePromotedP0Wave 
    //
    // This state indicates that the transaction has been promoted during phase 0.  This 
    // is a holding state until the current phase 0 wave is complete.  When the current
    // wave is complete the state changes to committing.
    internal class TransactionStatePromotedP0Wave : TransactionStatePromotedBase
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            CommonEnterState( tx ); 
        }
 

        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        {
            // Don't allow this again. 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 
 

        internal override void Phase0VolatilePrepareDone( InternalTransaction tx ) 
        {
            try
            {
                // Now that the previous wave is done continue start committing the transaction. 
                _TransactionStatePromotedCommitting.EnterState( tx );
            } 
            catch( TransactionException e ) 
            {
                // In this state we don't want a transaction exception from BeginCommit to randomly 
                // bubble up to the application or go unhandled.  So catch the exception and if the
                // inner exception for the transaction has not already been set then set it.
                if( tx.innerException == null )
                { 
                    tx.innerException = e;
                } 
                if ( DiagnosticTrace.Verbose ) 
                {
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        e );
                }
            }
 
        }
 
 
        internal override bool ContinuePhase0Prepares()
        { 
            return true;
        }

 
        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        { 
            if( tx.innerException == null ) 
            {
                tx.innerException = e; 
            }

            // This change state event at this point would be caused by one of the enlistments
            // aborting.  Really change to P0Aborting 
            _TransactionStatePromotedP0Aborting.EnterState( tx );
        } 
    } 

 
    // TransactionStatePromotedCommitting
    //
    // The transaction has been promoted but is in the process of committing.
    internal class TransactionStatePromotedCommitting : TransactionStatePromotedBase 
    {
        internal override void EnterState( InternalTransaction tx ) 
        { 
            CommonEnterState( tx );
 
            // Use the asynchronous commit provided by the promoted transaction
            Oletx.OletxCommittableTransaction ctx = (Oletx.OletxCommittableTransaction)tx.PromotedTransaction;
            ctx.BeginCommit( tx );
        } 

 
        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState ) 
        {
            // Don't allow this again. 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }

 
        internal override void ChangeStatePromotedPhase0( InternalTransaction tx )
        { 
            _TransactionStatePromotedPhase0.EnterState( tx ); 
        }
 

        internal override void ChangeStatePromotedPhase1( InternalTransaction tx )
        {
            _TransactionStatePromotedPhase1.EnterState( tx ); 
        }
    } 
 

    // TransactionStatePromotedPhase0 
    //
    // This state indicates that the transaction has been promoted and started the process
    // of committing.  The transaction had volatile phase0 enlistments and is acting as a
    // proxy to the TM for those phase0 enlistments. 
    internal class TransactionStatePromotedPhase0 : TransactionStatePromotedCommitting
    { 
        internal override void EnterState( InternalTransaction tx ) 
        {
            CommonEnterState( tx ); 

            // Get a copy of the current volatile enlistment count before entering this loop so that other
            // threads don't affect the operation of this loop.
            int volatileCount = tx.phase0Volatiles.volatileEnlistmentCount; 
            int dependentCount = tx.phase0Volatiles.dependentClones;
 
            // Store the number of phase0 volatiles for this wave. 
            tx.phase0VolatileWaveCount = volatileCount;
 
            // Check to see if we still need to send out volatile prepare notifications or if
            // they are all done.  They may be done if the transaction was already in phase 0
            // before it got promoted.
            if( tx.phase0Volatiles.preparedVolatileEnlistments < 
                volatileCount + dependentCount )
            { 
                // Broadcast preprepare to the volatile subordinates 
                for( int i = 0; i < volatileCount; i++ )
                { 
                    tx.phase0Volatiles.volatileEnlistments [i].twoPhaseState.ChangeStatePreparing(
                        tx.phase0Volatiles.volatileEnlistments [i] );

                    if( !tx.State.ContinuePhase0Prepares() ) 
                    {
                        break; 
                    } 
                }
            } 
            else
            {
                Phase0VolatilePrepareDone( tx );
            } 
        }
 
 
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        { 
            Debug.Assert( tx.phase0Volatiles.VolatileDemux != null, "Volatile Demux must exist for VolatilePrepareDone when promoted." );

            System.Threading.Monitor.Exit( tx );
            try 
            {
                // Tell the distributed TM that the volatile enlistments are prepared 
                tx.phase0Volatiles.VolatileDemux.oletxEnlistment.Prepared(); 
            }
            finally 
            {
#pragma warning disable 0618
                //@
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
            } 
        } 

 
        internal override bool ContinuePhase0Prepares()
        {
            return true;
        } 

 
        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e ) 
        {
            if( tx.innerException == null ) 
            {
                tx.innerException = e;
            }
 
            // This change state event at this point would be caused by one of the enlistments
            // aborting.  Really change to P0Aborting 
            _TransactionStatePromotedP0Aborting.EnterState( tx ); 
        }
    } 


    // TransactionStatePromotedPhase1
    // 
    // This state indicates that the transaction has been promoted and started the process
    // of committing.  The transaction had volatile phase1 enlistments and is acting as a 
    // proxy to the TM for those phase1 enlistments. 
    internal class TransactionStatePromotedPhase1 : TransactionStatePromotedCommitting
    { 
        internal override void EnterState( InternalTransaction tx )
        {
            CommonEnterState( tx );
 
            if( tx.committableTransaction != null )
            { 
                // If we have a committable transaction then mark it as complete. 
                tx.committableTransaction.complete = true;
            } 

            // If at this point there are phase1 dependent clones abort the transaction
            if( tx.phase1Volatiles.dependentClones != 0 )
            { 
                tx.State.ChangeStateTransactionAborted( tx, null );
                return; 
            } 

            // Get a copy of the current volatile enlistment count before entering this loop so that other 
            // threads don't affect the operation of this loop.
            int volatileCount = tx.phase1Volatiles.volatileEnlistmentCount;

            // Check to see if we still need to send out volatile prepare notifications or if 
            // they are all done.  They may be done if the transaction was already in phase 0
            // before it got promoted. 
            if( tx.phase1Volatiles.preparedVolatileEnlistments < volatileCount ) 
            {
                // Broadcast preprepare to the volatile subordinates 
                for( int i = 0; i < volatileCount; i++ )
                {
                    tx.phase1Volatiles.volatileEnlistments [i].twoPhaseState.ChangeStatePreparing(
                        tx.phase1Volatiles.volatileEnlistments [i] ); 
                    if( !tx.State.ContinuePhase1Prepares() )
                    { 
                        break; 
                    }
                } 
            }
            else
            {
                Phase1VolatilePrepareDone( tx ); 
            }
        } 
 

        internal override void CreateBlockingClone( InternalTransaction tx ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }
 

        internal override void CreateAbortingClone( InternalTransaction tx ) 
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 


        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        { 
            if( tx.innerException == null )
            { 
                tx.innerException = e; 
            }
 
            // This change state event at this point would be caused by one of the enlistments
            // aborting.  Really change to P1Aborting
            _TransactionStatePromotedP1Aborting.EnterState( tx );
        } 

 
        internal override void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        {
            Debug.Assert( tx.phase1Volatiles.VolatileDemux != null, "Volatile Demux must exist for VolatilePrepareDone when promoted." ); 

            System.Threading.Monitor.Exit( tx );
            try
            { 
                // Tell the distributed TM that the volatile enlistments are prepared
                tx.phase1Volatiles.VolatileDemux.oletxEnlistment.Prepared(); 
            } 
            finally
            { 
#pragma warning disable 0618
                //@
                System.Threading.Monitor.Enter(tx);
#pragma warning restore 0618 
            }
        } 
 

        internal override bool ContinuePhase1Prepares() 
        {
            return true;
        }
 

        internal override Enlistment EnlistVolatile( InternalTransaction tx, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction ) 
        { 
            throw new TransactionException( SR.GetString(SR.TooLate) );
        } 


        internal override Enlistment EnlistVolatile( InternalTransaction tx, ISinglePhaseNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction )
        { 
            throw new TransactionException( SR.GetString(SR.TooLate) );
        } 
 

        internal override Enlistment EnlistDurable( InternalTransaction tx, Guid resourceManagerIdentifier, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction ) 
        {
            throw new TransactionException( SR.GetString(SR.TooLate) );
        }
 

        internal override Enlistment EnlistDurable( InternalTransaction tx, Guid resourceManagerIdentifier, ISinglePhaseNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction ) 
        { 
            throw new TransactionException( SR.GetString(SR.TooLate) );
        } 
    }


 
    // TransactionStatePromotedAborting
    // 
    // This state indicates that the transaction has been promoted but aborted.  Once the volatile 
    // enlistments have finished responding the tx can be finished.
    internal abstract class TransactionStatePromotedAborting : TransactionStatePromotedBase 
    {
        internal override void EnterState( InternalTransaction tx )
        {
            CommonEnterState( tx ); 
        }
 
 
        internal override TransactionStatus get_Status( InternalTransaction tx )
        { 
            return TransactionStatus.Aborted;
        }

 
        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        { 
            // Don't allow this again. 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 


        internal override void CreateBlockingClone( InternalTransaction tx )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        } 
 

        internal override void CreateAbortingClone( InternalTransaction tx ) 
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }
 

        internal override void ChangeStatePromotedAborted( InternalTransaction tx ) 
        { 
            _TransactionStatePromotedAborted.EnterState( tx );
        } 


        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        { 
            // Don't do this yet wait until all of the notifications come back.
        } 
 

        internal override void RestartCommitIfNeeded( InternalTransaction tx ) 
        {
            // Commit cannot be restarted
        }
 
    }
 
 
    // TransactionStatePromotedP0Aborting
    // 
    // This state indicates that the transaction has been promoted but aborted by a phase 0 volatile
    // enlistment.  Once the volatile enlistments have finished responding the tx can be finished.
    internal class TransactionStatePromotedP0Aborting : TransactionStatePromotedAborting
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            CommonEnterState( tx ); 

            ChangeStatePromotedAborted( tx ); 

            // If we have a volatilePreparingEnlistment tell it to roll back.
            if( tx.phase0Volatiles.VolatileDemux.preparingEnlistment != null )
            { 
                System.Threading.Monitor.Exit( tx );
                try 
                { 
                    // Tell the distributed TM that the tx aborted.
                    tx.phase0Volatiles.VolatileDemux.oletxEnlistment.ForceRollback(); 
                }
                finally
                {
#pragma warning disable 0618 
                    //@
                    System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618 
                }
            } 
            else
            {
                // Otherwise make sure that the transaction rolls back.
                tx.PromotedTransaction.Rollback(); 
            }
        } 
 

        internal override void Phase0VolatilePrepareDone( InternalTransaction tx ) 
        {
            // If this happens as a ---- it is just fine.
        }
    } 

 
    // TransactionStatePromotedP1Aborting 
    //
    // This state indicates that the transaction has been promoted but aborted by a phase 1 volatile 
    // enlistment.  Once the volatile enlistments have finished responding the tx can be finished.
    internal class TransactionStatePromotedP1Aborting : TransactionStatePromotedAborting
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            CommonEnterState( tx ); 
 
            Debug.Assert( tx.phase1Volatiles.VolatileDemux != null, "Volatile Demux must exist." );
 
            ChangeStatePromotedAborted( tx );

            System.Threading.Monitor.Exit( tx );
            try 
            {
                // Tell the distributed TM that the tx aborted. 
                tx.phase1Volatiles.VolatileDemux.oletxEnlistment.ForceRollback(); 
            }
            finally 
            {
#pragma warning disable 0618
                //@
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
            } 
        } 

 
        internal override void Phase1VolatilePrepareDone( InternalTransaction tx )
        {
            // If this happens as a ---- it is fine.
        } 
    }
 
 
    // TransactionStatePromotedEnded
    // 
    // This is a common base class for committed, aborted, and indoubt states of a promoted
    // transaction.
    internal abstract class TransactionStatePromotedEnded : TransactionStateEnded
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            base.EnterState( tx ); 

            CommonEnterState( tx ); 

            if( !ThreadPool.QueueUserWorkItem( SignalMethod, tx ))
            {
                throw TransactionException.CreateInvalidOperationException( 
                    SR.GetString( SR.TraceSourceLtm ),
                    SR.GetString(SR.UnexpectedFailureOfThreadPool), 
                    null 
                    );
            } 
        }


        internal override void AddOutcomeRegistrant( InternalTransaction tx, TransactionCompletedEventHandler transactionCompletedDelegate ) 
        {
            if( transactionCompletedDelegate != null ) 
            { 
                TransactionEventArgs args = new TransactionEventArgs( );
                args.transaction = tx.outcomeSource.InternalClone(); 
                transactionCompletedDelegate( args.transaction , args );
            }
        }
 

        internal override void EndCommit( InternalTransaction tx ) 
        { 
            // Test the outcome of the transaction and respond accordingly.
            Debug.Assert( tx.PromotedTransaction != null, "Promoted state not valid for transaction." ); 
            PromotedTransactionOutcome( tx );
        }

 
        internal override void CompleteBlockingClone( InternalTransaction tx )
        { 
            // The transaction is finished ignore these. 
        }
 

        internal override void CompleteAbortingClone( InternalTransaction tx )
        {
            // The transaction is finished ignore these. 
        }
 
 
        internal override void CreateBlockingClone( InternalTransaction tx )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException );
        }

 
        internal override void CreateAbortingClone( InternalTransaction tx )
        { 
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
        internal override Guid get_Identifier( InternalTransaction tx )
        {
            return tx.PromotedTransaction.Identifier;
        } 

        internal override void Promote( InternalTransaction tx ) 
        { 
            // do nothing, we are already promoted
        } 

        protected abstract void PromotedTransactionOutcome( InternalTransaction tx );

        private static WaitCallback signalMethod; 
        private static WaitCallback SignalMethod
        { 
            get 
            {
                if( signalMethod == null ) 
                {
                    lock( ClassSyncObject )
                    {
                        if( signalMethod == null ) 
                        {
                            signalMethod = new WaitCallback( SignalCallback ); 
                        } 
                    }
                } 

                return signalMethod;
            }
        } 

 
        private static void SignalCallback( object state ) 
        {
            InternalTransaction tx = (InternalTransaction)state; 
            lock( tx )
            {
                tx.SignalAsyncCompletion();
                TransactionManager.TransactionTable.Remove( tx ); 
            }
        } 
 
    }
 

    // TransactionStatePromotedAborted
    //
    // This state indicates that the transaction has been promoted and the outcome 
    // of the transaction is aborted.
    internal class TransactionStatePromotedAborted : TransactionStatePromotedEnded 
    { 
        internal override void EnterState( InternalTransaction tx )
        { 
            base.EnterState( tx );

            // Tell all the enlistments the outcome.
            if( tx.phase1Volatiles.VolatileDemux != null ) 
            {
                tx.phase1Volatiles.VolatileDemux.BroadcastRollback( ref tx.phase1Volatiles ); 
            } 

            if( tx.phase0Volatiles.VolatileDemux != null ) 
            {
                tx.phase0Volatiles.VolatileDemux.BroadcastRollback( ref tx.phase0Volatiles );
            }
 
            // Fire Completion for anyone listening
            tx.FireCompletion( ); 
            // We don't need to do the AsyncCompletion stuff.  If it was needed, it was done out of SignalCallback. 

            if ( DiagnosticTrace.Warning ) 
            {
                TransactionAbortedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.TransactionTraceId
                    ); 
            }
 
        } 

 
        internal override TransactionStatus get_Status( InternalTransaction tx )
        {
            return TransactionStatus.Aborted;
        } 

 
        internal override void Rollback( InternalTransaction tx, Exception e ) 
        {
            // Already done. 
        }


        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState ) 
        {
            throw TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), tx.innerException ); 
        } 

 
        internal override void CreateBlockingClone( InternalTransaction tx )
        {
            throw TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), tx.innerException );
        } 

 
        internal override void CreateAbortingClone( InternalTransaction tx ) 
        {
            throw TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), tx.innerException ); 
        }


        internal override void RestartCommitIfNeeded( InternalTransaction tx ) 
        {
            // Commit cannot be restarted 
        } 

 
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        {
            // Since the transaction is aborted ignore it.
        } 

 
        internal override void Phase1VolatilePrepareDone( InternalTransaction tx ) 
        {
            // Since the transaction is aborted ignore it. 
        }


        internal override void ChangeStatePromotedPhase0( InternalTransaction tx ) 
        {
            throw new TransactionAbortedException( tx.innerException ); 
        } 

        internal override void ChangeStatePromotedPhase1( InternalTransaction tx ) 
        {
            throw new TransactionAbortedException( tx.innerException );
        }
 
        internal override void ChangeStatePromotedAborted( InternalTransaction tx )
        { 
            // This call may come from multiple events.  Support being told more than once. 
        }
 

        internal override void ChangeStateTransactionAborted( InternalTransaction tx, Exception e )
        {
            // This may come from a promotable single phase enlistments abort response. 
        }
 
 
        protected override void PromotedTransactionOutcome( InternalTransaction tx )
        { 
            if ( ( null == tx.innerException ) && ( null != tx.PromotedTransaction ) )
            {
                tx.innerException = tx.PromotedTransaction.InnerException;
            } 
            throw TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), tx.innerException );
        } 
 

        internal override void CheckForFinishedTransaction( InternalTransaction tx ) 
        {
            throw new TransactionAbortedException( tx.innerException );
        }
 

        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context ) 
        { 
            throw TransactionAbortedException.Create( SR.GetString( SR.TraceSourceLtm), tx.innerException );
        } 


        internal override void InDoubtFromDtc( InternalTransaction tx )
        { 
            // Getting this event would mean that a PSPE enlistment has told us the
            // transaction outcome.  It is possible that a PSPE enlistment would know 
            // the transaction outcome when DTC does not.  So ignore the indoubt 
            // notification from DTC.
        } 


        internal override void InDoubtFromEnlistment( InternalTransaction tx )
        { 
            // In this case DTC has told us the outcome but a PSPE enlistment
            // is telling us that it does not know the outcome of the transaction. 
            // So ignore the notification from the enlistment. 
        }
    } 



    // TransactionStatePromotedCommitted 
    //
    // This state indicates that the transaction has been promoted and the outcome 
    // of the transaction is committed 
    internal class TransactionStatePromotedCommitted : TransactionStatePromotedEnded
    { 
        internal override void EnterState( InternalTransaction tx )
        {
            base.EnterState( tx );
 
            // Tell all the enlistments the outcome.
            if( tx.phase1Volatiles.VolatileDemux != null ) 
            { 
                tx.phase1Volatiles.VolatileDemux.BroadcastCommitted( ref tx.phase1Volatiles );
            } 

            if( tx.phase0Volatiles.VolatileDemux != null )
            {
                tx.phase0Volatiles.VolatileDemux.BroadcastCommitted( ref tx.phase0Volatiles ); 
            }
 
            // Fire Completion for anyone listening 
            tx.FireCompletion( );
            // We don't need to do the AsyncCompletion stuff.  If it was needed, it was done out of SignalCallback. 

            if ( DiagnosticTrace.Verbose )
            {
                TransactionCommittedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.TransactionTraceId
                    ); 
            } 

        } 


        internal override TransactionStatus get_Status( InternalTransaction tx )
        { 
            return TransactionStatus.Committed;
        } 
 

        internal override void ChangeStatePromotedCommitted( InternalTransaction tx ) 
        {
            // This call may come from multiple different events.  Support being told more than once.
        }
 

        protected override void PromotedTransactionOutcome( InternalTransaction tx ) 
        { 
            // This is a happy transaction.
        } 


        internal override void InDoubtFromDtc( InternalTransaction tx )
        { 
            // Getting this event would mean that a PSPE enlistment has told us the
            // transaction outcome.  It is possible that a PSPE enlistment would know 
            // the transaction outcome when DTC does not.  So ignore the indoubt 
            // notification from DTC.
        } 


        internal override void InDoubtFromEnlistment( InternalTransaction tx )
        { 
            // In this case DTC has told us the outcome but a PSPE enlistment
            // is telling us that it does not know the outcome of the transaction. 
            // So ignore the notification from the enlistment. 
        }
    } 



    // TransactionStatePromotedIndoubt 
    //
    // This state indicates that the transaction has been promoted but the outcome 
    // of the transaction is indoubt. 
    internal class TransactionStatePromotedIndoubt : TransactionStatePromotedEnded
    { 
        internal override void EnterState( InternalTransaction tx )
        {
            base.EnterState( tx );
 
            // Tell all the enlistments the outcome.
            if( tx.phase1Volatiles.VolatileDemux != null ) 
            { 
                tx.phase1Volatiles.VolatileDemux.BroadcastInDoubt( ref tx.phase1Volatiles );
            } 

            if( tx.phase0Volatiles.VolatileDemux != null )
            {
                tx.phase0Volatiles.VolatileDemux.BroadcastInDoubt( ref tx.phase0Volatiles ); 
            }
 
            // Fire Completion for anyone listening 
            tx.FireCompletion( );
            // We don't need to do the AsyncCompletion stuff.  If it was needed, it was done out of SignalCallback. 

            if ( DiagnosticTrace.Warning )
            {
                TransactionInDoubtTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.TransactionTraceId
                    ); 
            } 

        } 


        internal override TransactionStatus get_Status( InternalTransaction tx )
        { 
            return TransactionStatus.InDoubt;
        } 
 

        internal override void RestartCommitIfNeeded( InternalTransaction tx ) 
        {
            // Commit cannot be restarted
        }
 

        internal override void ChangeStatePromotedPhase0( InternalTransaction tx ) 
        { 
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException );
        } 

        internal override void ChangeStatePromotedPhase1( InternalTransaction tx )
        {
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException ); 
        }
 
 
        internal override void InDoubtFromDtc( InternalTransaction tx )
        { 
            // This call may actually come from multiple sources that ----.
            // Since we already took action based on the first notification ignore the
            // others.
        } 

 
        internal override void InDoubtFromEnlistment( InternalTransaction tx ) 
        {
            // This call may actually come from multiple sources that ----. 
            // Since we already took action based on the first notification ignore the
            // others.
        }
 

        protected override void PromotedTransactionOutcome( InternalTransaction tx ) 
        { 
            if ( ( null == tx.innerException ) && ( null != tx.PromotedTransaction ) )
            { 
                tx.innerException = tx.PromotedTransaction.InnerException;
            }
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException );
        } 

 
        internal override void CheckForFinishedTransaction( InternalTransaction tx ) 
        {
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException ); 
        }


        internal override void GetObjectData( InternalTransaction tx, SerializationInfo serializationInfo, StreamingContext context ) 
        {
            throw TransactionInDoubtException.Create( SR.GetString( SR.TraceSourceBase), tx.innerException ); 
        } 

 
        internal override void ChangeStatePromotedAborted( InternalTransaction tx )
        {
            // Transaction outcome can come from different directions.  In the case of InDoubt
            // transactions it is possible that one source knowns the actual outcome for 
            // the transaction.  However since the transaction does not know if it will receive
            // a different answer for the outcome it accepts the first answer it gets. 
            // By the time we receive a better answer the clients of this transaction 
            // have already been informed that the transaction is InDoubt.
        } 


        internal override void ChangeStatePromotedCommitted( InternalTransaction tx )
        { 
            // See comment in ChangeStatePromotedAborted
        } 
    } 

 
    // TransactionStateDelegatedBase
    //
    // This state is the base state for delegated transactions
    internal abstract class TransactionStateDelegatedBase : TransactionStatePromoted 
    {
        internal override void EnterState( InternalTransaction tx ) 
        { 
            if( tx.outcomeSource.isoLevel == IsolationLevel.Snapshot )
            { 
                throw TransactionException.CreateInvalidOperationException( SR.GetString( SR.TraceSourceLtm ),
                    SR.GetString( SR.CannotPromoteSnapshot ), null );
            }
 
            // Assign the state
            CommonEnterState( tx ); 
 
            // Create a transaction with the distributed transaction manager
            Oletx.OletxTransaction distributedTx = null; 
            try
            {
                // Ask the delegation interface to promote the transaction.
                if ( DiagnosticTrace.Verbose && tx.durableEnlistment != null ) 
                {
                    EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        tx.durableEnlistment.EnlistmentTraceId, 
                        NotificationCall.Promote
                        ); 
                }


                distributedTx = _TransactionStatePSPEOperation.PSPEPromote( tx ); 
            }
            catch( TransactionPromotionException e ) 
            { 
                tx.innerException = e;
                if ( DiagnosticTrace.Verbose ) 
                {
                    ExceptionConsumedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                        e );
                } 
            }
            finally 
            { 
                if( ((object)distributedTx) == null )
                { 
                    // There was an exception trying to create the distributed transaction abort
                    // the local transaction and exit.
                    tx.State.ChangeStateAbortedDuringPromotion( tx );
                } 
            }
 
            if( ((object)distributedTx) == null ) 
            {
                return; 
            }

            // Associate the distributed transaction with the local transaction.
            tx.PromotedTransaction = distributedTx; 

            // Add a weak reference to the transaction to the promotedTransactionTable. 
            Hashtable promotedTransactionTable = TransactionManager.PromotedTransactionTable; 
            lock( promotedTransactionTable )
            { 
                // Since we are adding this reference to the table create an object that will clean that
                // entry up.
                tx.finalizedObject = new FinalizedObject( tx, tx.PromotedTransaction.Identifier );
 
                WeakReference weakRef = new WeakReference( tx.outcomeSource, false );
                promotedTransactionTable[ tx.PromotedTransaction.Identifier ] = weakRef; 
            } 
            TransactionManager.FireDistributedTransactionStarted( tx.outcomeSource );
 
            if ( DiagnosticTrace.Information )
            {
                TransactionPromotedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    tx.TransactionTraceId, 
                    distributedTx.TransactionTraceId
                    ); 
            } 

            // Once we have a promoted transaction promote the enlistments. 
            PromoteEnlistmentsAndOutcome( tx );
        }
    }
 

    // TransactionStateDelegated 
    // 
    // This state represents a transaction that had a promotable single phase enlistment that then
    // was promoted.  Most of the functionality is inherited from transaction state promoted 
    // except for the way that commit happens.
    internal class TransactionStateDelegated : TransactionStateDelegatedBase
    {
        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState ) 
        {
            // Store the given values 
            tx.asyncCommit = asyncCommit; 
            tx.asyncCallback = asyncCallback;
            tx.asyncState = asyncState; 

            // Initiate the commit process.
            _TransactionStateDelegatedCommitting.EnterState( tx );
        } 

 
        internal override bool PromoteDurable( InternalTransaction tx ) 
        {
            // Let the enlistment know that it has been delegated.  For this type of enlistment that 
            // is really all that needs to be done.
            tx.durableEnlistment.State.ChangeStateDelegated( tx.durableEnlistment );

            return true; 
        }
 
 
        internal override void RestartCommitIfNeeded( InternalTransaction tx )
        { 
            _TransactionStateDelegatedP0Wave.EnterState( tx );
        }

 
        internal override void Rollback( InternalTransaction tx, Exception e )
        { 
            // Pass the Rollback through the promotable single phase enlistment to be 
            // certain it is notified.
 
            if( tx.innerException == null )
            {
                tx.innerException = e;
            } 

            _TransactionStateDelegatedAborting.EnterState( tx ); 
        } 
    }
 

    // TransactionStateDelegatedSubordinate
    //
    // This state represents a transaction that is subordinate to another TM and has been 
    // promoted.
    internal class TransactionStateDelegatedSubordinate : TransactionStateDelegatedBase 
    { 
        internal override bool PromoteDurable( InternalTransaction tx )
        { 
            return true;
        }

 
        internal override void Rollback( InternalTransaction tx, Exception e )
        { 
            // Pass the Rollback through the promotable single phase enlistment to be 
            // certain it is notified.
 
            if( tx.innerException == null )
            {
                tx.innerException = e;
            } 

            tx.PromotedTransaction.Rollback(); 
            _TransactionStatePromotedAborted.EnterState( tx ); 
        }
 

        internal override void ChangeStatePromotedPhase0( InternalTransaction tx )
        {
            _TransactionStatePromotedPhase0.EnterState( tx ); 
        }
 
 
        internal override void ChangeStatePromotedPhase1( InternalTransaction tx )
        { 
            _TransactionStatePromotedPhase1.EnterState( tx );
        }
    }
 

    // TransactionStatePSPEOperation 
    // 
    // Someone is trying to enlist for promotable single phase.  Don't allow them to do anything
    // ----. 
    internal class TransactionStatePSPEOperation : TransactionState
    {
        internal override void EnterState( InternalTransaction tx )
        { 
            // No one should ever use this particular version.  It has to be overridden because
            // the base is abstract. 
            throw new InvalidOperationException(); 
        }
 

        internal override TransactionStatus get_Status( InternalTransaction tx )
        {
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
 
        internal void PSPEInitialize(
            InternalTransaction tx, 
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification )
        {
            Debug.Assert( tx.State == _TransactionStateActive, "PSPEPromote called from state other than TransactionStateActive" );
            CommonEnterState( tx ); 

            try 
            { 
                // Try to initialize the pspn.  If an exception is thrown let it propigate
                // all the way up to the caller. 
                promotableSinglePhaseNotification.Initialize();
            }
            finally
            { 
                _TransactionStateActive.CommonEnterState( tx );
            } 
        } 

        // This method will call the intialize method on IPromotableSinglePhaseNotification. 
        // The tx state will be set to _TransactionStatePhase0 to receive and process further
        // enlistments during Phase0.

        internal void Phase0PSPEInitialize( 
            InternalTransaction tx,
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification ) 
        { 
            Debug.Assert( tx.State == _TransactionStatePhase0, "Phase0PSPEInitialize called from state other than _TransactionStatePhase0" );
            CommonEnterState( tx ); 

            try
            {
                // Try to initialize the PSPE.  If an exception is thrown let it propagate 
                // all the way up to the caller.
                promotableSinglePhaseNotification.Initialize(); 
            } 
            finally
            { 
                 _TransactionStatePhase0.CommonEnterState(tx);
            }
        }
 

        internal Oletx.OletxTransaction PSPEPromote( InternalTransaction tx ) 
        { 
            TransactionState returnState = tx.State;
            Debug.Assert( returnState == _TransactionStateDelegated || 
                returnState == _TransactionStateDelegatedSubordinate ,
                "PSPEPromote called from state other than TransactionStateDelegated" );
            CommonEnterState( tx );
 
            Oletx.OletxTransaction distributedTx = null;
            try 
            { 
                Byte [] propagationToken = tx.promoter.Promote();
 
                if( propagationToken == null )
                {
                    // The PSPE has returned an invalid promoted transaction.
                    throw TransactionException.CreateInvalidOperationException( 
                            SR.GetString( SR.TraceSourceLtm ),
                            SR.GetString( SR.PromotedReturnedInvalidValue ), 
                            null 
                            );
                } 

                try
                {
                    distributedTx = TransactionInterop.GetOletxTransactionFromTransmitterPropigationToken( 
                                        propagationToken
                                        ); 
                } 
                catch( ArgumentException e )
                { 
                    // The PSPE has returned an invalid promoted transaction.
                    throw TransactionException.CreateInvalidOperationException(
                            SR.GetString( SR.TraceSourceLtm ),
                            SR.GetString( SR.PromotedReturnedInvalidValue ), 
                            e
                            ); 
                } 

                if( TransactionManager.FindPromotedTransaction( distributedTx.Identifier ) != null ) 
                {
                    // If there is already a promoted transaction then someone has committed an error.
                    distributedTx.Dispose();
                    throw TransactionException.CreateInvalidOperationException( 
                            SR.GetString( SR.TraceSourceLtm ),
                            SR.GetString( SR.PromotedTransactionExists ), 
                            null 
                            );
                } 
            }
            finally
            {
                returnState.CommonEnterState( tx ); 
            }
 
            return distributedTx; 
        }
    } 


    // TransactionStateDelegatedP0Wave
    // 
    // This state is exactly the same as TransactionStatePromotedP0Wave with
    // the exception that when commit is restarted it is restarted in a different 
    // way. 
    internal class TransactionStateDelegatedP0Wave : TransactionStatePromotedP0Wave
    { 
        internal override void Phase0VolatilePrepareDone( InternalTransaction tx )
        {
            _TransactionStateDelegatedCommitting.EnterState( tx );
        } 
    }
 
 
    // TransactionStateDelegatedCommitting
    // 
    // The transaction has been promoted but is in the process of committing.
    internal class TransactionStateDelegatedCommitting : TransactionStatePromotedCommitting
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            CommonEnterState( tx ); 
 
            // Forward this on to the promotable single phase enlisment
            System.Threading.Monitor.Exit( tx ); 

            if ( DiagnosticTrace.Verbose )
            {
                EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    tx.durableEnlistment.EnlistmentTraceId,
                    NotificationCall.SinglePhaseCommit 
                    ); 
            }
 
            try
            {
                tx.durableEnlistment.PromotableSinglePhaseNotification.SinglePhaseCommit(
                    tx.durableEnlistment.SinglePhaseEnlistment ); 
            }
            finally 
            { 
#pragma warning disable 0618
                //@ 
                System.Threading.Monitor.Enter(tx);
#pragma warning restore 0618
            }
        } 
    }
 
 
    // TransactionStateDelegatedAborting
    // 
    // The transaction has been promoted but is in the process of committing.
    internal class TransactionStateDelegatedAborting : TransactionStatePromotedAborted
    {
        internal override void EnterState( InternalTransaction tx ) 
        {
            CommonEnterState( tx ); 
 
            // The distributed TM is driving the commit processing, so marking of complete
            // is done in TransactionStatePromotedPhase0Aborting.EnterState or 
            // TransactionStatePromotedPhase1Aborting.EnterState.

            // Release the lock
            System.Threading.Monitor.Exit( tx ); 
            try
            { 
                if ( DiagnosticTrace.Verbose ) 
                {
                    EnlistmentNotificationCallTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                        tx.durableEnlistment.EnlistmentTraceId,
                        NotificationCall.Rollback
                        );
                } 

                tx.durableEnlistment.PromotableSinglePhaseNotification.Rollback( 
                    tx.durableEnlistment.SinglePhaseEnlistment ); 
            }
            finally 
            {
#pragma warning disable 0618
                //@
                System.Threading.Monitor.Enter(tx); 
#pragma warning restore 0618
            } 
        } 

 
        internal override void BeginCommit( InternalTransaction tx, bool asyncCommit, AsyncCallback asyncCallback, object asyncState )
        {
            // Initiate the commit process.
            throw TransactionException.CreateTransactionStateException( SR.GetString( SR.TraceSourceLtm ), tx.innerException ); 
        }
 
 
        internal override void ChangeStatePromotedAborted( InternalTransaction tx )
        { 
            _TransactionStatePromotedAborted.EnterState( tx );
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

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