PersistenceContextEnlistment.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 / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / Dispatcher / PersistenceContextEnlistment.cs / 1305376 / PersistenceContextEnlistment.cs

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

namespace System.ServiceModel.Activities.Dispatcher 
{
    using System.Collections.Generic; 
    using System.Runtime; 
    using System.Threading;
    using System.Transactions; 

    sealed class PersistenceContextEnlistment : IEnlistmentNotification
    {
        PreparingEnlistment preparingEnlistment; 
        Enlistment enlistment;
 
        // This will be true if we have received either a Prepare or Rollback 
        // notification from the transaction manager. If this is true, it is too
        // late to try to add more entries to the undo collection. 
        bool tooLateForMoreUndo;
        Transaction transaction;
        object ThisLock = new object();
 
        List enlistedContexts;
 
        static Action prepareCallback; 
        static Action commitCallback;
        static Action rollbackCallback; 
        static Action indoubtCallback;

        internal PersistenceContextEnlistment(PersistenceContext context, Transaction transaction)
        { 
            this.transaction = transaction;
 
            this.enlistedContexts = new List(); 
            this.enlistedContexts.Add(context);
        } 

        internal void AddToEnlistment(PersistenceContext context)
        {
            lock (this.ThisLock) 
            {
                if (tooLateForMoreUndo) 
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.PersistenceTooLateToEnlist));
                } 

                this.enlistedContexts.Add(context);
            }
        } 

        internal static Action PrepareCallback 
        { 
            get
            { 
                if (prepareCallback == null)
                {
                    prepareCallback = new Action(DoPrepare);
                } 
                return prepareCallback;
            } 
        } 

        internal static Action CommitCallback 
        {
            get
            {
                if (commitCallback == null) 
                {
                    commitCallback = new Action(DoCommit); 
                } 
                return commitCallback;
            } 
        }

        internal static Action RollbackCallback
        { 
            get
            { 
                if (rollbackCallback == null) 
                {
                    rollbackCallback = new Action(DoRollback); 
                }
                return rollbackCallback;
            }
        } 

        internal static Action IndoubtCallback 
        { 
            get
            { 
                if (indoubtCallback == null)
                {
                    indoubtCallback = new Action(DoIndoubt);
                } 
                return indoubtCallback;
            } 
        } 

        void IEnlistmentNotification.Prepare(PreparingEnlistment preparingEnlistment) 
        {
            // We don't want to try to grab one of our locks while executing on the
            // System.Transactions notification thread because that will block all
            // the other notifications that need to be made. So schedule the 
            // processing of this on another thread. If we decide that the locks
            // aren't necessary, we can get rid of this. 
            this.preparingEnlistment = preparingEnlistment; 
            ActionItem.Schedule(PrepareCallback, this);
        } 

        void IEnlistmentNotification.Commit(Enlistment enlistment)
        {
            // We don't want to try to grab one of our locks while executing on the 
            // System.Transactions notification thread because that will block all
            // the other notifications that need to be made. So schedule the 
            // processing of this on another thread. If we decide that the locks 
            // aren't necessary, we can get rid of this.
            this.enlistment = enlistment; 
            ActionItem.Schedule(CommitCallback, this);
        }

        void IEnlistmentNotification.Rollback(Enlistment enlistment) 
        {
            // We don't want to try to grab one of our locks while executing on the 
            // System.Transactions notification thread because that will block all 
            // the other notifications that need to be made. So schedule the
            // processing of this on another thread. If we decide that the locks 
            // aren't necessary, we can get rid of this.
            this.enlistment = enlistment;
            ActionItem.Schedule(RollbackCallback, this);
        } 

        void IEnlistmentNotification.InDoubt(Enlistment enlistment) 
        { 
            // We don't want to try to grab one of our locks while executing on the
            // System.Transactions notification thread because that will block all 
            // the other notifications that need to be made. So schedule the
            // processing of this on another thread. If we decide that the locks
            // aren't necessary, we can get rid of this.
            this.enlistment = enlistment; 
            ActionItem.Schedule(IndoubtCallback, this);
        } 
 
        internal static void DoPrepare(object state)
        { 
            PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment;
            Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoPrepare called with an object that is not a PersistenceContext.");

            lock (pcEnlist.ThisLock) 
            {
                pcEnlist.tooLateForMoreUndo = true; 
            } 

            // This needs to be done outside of the lock because it could induce System.Transactions 
            // to do a whole bunch of other work inline, including issuing the Commit call and doing
            // Completion notifications for hte transaction. We don't want to be holding the lock
            // during all of that.
            pcEnlist.preparingEnlistment.Prepared(); 
        }
 
        internal static void DoCommit(object state) 
        {
            PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment; 
            Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoCommit called with an object that is not a PersistenceContext.");

            lock (pcEnlist.ThisLock)
            { 
                // Wake up the next waiter for the pc, if any.
                foreach (PersistenceContext context in pcEnlist.enlistedContexts) 
                { 
                    context.ScheduleNextTransactionWaiter();
                } 
            }
            lock (PersistenceContext.Enlistments)
            {
                PersistenceContext.Enlistments.Remove(pcEnlist.transaction.GetHashCode()); 
            }
            // This needs to be outside the lock because SysTx might do other stuff on the thread. 
            pcEnlist.enlistment.Done(); 
        }
 
        internal static void DoRollback(object state)
        {
            PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment;
            Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoRollback called with an object that is not a PersistenceContext."); 

            lock (pcEnlist.ThisLock) 
            { 
                pcEnlist.tooLateForMoreUndo = true;
 
                foreach (PersistenceContext context in pcEnlist.enlistedContexts)
                {
                    context.Abort();
                    context.ScheduleNextTransactionWaiter(); 
                }
            } 
            lock (PersistenceContext.Enlistments) 
            {
                PersistenceContext.Enlistments.Remove(pcEnlist.transaction.GetHashCode()); 
            }
            // This needs to be outside the lock because SysTx might do other stuff on the thread.
            pcEnlist.enlistment.Done();
        } 

        internal static void DoIndoubt(object state) 
        { 
            PersistenceContextEnlistment pcEnlist = state as PersistenceContextEnlistment;
            Fx.Assert(null != pcEnlist, "PersistenceContextEnlistment.DoIndoubt called with an object that is not a PersistenceContext."); 

            lock (pcEnlist.ThisLock)
            {
                pcEnlist.tooLateForMoreUndo = true; 

                foreach (PersistenceContext context in pcEnlist.enlistedContexts) 
                { 
                    context.Abort();
                    context.ScheduleNextTransactionWaiter(); 
                }
            }
            lock (PersistenceContext.Enlistments)
            { 
                PersistenceContext.Enlistments.Remove(pcEnlist.transaction.GetHashCode());
            } 
            // This needs to be outside the lock because SysTx might do other stuff on the thread. 
            pcEnlist.enlistment.Done();
        } 
    }
}

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