// This happens out-of-band of ReceiveAsyncResult. // When transaction was aborted, we best-effort abandon the context. void OnTransactionComplete(object sender, TransactionEventArgs e) { if (e.Transaction.TransactionInformation.Status != TransactionStatus.Committed) { BufferedReceiveManager.AbandonReceiveContext(this.context.receiveContext); } }
bool ProcessReply() { bool completed = false; this.workflowInstance.ReleaseContext(this); this.RemovePendingOperation(); if (this.CurrentState == State.BookmarkResumption) //We are still in Bookmark Resume { this.CurrentState = State.ResultReceived; //HandleEndResumeBookmark will take care of Completing AsyncResult. } else if (this.CurrentState == State.WaitForResult) //We already finished the bookmarkOperation; Now have to signal the AsynResult. { this.CurrentState = State.Completed; completed = true; } // we are not really completed until the ReceiveContext finishes its work if (completed) { if (this.pendingException == null) { completed = ProcessReceiveContext(); } else { // if there's a pendingException, we let the RC abandon async so there's no need // to affect the completed status BufferedReceiveManager.AbandonReceiveContext(this.receiveContext); } } return(completed); }
private bool ProcessReply() { bool flag = false; this.workflowInstance.ReleaseContext(this); this.RemovePendingOperation(); if (this.CurrentState == State.BookmarkResumption) { this.CurrentState = State.ResultReceived; } else if (this.CurrentState == State.WaitForResult) { this.CurrentState = State.Completed; flag = true; } if (flag) { if (this.pendingException == null) { return(this.ProcessReceiveContext()); } BufferedReceiveManager.AbandonReceiveContext(this.receiveContext); } return(flag); }
private static bool HandleEndResumeBookmark(IAsyncResult result) { WorkflowOperationContext asyncState = (WorkflowOperationContext)result.AsyncState; bool flag = false; bool flag2 = true; try { if (asyncState.workflowInstance.EndResumeProtocolBookmark(result) != BookmarkResumptionResult.Success) { asyncState.OperationContext.Host.RaiseUnknownMessageReceived(asyncState.OperationContext.IncomingMessage); if ((asyncState.workflowInstance.BufferedReceiveManager != null) && asyncState.workflowInstance.BufferedReceiveManager.BufferReceive(asyncState.OperationContext, asyncState.receiveContext, asyncState.bookmark.Name, BufferedReceiveState.WaitingOnBookmark, false)) { if (System.ServiceModel.Activities.TD.BufferOutOfOrderMessageNoBookmarkIsEnabled()) { System.ServiceModel.Activities.TD.BufferOutOfOrderMessageNoBookmark(asyncState.workflowInstance.Id.ToString(), asyncState.bookmark.Name); } flag2 = false; } throw System.ServiceModel.Activities.FxTrace.Exception.AsError(new FaultException(OperationExecutionFault.CreateOperationNotAvailableFault(asyncState.workflowInstance.Id, asyncState.bookmark.Name))); } lock (asyncState.thisLock) { if (asyncState.CurrentState == State.ResultReceived) { asyncState.CurrentState = State.Completed; if (asyncState.pendingException != null) { throw System.ServiceModel.Activities.FxTrace.Exception.AsError(asyncState.pendingException); } flag = true; } else { asyncState.CurrentState = State.WaitForResult; flag = false; } if (flag) { flag = asyncState.ProcessReceiveContext(); } flag2 = false; } } finally { if (flag2) { BufferedReceiveManager.AbandonReceiveContext(asyncState.receiveContext); } asyncState.RemovePendingOperation(); } return(flag); }
public ControlOperationInvoker(OperationDescription description, ServiceEndpoint endpoint, CorrelationKeyCalculator correlationKeyCalculator, IOperationInvoker innerInvoker, ServiceHostBase host) { Fx.Assert(host is WorkflowServiceHost, "ControlOperationInvoker must be used with a WorkflowServiceHost"); this.host = (WorkflowServiceHost)host; this.instanceManager = this.host.DurableInstanceManager; this.operationName = description.Name; this.isOneWay = description.IsOneWay; this.endpoint = endpoint; this.innerInvoker = innerInvoker; this.keyCalculator = correlationKeyCalculator; this.persistTimeout = this.host.PersistTimeout; if (description.DeclaringContract == WorkflowControlEndpoint.WorkflowControlServiceContract || description.DeclaringContract == WorkflowControlEndpoint.WorkflowControlServiceBaseContract) { //Mode1: This invoker belongs to IWorkflowInstanceManagement operation. this.isControlOperation = true; switch (this.operationName) { case XD2.WorkflowInstanceManagementService.Cancel: case XD2.WorkflowInstanceManagementService.TransactedCancel: case XD2.WorkflowInstanceManagementService.Run: case XD2.WorkflowInstanceManagementService.TransactedRun: case XD2.WorkflowInstanceManagementService.Unsuspend: case XD2.WorkflowInstanceManagementService.TransactedUnsuspend: this.inputParameterCount = 1; break; case XD2.WorkflowInstanceManagementService.Abandon: case XD2.WorkflowInstanceManagementService.Suspend: case XD2.WorkflowInstanceManagementService.TransactedSuspend: case XD2.WorkflowInstanceManagementService.Terminate: case XD2.WorkflowInstanceManagementService.TransactedTerminate: case XD2.WorkflowInstanceManagementService.Update: case XD2.WorkflowInstanceManagementService.TransactedUpdate: this.inputParameterCount = 2; break; default: throw Fx.AssertAndThrow("Unreachable code"); } } else if (endpoint is WorkflowHostingEndpoint) { this.CanCreateInstance = true; } else { this.bufferedReceiveManager = this.host.Extensions.Find<BufferedReceiveManager>(); } }
WorkflowServiceInstance(Activity workflowDefinition, WorkflowIdentity definitionIdentity, Guid instanceId, WorkflowServiceHost serviceHost, PersistenceContext persistenceContext) : base(workflowDefinition, definitionIdentity) { this.serviceHost = serviceHost; this.instanceId = instanceId; this.persistTimeout = serviceHost.PersistTimeout; this.trackTimeout = serviceHost.TrackTimeout; this.bufferedReceiveManager = serviceHost.Extensions.Find<BufferedReceiveManager>(); if (persistenceContext != null) { this.persistenceContext = persistenceContext; this.persistenceContext.Closed += this.OnPersistenceContextClosed; } this.thisLock = new object(); this.pendingRequests = new List<WorkflowOperationContext>(); this.executorLock = new WorkflowExecutionLock(this); this.activeOperationsLock = new object(); this.acquireReferenceSemaphore = new ThreadNeutralSemaphore(1); this.acquireLockTimeout = TimeSpan.MaxValue; // Two initial references are held: // The first referenceCount is owned by UnloadInstancePolicy (ReleaseInstance) this.referenceCount = 1; // The second referenceCount is owned by the loader / creator of the instance. this.TryAddReference(); }
static bool HandleEndResumeBookmark(IAsyncResult result) { WorkflowOperationContext thisPtr = (WorkflowOperationContext)result.AsyncState; bool completed = false; bool shouldAbandon = true; try { BookmarkResumptionResult resumptionResult = thisPtr.workflowInstance.EndResumeProtocolBookmark(result); if (resumptionResult != BookmarkResumptionResult.Success) { // Raise UnkownMessageReceivedEvent when we fail to resume bookmark thisPtr.OperationContext.Host.RaiseUnknownMessageReceived(thisPtr.OperationContext.IncomingMessage); // Only delay-retry this operation once (and only if retries are supported). Future calls will ensure the bookmark is set. if (thisPtr.workflowInstance.BufferedReceiveManager != null) { bool bufferSuccess = thisPtr.workflowInstance.BufferedReceiveManager.BufferReceive( thisPtr.OperationContext, thisPtr.receiveContext, thisPtr.bookmark.Name, BufferedReceiveState.WaitingOnBookmark, false); if (bufferSuccess) { if (TD.BufferOutOfOrderMessageNoBookmarkIsEnabled()) { TD.BufferOutOfOrderMessageNoBookmark(thisPtr.eventTraceActivity, thisPtr.workflowInstance.Id.ToString(), thisPtr.bookmark.Name); } shouldAbandon = false; } } // The throw exception is intentional whether or not BufferedReceiveManager is set. // This is to allow exception to bubble up the stack to WCF to cleanup various state (like Transaction). // This is queue scenario and as far as the client is concerned, the client will not see any exception. throw FxTrace.Exception.AsError(new FaultException(OperationExecutionFault.CreateOperationNotAvailableFault(thisPtr.workflowInstance.Id, thisPtr.bookmark.Name))); } lock (thisPtr.thisLock) { if (thisPtr.CurrentState == State.ResultReceived) { thisPtr.CurrentState = State.Completed; if (thisPtr.pendingException != null) { throw FxTrace.Exception.AsError(thisPtr.pendingException); } completed = true; } else { thisPtr.CurrentState = State.WaitForResult; completed = false; } // we are not really completed until the ReceiveContext finishes its work if (completed) { completed = thisPtr.ProcessReceiveContext(); } shouldAbandon = false; } } finally { if (shouldAbandon) { BufferedReceiveManager.AbandonReceiveContext(thisPtr.receiveContext); } thisPtr.RemovePendingOperation(); } return(completed); }