예제 #1
0
            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();
                }
            }
예제 #2
0
            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);
                }
            }
예제 #3
0
        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);
        }