Enlistment.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 / Enlistment.cs / 1305376 / Enlistment.cs

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

namespace System.Transactions 
{ 
    using System;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Threading;
    using System.Transactions;
    using System.Transactions.Diagnostics; 

    internal interface IPromotedEnlistment 
    { 
        void EnlistmentDone();
 
        void Prepared();

        void ForceRollback();
 
        void ForceRollback(Exception e);
 
        void Committed(); 

        void Aborted(); 

        void Aborted(Exception e);

        void InDoubt(); 

        void InDoubt(Exception e); 
 
        byte [] GetRecoveryInformation();
 
        InternalEnlistment InternalEnlistment
        {
            get;
            set; 
        }
    } 
 

    // 
    // InternalEnlistment by itself can support a Phase0 volatile enlistment.
    // There are derived classes to support durable, phase1 volatile & PSPE
    // enlistments.
    // 
    class InternalEnlistment : ISinglePhaseNotificationInternal
    { 
        // Storage for the state of the enlistment. 
        internal EnlistmentState twoPhaseState;
 
        // Interface implemented by the enlistment owner for notifications
        protected IEnlistmentNotification twoPhaseNotifications;

        // Store a reference to the single phase notification interface in case 
        // the enlisment supports it.
        protected ISinglePhaseNotification singlePhaseNotifications; 
 
        // Reference to the containing transaction.
        protected InternalTransaction transaction; 

        // Reference to the lightweight transaction.
        Transaction atomicTransaction;
 
        // The EnlistmentTraceIdentifier for this enlistment.
        private EnlistmentTraceIdentifier traceIdentifier; 
 
        // Unique value amongst all enlistments for a given internal transaction.
        int enlistmentId; 

        // Parent Enlistment Object
        Enlistment enlistment;
        PreparingEnlistment preparingEnlistment; 
        SinglePhaseEnlistment singlePhaseEnlistment;
 
        // If this enlistment is promoted store the object it delegates to. 
        IPromotedEnlistment promotedEnlistment;
 
        // For Recovering Enlistments
        protected InternalEnlistment(
            Enlistment enlistment,
            IEnlistmentNotification twoPhaseNotifications 
            )
        { 
            Debug.Assert(this is RecoveringInternalEnlistment, "this is RecoveringInternalEnlistment"); 
            this.enlistment = enlistment;
            this.twoPhaseNotifications = twoPhaseNotifications; 
            this.enlistmentId = 1;
            this.traceIdentifier = EnlistmentTraceIdentifier.Empty;
        }
 

        // For Promotable Enlistments 
        protected InternalEnlistment( 
            Enlistment enlistment,
            InternalTransaction transaction, 
            Transaction atomicTransaction
            )
        {
            Debug.Assert(this is PromotableInternalEnlistment, "this is PromotableInternalEnlistment"); 
            this.enlistment = enlistment;
            this.transaction = transaction; 
            this.atomicTransaction = atomicTransaction; 
            this.enlistmentId = transaction.enlistmentCount++;
            this.traceIdentifier = EnlistmentTraceIdentifier.Empty; 
        }


        internal InternalEnlistment( 
            Enlistment enlistment,
            InternalTransaction transaction, 
            IEnlistmentNotification twoPhaseNotifications, 
            ISinglePhaseNotification singlePhaseNotifications,
            Transaction atomicTransaction 
            )
        {
            this.enlistment = enlistment;
            this.transaction = transaction; 
            this.twoPhaseNotifications = twoPhaseNotifications;
            this.singlePhaseNotifications = singlePhaseNotifications; 
            this.atomicTransaction = atomicTransaction; 
            this.enlistmentId = transaction.enlistmentCount++;
            this.traceIdentifier = EnlistmentTraceIdentifier.Empty; 
        }


        internal InternalEnlistment( 
            Enlistment enlistment,
            IEnlistmentNotification twoPhaseNotifications, 
            InternalTransaction transaction, 
            Transaction atomicTransaction
            ) 
        {
            this.enlistment = enlistment;
            this.twoPhaseNotifications = twoPhaseNotifications;
            this.transaction = transaction; 
            this.atomicTransaction = atomicTransaction;
        } 
 

