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(); } }
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); } }
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); }