ServiceDurableInstance.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 / NetFx35 / System.WorkflowServices / System / ServiceModel / Dispatcher / ServiceDurableInstance.cs / 1305376 / ServiceDurableInstance.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{ 
    using System;
    using System.Runtime; 
    using System.Runtime.Diagnostics; 
    using System.ServiceModel;
    using System.ServiceModel.Description; 
    using System.ServiceModel.Diagnostics;
    using System.ServiceModel.Persistence;
    using System.Transactions;
    using System.Diagnostics; 

    class ServiceDurableInstance : DurableInstance 
    { 
        bool abortInstance;
        DependentTransaction clonedTransaction; 
        ServiceDurableInstanceContextProvider contextManager;
        bool existsInPersistence;
        object instance;
        LockingPersistenceProvider lockingProvider; 
        bool markedForCompletion;
        Type newServiceType; 
        TimeSpan operationTimeout; 
        int outstandingOperations;
        PersistenceProvider provider; 
        DurableRuntimeValidator runtimeValidator;
        bool saveStateInOperationTransaction;
        UnknownExceptionAction unknownExceptionAction;
 
        public ServiceDurableInstance(
            PersistenceProvider persistenceProvider, 
            ServiceDurableInstanceContextProvider contextManager, 
            bool saveStateInOperationTransaction,
            UnknownExceptionAction unknownExceptionAction, 
            DurableRuntimeValidator runtimeValidator,
            TimeSpan operationTimeout)
            : this(persistenceProvider, contextManager, saveStateInOperationTransaction, unknownExceptionAction, runtimeValidator, operationTimeout, null)
        { 
        }
 
        public ServiceDurableInstance( 
            PersistenceProvider persistenceProvider,
            ServiceDurableInstanceContextProvider contextManager, 
            bool saveStateInOperationTransaction,
            UnknownExceptionAction unknownExceptionAction,
            DurableRuntimeValidator runtimeValidator,
            TimeSpan operationTimeout, 
            Type serviceType)
            : base(contextManager, persistenceProvider == null ? Guid.Empty : persistenceProvider.Id) 
        { 
            if (persistenceProvider == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("persistenceProvider");
            }

            if (contextManager == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextManager"); 
            } 

            if (runtimeValidator == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("runtimeValidator");
            }
 
            Fx.Assert(operationTimeout > TimeSpan.Zero,
                "Timeout needs to be greater than zero."); 
 
            this.lockingProvider = persistenceProvider as LockingPersistenceProvider;
            this.provider = persistenceProvider; 
            this.contextManager = contextManager;
            this.saveStateInOperationTransaction = saveStateInOperationTransaction;
            this.unknownExceptionAction = unknownExceptionAction;
            this.runtimeValidator = runtimeValidator; 
            this.operationTimeout = operationTimeout;
            this.newServiceType = serviceType; 
        } 

        enum OperationType 
        {
            None = 0,
            Delete = 1,
            Unlock = 2, 
            Create = 3,
            Update = 4 
        } 

        public object Instance 
        {
            get
            {
                return this.instance; 
            }
        } 
 
        public void AbortInstance()
        { 
            ConcurrencyMode concurrencyMode = this.runtimeValidator.ConcurrencyMode;

            if (concurrencyMode != ConcurrencyMode.Single)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException( 
                    SR2.GetString(SR2.AbortInstanceRequiresSingle))); 
            }
 
            if (this.saveStateInOperationTransaction)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException( 
                    SR2.GetString(SR2.CannotAbortWithSaveStateInTransaction)));
            } 
 
            if (this.markedForCompletion)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException(
                    SR2.GetString(
                    SR2.DurableOperationMethodInvalid, 
                    "AbortInstance",
                    "CompleteInstance"))); 
            } 

            this.abortInstance = true; 
        }

        public IAsyncResult BeginFinishOperation(bool completeInstance, bool performPersistence, Exception operationException, AsyncCallback callback, object state)
        { 
            return new FinishOperationAsyncResult(this, completeInstance, performPersistence, operationException, callback, state);
        } 
 
        public IAsyncResult BeginStartOperation(bool canCreateInstance, AsyncCallback callback, object state)
        { 
            return new StartOperationAsyncResult(this, canCreateInstance, callback, state);
        }

        public void EndFinishOperation(IAsyncResult result) 
        {
            FinishOperationAsyncResult.End(result); 
        } 

        public object EndStartOperation(IAsyncResult result) 
        {
            return StartOperationAsyncResult.End(result);
        }
 
        public void FinishOperation(bool completeInstance, bool performPersistence, Exception operationException)
        { 
            try 
            {
                bool disposeInstance; 
                OperationType operation = FinishOperationCommon(completeInstance, operationException, out disposeInstance);

                Fx.Assert(
                    (performPersistence || (operation != OperationType.Delete && operation != OperationType.Unlock)), 
                    "If we aren't performing persistence then we are a NotAllowed contract and therefore should never have loaded from persistence.");
 
                if (performPersistence) 
                {
                    switch (operation) 
                    {
                        case OperationType.Unlock:
                            // Do the null check out here to avoid creating the scope
                            if (this.lockingProvider != null) 
                            {
                                using (PersistenceScope scope = new PersistenceScope( 
                                    this.saveStateInOperationTransaction, 
                                    this.clonedTransaction))
                                { 
                                    this.lockingProvider.Unlock(this.operationTimeout);
                                }
                            }
                            break; 
                        case OperationType.Delete:
                            using (PersistenceScope scope = new PersistenceScope( 
                                this.saveStateInOperationTransaction, 
                                this.clonedTransaction))
                            { 
                                this.provider.Delete(this.instance, this.operationTimeout);

                                if (DiagnosticUtility.ShouldTraceInformation)
                                { 
                                    string traceText = SR.GetString(SR.TraceCodeServiceDurableInstanceDeleted, this.InstanceId);
                                    TraceUtility.TraceEvent(TraceEventType.Information, 
                                        TraceCode.ServiceDurableInstanceDeleted, traceText, 
                                        new StringTraceRecord("DurableInstanceDetail", traceText),
                                        this, null); 
                                }
                            }
                            break;
                        case OperationType.Create: 
                            using (PersistenceScope scope = new PersistenceScope(
                                this.saveStateInOperationTransaction, 
                                this.clonedTransaction)) 
                            {
                                if (this.lockingProvider != null) 
                                {
                                    this.lockingProvider.Create(this.Instance, this.operationTimeout, disposeInstance);
                                }
                                else 
                                {
                                    this.provider.Create(this.Instance, this.operationTimeout); 
                                } 

                                if (DiagnosticUtility.ShouldTraceInformation) 
                                {
                                    string traceText = SR2.GetString(SR2.ServiceDurableInstanceSavedDetails, this.InstanceId, (this.lockingProvider != null) ? "True" : "False");
                                    TraceUtility.TraceEvent(TraceEventType.Information,
                                        TraceCode.ServiceDurableInstanceSaved, SR.GetString(SR.TraceCodeServiceDurableInstanceSaved), 
                                        new StringTraceRecord("DurableInstanceDetail", traceText),
                                        this, null); 
                                } 
                            }
                            break; 
                        case OperationType.Update:
                            using (PersistenceScope scope = new PersistenceScope(
                                this.saveStateInOperationTransaction,
                                this.clonedTransaction)) 
                            {
                                if (this.lockingProvider != null) 
                                { 
                                    this.lockingProvider.Update(this.Instance, this.operationTimeout, disposeInstance);
                                } 
                                else
                                {
                                    this.provider.Update(this.Instance, this.operationTimeout);
                                } 

                                if (DiagnosticUtility.ShouldTraceInformation) 
                                { 
                                    string traceText = SR2.GetString(SR2.ServiceDurableInstanceSavedDetails, this.InstanceId, (this.lockingProvider != null) ? "True" : "False");
                                    TraceUtility.TraceEvent(TraceEventType.Information, 
                                        TraceCode.ServiceDurableInstanceSaved, SR.GetString(SR.TraceCodeServiceDurableInstanceSaved),
                                        new StringTraceRecord("DurableInstanceDetail", traceText),
                                        this, null);
                                } 
                            }
                            break; 
                        case OperationType.None: 
                            break;
                        default: 
                            Fx.Assert("We should never get an unknown OperationType.");
                            break;
                    }
                } 

                if (disposeInstance) 
                { 
                    DisposeInstance();
                } 
            }
            finally
            {
                CompleteClonedTransaction(); 
            }
        } 
 
        public void MarkForCompletion()
        { 
            if (this.abortInstance)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException( 
                    SR2.GetString(
                    SR2.DurableOperationMethodInvalid, 
                    "CompleteInstance", 
                    "AbortInstance")));
            } 

            this.markedForCompletion = true;
        }
 
        public object StartOperation(bool canCreateInstance)
        { 
            using (StartOperationScope scope = new StartOperationScope(this)) 
            {
                if (this.markedForCompletion) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new InstanceNotFoundException(this.InstanceId));
                } 

                if (this.instance == null) 
                { 
                    if (!TryActivateInstance(canCreateInstance))
                    { 
                        using (PersistenceScope persistenceScope = new PersistenceScope(
                            this.saveStateInOperationTransaction,
                            this.clonedTransaction))
                        { 
                            if (this.lockingProvider != null)
                            { 
                                this.instance = this.lockingProvider.Load(this.operationTimeout, true); 
                            }
                            else 
                            {
                                this.instance = this.provider.Load(this.operationTimeout);
                            }
 
                            if (DiagnosticUtility.ShouldTraceInformation)
                            { 
                                string traceText = SR2.GetString(SR2.ServiceDurableInstanceLoadedDetails, this.InstanceId, (this.lockingProvider != null) ? "True" : "False"); 
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                    TraceCode.ServiceDurableInstanceLoaded, SR.GetString(SR.TraceCodeServiceDurableInstanceLoaded), 
                                    new StringTraceRecord("DurableInstanceDetail", traceText),
                                    this, null);
                            }
                        } 

                        this.existsInPersistence = true; 
                    } 
                }
 
                scope.Complete();
            }

            Fx.Assert( 
                this.instance != null,
                "Instance should definitely be non-null here or we should have thrown an exception."); 
 
            return this.instance;
        } 

        protected override void OnAbort()
        {
            this.provider.Abort(); 
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return this.provider.BeginClose(timeout, callback, state); 
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return this.provider.BeginOpen(timeout, callback, state);
        } 
 
        protected override void OnClose(TimeSpan timeout)
        { 
            this.provider.Close(timeout);
        }

        protected override void OnEndClose(IAsyncResult result) 
        {
            this.provider.EndClose(result); 
        } 

        protected override void OnEndOpen(IAsyncResult result) 
        {
            this.provider.EndOpen(result);
        }
 
        protected override void OnOpen(TimeSpan timeout)
        { 
            this.provider.Open(timeout); 
        }
 
        void CompleteClonedTransaction()
        {
            if (this.clonedTransaction != null)
            { 
                this.clonedTransaction.Complete();
                this.clonedTransaction = null; 
            } 
        }
 
        void DisposeInstance()
        {
            Fx.Assert(
                this.instance != null, 
                "Before making this call we should check instance for null.");
 
            IDisposable disposableInstance = this.instance as IDisposable; 

            if (disposableInstance != null) 
            {
                disposableInstance.Dispose();

                if (DiagnosticUtility.ShouldTraceInformation) 
                {
                    string traceText = SR.GetString(SR.TraceCodeServiceDurableInstanceDisposed, this.InstanceId); 
                    TraceUtility.TraceEvent(TraceEventType.Information, 
                        TraceCode.ServiceDurableInstanceDisposed, SR.GetString(SR.TraceCodeServiceDurableInstanceDisposed),
                        new StringTraceRecord("DurableInstanceDetail", traceText), 
                        this, null);
                }
            }
 
            this.instance = null;
        } 
 
        OperationType FinishOperationCommon(bool completeInstance, Exception operationException, out bool disposeInstance)
        { 
            // No need for Interlocked because we don't support
            // ConcurrencyMode.Multiple
            this.outstandingOperations--;
 
            DurableOperationContext.EndOperation();
 
            Fx.Assert(this.outstandingOperations >= 0, 
                "OutstandingOperations should never go below zero.");
 
            Fx.Assert(this.instance != null,
                "Instance should never been null here - we only get here if StartOperation completes successfully.");

            OperationType operation = OperationType.None; 
            disposeInstance = false;
 
            // This is a "fuzzy" still referenced.  Immediately 
            // after this line another message could come in and
            // reference this InstanceContext, but it doesn't matter 
            // because regardless of scheme used the other message
            // would have had to reacquire the database lock.
            bool stillReferenced = this.contextManager.GetReferenceCount(this.InstanceId) > 1;
 
            this.markedForCompletion |= completeInstance;
 
            if (this.outstandingOperations == 0) 
            {
                if (this.saveStateInOperationTransaction && 
                    this.clonedTransaction != null &&
                    this.clonedTransaction.TransactionInformation.Status == TransactionStatus.Aborted)
                {
                    this.abortInstance = false; 
                    this.markedForCompletion = false;
                    disposeInstance = true; 
                } 
                else if (operationException != null && !(operationException is FaultException))
                { 
                    if (this.unknownExceptionAction == UnknownExceptionAction.TerminateInstance)
                    {
                        if (this.existsInPersistence)
                        { 
                            operation = OperationType.Delete;
                        } 
 
                        this.existsInPersistence = true;
                        disposeInstance = true; 
                    }
                    else
                    {
                        Fx.Assert(this.unknownExceptionAction == UnknownExceptionAction.AbortInstance, "If it is not TerminateInstance then it must be AbortInstance."); 

                        if (this.existsInPersistence) 
                        { 
                            operation = OperationType.Unlock;
                        } 

                        this.existsInPersistence = true;
                        disposeInstance = true;
                        this.markedForCompletion = false; 
                    }
                } 
                else if (this.abortInstance) 
                {
                    this.abortInstance = false; 

                    // AbortInstance can only be called in ConcurrencyMode.Single
                    // and therefore markedForCompletion could only have been
                    // set true by this same operation (either declaratively or 
                    // programmatically).  We set it false again so that the
                    // next operation doesn't cause instance completion. 
                    this.markedForCompletion = false; 

                    if (this.existsInPersistence && !stillReferenced) 
                    {
                        // No need for a transactional version of this as we do not allow
                        // AbortInstance to be called in scenarios with SaveStateInOperationTransaction
                        // set to true 
                        Fx.Assert(!this.saveStateInOperationTransaction,
                            "SaveStateInOperationTransaction must be false if we allowed an abort."); 
 
                        if (this.lockingProvider != null)
                        { 
                            operation = OperationType.Unlock;
                        }
                    }
 
                    this.existsInPersistence = true;
                    disposeInstance = true; 
                } 
                else if (this.markedForCompletion)
                { 
                    if (this.existsInPersistence)
                    {
                        // We don't set exists in persistence to
                        // false here because we want the proper 
                        // persistence exceptions to get back to the
                        // client if we end up here again. 
 
                        operation = OperationType.Delete;
                    } 

                    // Even if we didn't delete the instance because it
                    // never existed we should set this to true.  This will
                    // make sure that any future requests to this instance of 
                    // ServiceDurableInstance will treat the object as deleted.
                    this.existsInPersistence = true; 
                    disposeInstance = true; 
                }
                else 
                {
                    if (this.existsInPersistence)
                    {
                        operation = OperationType.Update; 
                    }
                    else 
                    { 
                        operation = OperationType.Create;
                    } 

                    this.existsInPersistence = true;
                    if (!stillReferenced)
                    { 
                        disposeInstance = true;
                    } 
                } 
            }
 
            return operation;
        }

        bool TryActivateInstance(bool canCreateInstance) 
        {
            if (this.newServiceType != null && !this.existsInPersistence) 
            { 
                if (canCreateInstance)
                { 
                    this.instance = Activator.CreateInstance(this.newServiceType);
                    return true;
                }
                else 
                {
                    DurableErrorHandler.CleanUpInstanceContextAtOperationCompletion(); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FaultException(new DurableDispatcherAddressingFault())); 
                }
            } 

            return false;
        }
 
        class FinishOperationAsyncResult : AsyncResult
        { 
            static AsyncCallback createCallback = Fx.ThunkCallback(new AsyncCallback(CreateComplete)); 
            static AsyncCallback deleteCallback = Fx.ThunkCallback(new AsyncCallback(DeleteComplete));
            static AsyncCallback unlockCallback = Fx.ThunkCallback(new AsyncCallback(UnlockComplete)); 
            static AsyncCallback updateCallback = Fx.ThunkCallback(new AsyncCallback(UpdateComplete));

            ServiceDurableInstance durableInstance;
 
            public FinishOperationAsyncResult(ServiceDurableInstance durableInstance, bool completeInstance, bool performPersistence, Exception operationException, AsyncCallback callback, object state)
                : base(callback, state) 
            { 
                this.durableInstance = durableInstance;
 
                IAsyncResult result = null;
                OperationType operation = OperationType.None;
                bool completeSelf = false;
                bool disposeInstace; 
                operation = this.durableInstance.FinishOperationCommon(completeInstance, operationException, out disposeInstace);
 
                if (performPersistence) 
                {
                    switch (operation) 
                    {
                        case OperationType.Unlock:
                            if (this.durableInstance.lockingProvider != null)
                            { 
                                using (PersistenceScope scope = new PersistenceScope(
                                    this.durableInstance.saveStateInOperationTransaction, 
                                    this.durableInstance.clonedTransaction)) 
                                {
                                    result = this.durableInstance.lockingProvider.BeginUnlock(this.durableInstance.operationTimeout, unlockCallback, this); 
                                }
                            }
                            break;
                        case OperationType.Delete: 
                            using (PersistenceScope scope = new PersistenceScope(
                                this.durableInstance.saveStateInOperationTransaction, 
                                this.durableInstance.clonedTransaction)) 
                            {
                                result = this.durableInstance.provider.BeginDelete(this.durableInstance.Instance, this.durableInstance.operationTimeout, deleteCallback, this); 
                            }
                            break;
                        case OperationType.Create:
                            using (PersistenceScope scope = new PersistenceScope( 
                                this.durableInstance.saveStateInOperationTransaction,
                                this.durableInstance.clonedTransaction)) 
                            { 
                                if (this.durableInstance.lockingProvider != null)
                                { 
                                    result = this.durableInstance.lockingProvider.BeginCreate(this.durableInstance.Instance, this.durableInstance.operationTimeout, disposeInstace, createCallback, this);
                                }
                                else
                                { 
                                    result = this.durableInstance.provider.BeginCreate(this.durableInstance.Instance, this.durableInstance.operationTimeout, createCallback, this);
                                } 
                            } 
                            break;
                        case OperationType.Update: 
                            using (PersistenceScope scope = new PersistenceScope(
                                this.durableInstance.saveStateInOperationTransaction,
                                this.durableInstance.clonedTransaction))
                            { 
                                if (this.durableInstance.lockingProvider != null)
                                { 
                                    result = this.durableInstance.lockingProvider.BeginUpdate(this.durableInstance.Instance, this.durableInstance.operationTimeout, disposeInstace, updateCallback, this); 
                                }
                                else 
                                {
                                    result = this.durableInstance.provider.BeginUpdate(this.durableInstance.Instance, this.durableInstance.operationTimeout, updateCallback, this);
                                }
                            } 
                            break;
                        case OperationType.None: 
                            break; 
                        default:
                            Fx.Assert("Unknown OperationType was passed in."); 
                            break;
                    }
                }
 
                if (disposeInstace)
                { 
                    this.durableInstance.DisposeInstance(); 
                }
 
                if (operation == OperationType.None ||
                    (result != null && result.CompletedSynchronously))
                {
                    completeSelf = true; 
                }
 
                if (!performPersistence) 
                {
                    Fx.Assert(result == null, "Should not have had a result if we didn't perform persistence."); 
                    Complete(true);
                    return;
                }
 
                if (completeSelf)
                { 
                    CallEndOperation(operation, result); 

                    Complete(true); 
                }
            }

            public static void End(IAsyncResult result) 
            {
                AsyncResult.End(result); 
            } 

            static void CreateComplete(IAsyncResult result) 
            {
                HandleOperationCompletion(OperationType.Create, result);
            }
 
            static void DeleteComplete(IAsyncResult result)
            { 
                HandleOperationCompletion(OperationType.Delete, result); 
            }
 
            static void HandleOperationCompletion(OperationType operation, IAsyncResult result)
            {
                if (result.CompletedSynchronously)
                { 
                    return;
                } 
 
                Fx.Assert(result.AsyncState is FinishOperationAsyncResult,
                    "Async state should have been FinishOperationAsyncResult"); 

                FinishOperationAsyncResult finishResult = (FinishOperationAsyncResult) result.AsyncState;

                Exception completionException = null; 
                try
                { 
                    finishResult.CallEndOperation(operation, result); 
                }
                catch (Exception e) 
                {
                    if (Fx.IsFatal(e))
                    {
                        throw; 
                    }
 
                    completionException = e; 
                }
 
                finishResult.Complete(false, completionException);
            }

            static void UnlockComplete(IAsyncResult result) 
            {
                HandleOperationCompletion(OperationType.Unlock, result); 
            } 

            static void UpdateComplete(IAsyncResult result) 
            {
                HandleOperationCompletion(OperationType.Update, result);
            }
 
            void CallEndOperation(OperationType operation, IAsyncResult result)
            { 
                try 
                {
                    switch (operation) 
                    {
                        case OperationType.Delete:
                            this.durableInstance.provider.EndDelete(result);
                            break; 
                        case OperationType.Unlock:
                            this.durableInstance.lockingProvider.EndUnlock(result); 
                            break; 
                        case OperationType.Create:
                            this.durableInstance.provider.EndCreate(result); 
                            break;
                        case OperationType.Update:
                            this.durableInstance.provider.EndUpdate(result);
                            break; 
                        case OperationType.None:
                            break; 
                        default: 
                            Fx.Assert("Should never have an unknown value for this enum.");
                            break; 
                    }
                }
                finally
                { 
                    this.durableInstance.CompleteClonedTransaction();
                } 
            } 
        }
 
        class PersistenceScope : IDisposable
        {
            DependentTransaction clonedTransaction;
            TransactionScope scope; 

            public PersistenceScope(bool saveStateInOperationTransaction, DependentTransaction clonedTransaction) 
            { 
                if (!saveStateInOperationTransaction)
                { 
                    this.scope = new TransactionScope(TransactionScopeOption.Suppress);
                }
                else if (clonedTransaction != null)
                { 
                    this.clonedTransaction = clonedTransaction;
                    this.scope = new TransactionScope(clonedTransaction); 
                } 
            }
 
            public void Dispose()
            {
                if (this.scope != null)
                { 
                    this.scope.Complete();
                    this.scope.Dispose(); 
                    this.scope = null; 
                }
            } 
        }

        class StartOperationAsyncResult : AsyncResult
        { 
            static AsyncCallback loadCallback = Fx.ThunkCallback(new AsyncCallback(LoadComplete));
 
            ServiceDurableInstance durableInstance; 
            OperationContext operationContext;
            StartOperationScope scope; 

            public StartOperationAsyncResult(ServiceDurableInstance durableInstance, bool canCreateInstance, AsyncCallback callback, object state)
                : base(callback, state)
            { 
                this.durableInstance = durableInstance;
 
                bool completeSelf = false; 
                IAsyncResult result = null;
                this.operationContext = OperationContext.Current; 

                scope = new StartOperationScope(this.durableInstance);
                bool success = false;
                try 
                {
                    if (this.durableInstance.instance == null) 
                    { 
                        if (this.durableInstance.TryActivateInstance(canCreateInstance))
                        { 
                            completeSelf = true;
                        }
                        else
                        { 
                            using (PersistenceScope persistenceScope = new PersistenceScope(
                                this.durableInstance.saveStateInOperationTransaction, 
                                this.durableInstance.clonedTransaction)) 
                            {
                                if (this.durableInstance.lockingProvider != null) 
                                {
                                    result = this.durableInstance.lockingProvider.BeginLoad(this.durableInstance.operationTimeout, true, loadCallback, this);
                                }
                                else 
                                {
                                    result = this.durableInstance.provider.BeginLoad(this.durableInstance.operationTimeout, loadCallback, this); 
                                } 
                            }
 
                            this.durableInstance.existsInPersistence = true;

                            if (result.CompletedSynchronously)
                            { 
                                completeSelf = true;
                            } 
                        } 
                    }
                    else 
                    {
                        completeSelf = true;
                    }
 

                    success = true; 
                } 
                finally
                { 
                    if (!success)
                    {
                        scope.Dispose();
                    } 
                }
 
                if (completeSelf) 
                {
                    try 
                    {
                        if (result != null)
                        {
                            this.durableInstance.instance = this.durableInstance.provider.EndLoad(result); 
                        }
 
                        Fx.Assert(this.durableInstance.instance != null, 
                            "The instance should always be set here.");
 
                        Complete(true);
                        scope.Complete();
                    }
                    finally 
                    {
                        scope.Dispose(); 
                    } 
                }
            } 

            public static object End(IAsyncResult result)
            {
                StartOperationAsyncResult startResult = AsyncResult.End(result); 

                return startResult.durableInstance.instance; 
            } 

            static void LoadComplete(IAsyncResult result) 
            {
                if (result.CompletedSynchronously)
                {
                    return; 
                }
 
                Fx.Assert(result.AsyncState is StartOperationAsyncResult, 
                    "Should have been passed a StartOperationAsyncResult as the state");
 
                StartOperationAsyncResult startResult = (StartOperationAsyncResult) result.AsyncState;
                Exception completionException = null;
                OperationContext oldOperationContext = OperationContext.Current;
                OperationContext.Current = startResult.operationContext; 

                try 
                { 
                    try
                    { 
                        startResult.durableInstance.instance = startResult.durableInstance.provider.EndLoad(result);

                        Fx.Assert(startResult.durableInstance.instance != null,
                            "The instance should always be set here."); 

                        startResult.scope.Complete(); 
                    } 
                    catch (Exception e)
                    { 
                        if (Fx.IsFatal(e))
                        {
                            throw;
                        } 

                        completionException = e; 
                    } 
                    finally
                    { 
                        startResult.scope.Dispose();
                    }

                    startResult.Complete(false, completionException); 
                }
                finally 
                { 
                    OperationContext.Current = oldOperationContext;
                } 
            }
        }

        class StartOperationScope : IDisposable 
        {
            ServiceDurableInstance durableInstance; 
            bool success; 

            public StartOperationScope(ServiceDurableInstance durableInstance) 
            {
                this.durableInstance = durableInstance;

                this.durableInstance.runtimeValidator.ValidateRuntime(); 

                DurableOperationContext.BeginOperation(); 
 
                // No need for Interlocked because we don't support
                // ConcurrencyMode.Multiple 
                this.durableInstance.outstandingOperations++;

                if (this.durableInstance.saveStateInOperationTransaction && Transaction.Current != null)
                { 
                    this.durableInstance.clonedTransaction = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
                } 
            } 

            public void Complete() 
            {
                this.success = true;
            }
 
            public void Dispose()
            { 
                if (!this.success) 
                {
                    Fx.Assert(OperationContext.Current != null, "Operation context should not be null at this point."); 

                    DurableOperationContext.EndOperation();

                    this.durableInstance.outstandingOperations--; 
                    this.durableInstance.CompleteClonedTransaction();
                } 
            } 
        }
    } 
}

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