        internal EnlistmentState State 
        {
            get
            {
                return this.twoPhaseState; 
            }
 
            set 
            {
                this.twoPhaseState = value; 
            }
        }

 
        internal Enlistment Enlistment
        { 
            get 
            {
                return this.enlistment; 
            }
        }

 
        internal PreparingEnlistment PreparingEnlistment
        { 
            get 
            {
                if( this.preparingEnlistment == null ) 
                {
                    // If there is a ---- here one of the objects would simply be garbage collected.
                    this.preparingEnlistment = new PreparingEnlistment( this );
                } 
                return this.preparingEnlistment;
            } 
        } 

 
        internal SinglePhaseEnlistment SinglePhaseEnlistment
        {
            get
            { 
                if( this.singlePhaseEnlistment == null )
                { 
                    // If there is a ---- here one of the objects would simply be garbage collected. 
                    this.singlePhaseEnlistment = new SinglePhaseEnlistment( this );
                } 
                return this.singlePhaseEnlistment;
            }
        }
 

        internal InternalTransaction Transaction 
        { 
            get
            { 
                return this.transaction;
            }
        }
 

        internal virtual object SyncRoot 
        { 
            get
            { 
                Debug.Assert( this.transaction != null, "this.transaction != null" );
                return this.transaction;
            }
        } 

 
        internal IEnlistmentNotification EnlistmentNotification 
        {
            get 
            {
                return this.twoPhaseNotifications;
            }
        } 

 
        internal ISinglePhaseNotification SinglePhaseNotification 
        {
            get 
            {
                return this.singlePhaseNotifications;
            }
        } 

 
        internal virtual IPromotableSinglePhaseNotification PromotableSinglePhaseNotification 
        {
            get 
            {
                Debug.Assert(false, "PromotableSinglePhaseNotification called for a non promotable enlistment.");
                throw new NotImplementedException();
            } 
        }
 
 
        internal IPromotedEnlistment PromotedEnlistment
        { 
            get
            {
                return this.promotedEnlistment;
            } 

            set 
            { 
                this.promotedEnlistment = value;
            } 
        }


        internal EnlistmentTraceIdentifier EnlistmentTraceId 
        {
            get 
            { 
                if ( this.traceIdentifier == EnlistmentTraceIdentifier.Empty )
                { 
                    lock( this.SyncRoot )
                    {
                        if ( this.traceIdentifier == EnlistmentTraceIdentifier.Empty )
                        { 
                            EnlistmentTraceIdentifier temp;
                            if ( null != this.atomicTransaction ) 
                            { 
                                temp = new EnlistmentTraceIdentifier(
                                    Guid.Empty, 
                                    this.atomicTransaction.TransactionTraceId,
                                    this.enlistmentId
                                    );
                            } 
                            else
                            { 
                                temp = new EnlistmentTraceIdentifier( 
                                    Guid.Empty,
                                    new TransactionTraceIdentifier( 
                                        InternalTransaction.InstanceIdentifier +
                                            Convert.ToString( Interlocked.Increment( ref InternalTransaction.nextHash ), CultureInfo.InvariantCulture ),
                                        0 ),
                                    this.enlistmentId 
                                    );
                            } 
                            Thread.MemoryBarrier(); 
                            this.traceIdentifier = temp;
                        } 
                    }
                }
                return this.traceIdentifier;
            } 
        }
 
 
        internal virtual void FinishEnlistment()
        { 
            // Note another enlistment finished.
            this.Transaction.phase0Volatiles.preparedVolatileEnlistments++;
            CheckComplete();
        } 

 
        internal virtual void CheckComplete() 
        {
            // Make certain we increment the right list. 
            Debug.Assert( this.Transaction.phase0Volatiles.preparedVolatileEnlistments <=
                this.Transaction.phase0Volatiles.volatileEnlistmentCount + this.Transaction.phase0Volatiles.dependentClones );

            // Check to see if all of the volatile enlistments are done. 
            if( this.Transaction.phase0Volatiles.preparedVolatileEnlistments ==
                this.Transaction.phase0VolatileWaveCount + this.Transaction.phase0Volatiles.dependentClones ) 
            { 
                this.Transaction.State.Phase0VolatilePrepareDone( this.Transaction );
            } 
        }


        internal virtual Guid ResourceManagerIdentifier 
        {
            get 
            { 
                Debug.Assert(false, "ResourceManagerIdentifier called for non durable enlistment");
                throw new NotImplementedException(); 
            }
        }

 
        void ISinglePhaseNotificationInternal.SinglePhaseCommit(
            IPromotedEnlistment singlePhaseEnlistment 
            ) 
        {
            bool spcCommitted = false; 
            this.promotedEnlistment = singlePhaseEnlistment;
            try
            {
                this.singlePhaseNotifications.SinglePhaseCommit(this.SinglePhaseEnlistment); 
                spcCommitted = true;
            } 
            finally 
            {
                if (!spcCommitted) 
                {
                    this.SinglePhaseEnlistment.InDoubt();
                }
            } 
        }
 
 
        void IEnlistmentNotificationInternal.Prepare(
            IPromotedEnlistment preparingEnlistment 
            )
        {
            this.promotedEnlistment = preparingEnlistment;
            this.twoPhaseNotifications.Prepare( this.PreparingEnlistment ); 
        }
 
 
        void IEnlistmentNotificationInternal.Commit(
            IPromotedEnlistment enlistment 
            )
        {
            this.promotedEnlistment = enlistment;
            this.twoPhaseNotifications.Commit( this.Enlistment ); 
        }
 
 
        void IEnlistmentNotificationInternal.Rollback(
            IPromotedEnlistment enlistment 
            )
        {
            this.promotedEnlistment = enlistment;
            this.twoPhaseNotifications.Rollback( this.Enlistment ); 
        }
 
 
        void IEnlistmentNotificationInternal.InDoubt(
            IPromotedEnlistment enlistment 
            )
        {
            this.promotedEnlistment = enlistment;
            this.twoPhaseNotifications.InDoubt( this.Enlistment ); 
        }
 
    } 

 
    class DurableInternalEnlistment : InternalEnlistment
    {
        // Resource Manager Identifier for this enlistment if it is durable
        internal Guid resourceManagerIdentifier; 

        internal DurableInternalEnlistment( 
            Enlistment enlistment, 
            Guid resourceManagerIdentifier,
            InternalTransaction transaction, 
            IEnlistmentNotification twoPhaseNotifications,
            ISinglePhaseNotification singlePhaseNotifications,
            Transaction atomicTransaction
            ) : 
            base(enlistment, transaction, twoPhaseNotifications, singlePhaseNotifications, atomicTransaction)
        { 
            this.resourceManagerIdentifier = resourceManagerIdentifier; 
        }
 

        protected DurableInternalEnlistment(
            Enlistment enlistment,
            IEnlistmentNotification twoPhaseNotifications 
            ) : base(enlistment, twoPhaseNotifications)
        { 
        } 

 
        internal override Guid ResourceManagerIdentifier
        {
            get
            { 
                return resourceManagerIdentifier;
            } 
        } 
    }
 

    //
    // Since RecoveringInternalEnlistment does not have a transaction it must take
    // a separate object as its [....] root. 
    //
    class RecoveringInternalEnlistment : DurableInternalEnlistment 
    { 
        object syncRoot;
 
        internal RecoveringInternalEnlistment(
            Enlistment enlistment,
            IEnlistmentNotification twoPhaseNotifications,
            object syncRoot 
            ) : base(enlistment, twoPhaseNotifications)
        { 
            this.syncRoot = syncRoot; 
        }
 
        internal override object SyncRoot
        {
            get
            { 
                return this.syncRoot;
            } 
        } 
    }
 

    class PromotableInternalEnlistment : InternalEnlistment
    {
        // This class acts as the durable single phase enlistment for a 
        // promotable single phase enlistment.
        IPromotableSinglePhaseNotification promotableNotificationInterface; 
 
        internal PromotableInternalEnlistment(
            Enlistment enlistment, 
            InternalTransaction transaction,
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification,
            Transaction atomicTransaction
            ) : 
            base(enlistment, transaction, atomicTransaction)
        { 
            this.promotableNotificationInterface = promotableSinglePhaseNotification; 
        }
 

        internal override IPromotableSinglePhaseNotification PromotableSinglePhaseNotification
        {
            get 
            {
                return this.promotableNotificationInterface; 
            } 
        }
    } 


    // This class supports volatile enlistments
    // 
    internal class Phase1VolatileEnlistment : InternalEnlistment
    { 
        public Phase1VolatileEnlistment( 
            Enlistment enlistment,
            InternalTransaction transaction, 
            IEnlistmentNotification twoPhaseNotifications,
            ISinglePhaseNotification singlePhaseNotifications,
            Transaction atomicTransaction
            ) 
            : base( enlistment, transaction, twoPhaseNotifications, singlePhaseNotifications, atomicTransaction )
        { 
        } 

 
        internal override void FinishEnlistment()
        {
            // Note another enlistment finished.
            this.transaction.phase1Volatiles.preparedVolatileEnlistments++; 
            CheckComplete();
        } 
 

        internal override void CheckComplete() 
        {
            // Make certain we increment the right list.
            Debug.Assert( this.transaction.phase1Volatiles.preparedVolatileEnlistments <=
                this.transaction.phase1Volatiles.volatileEnlistmentCount + 
                this.transaction.phase1Volatiles.dependentClones );
 
            // Check to see if all of the volatile enlistments are done. 
            if( this.transaction.phase1Volatiles.preparedVolatileEnlistments ==
                this.transaction.phase1Volatiles.volatileEnlistmentCount + 
                this.transaction.phase1Volatiles.dependentClones )
            {
                this.transaction.State.Phase1VolatilePrepareDone( this.transaction );
            } 
        }
    } 
 

    public class Enlistment 
    {
        // Interface for communicating with the state machine.
        internal InternalEnlistment internalEnlistment;
 
        internal Enlistment(
            InternalEnlistment internalEnlistment 
            ) 
        {
            this.internalEnlistment = internalEnlistment; 
        }


        internal Enlistment( 
            Guid resourceManagerIdentifier,
            InternalTransaction transaction, 
            IEnlistmentNotification twoPhaseNotifications, 
            ISinglePhaseNotification singlePhaseNotifications,
            Transaction atomicTransaction 
            )
        {
            this.internalEnlistment = new DurableInternalEnlistment(
                this, 
                resourceManagerIdentifier,
                transaction, 
                twoPhaseNotifications, 
                singlePhaseNotifications,
                atomicTransaction 
                );
        }

 
        internal Enlistment(
            InternalTransaction transaction, 
            IEnlistmentNotification twoPhaseNotifications, 
            ISinglePhaseNotification singlePhaseNotifications,
            Transaction atomicTransaction, 
            EnlistmentOptions enlistmentOptions
            )
        {
            if( (enlistmentOptions & EnlistmentOptions.EnlistDuringPrepareRequired) != 0 ) 
            {
                this.internalEnlistment = new InternalEnlistment( 
                    this, 
                    transaction,
                    twoPhaseNotifications, 
                    singlePhaseNotifications,
                    atomicTransaction
                    );
            } 
            else
            { 
                    this.internalEnlistment = new Phase1VolatileEnlistment( 
                    this,
                    transaction, 
                    twoPhaseNotifications,
                    singlePhaseNotifications,
                    atomicTransaction
                    ); 
            }
        } 
 

        // This constructor is for a promotable single phase enlistment. 
        internal Enlistment(
            InternalTransaction transaction,
            IPromotableSinglePhaseNotification promotableSinglePhaseNotification,
            Transaction atomicTransaction 
            )
        { 
            this.internalEnlistment = new PromotableInternalEnlistment( 
                this,
                transaction, 
                promotableSinglePhaseNotification,
                atomicTransaction
                );
        } 

 
        internal Enlistment( 
            IEnlistmentNotification twoPhaseNotifications,
            InternalTransaction transaction, 
            Transaction atomicTransaction
            )
        {
            this.internalEnlistment = new InternalEnlistment( 
                this,
                twoPhaseNotifications, 
                transaction, 
                atomicTransaction
                ); 
        }


        internal Enlistment( 
            IEnlistmentNotification twoPhaseNotifications,
            object syncRoot 
            ) 
        {
            this.internalEnlistment = new RecoveringInternalEnlistment( 
                this,
                twoPhaseNotifications,
                syncRoot
                ); 
        }
 
 
        public void Done()
        { 
            if ( DiagnosticTrace.Verbose )
            {
                MethodEnteredTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    "Enlistment.Done" 
                    );
                EnlistmentCallbackPositiveTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ), 
                    this.internalEnlistment.EnlistmentTraceId, 
                    EnlistmentCallback.Done
                    ); 
            }

            lock( this.internalEnlistment.SyncRoot )
            { 
                this.internalEnlistment.State.EnlistmentDone( this.internalEnlistment );
            } 
 
            if ( DiagnosticTrace.Verbose )
            { 
                MethodExitedTraceRecord.Trace( SR.GetString( SR.TraceSourceLtm ),
                    "Enlistment.Done"
                    );
            } 
        }
 
 
        internal InternalEnlistment InternalEnlistment
        { 
            get
            {
                return this.internalEnlistment;
            } 
        }
    } 
} 


// 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