internal void RevertToCheckpointState() { Debug.Assert(this.clonedInstanceStateStream != null, "cloned instance-state stream null at restore time"); // deserialize only on first access Activity clonedRootActivity = null; this.clonedInstanceStateStream.Position = 0; using (RuntimeEnvironment runtimeEnv = new RuntimeEnvironment(this.workflowExecutor.WorkflowRuntime)) { clonedRootActivity = Activity.Load(this.clonedInstanceStateStream, (Activity)this.workflowDefinition); } Debug.Assert(clonedRootActivity != null); // // Set the trackingListenerBroker before initializing the executor so the tracking // runtime gets a reference to the correct object clonedRootActivity.SetValue(WorkflowExecutor.TrackingListenerBrokerProperty, workflowExecutor.RootActivity.GetValue(WorkflowExecutor.TrackingListenerBrokerProperty)); // create the new workflowExecutor WorkflowExecutor newWorkflowExecutor = new WorkflowExecutor(Guid.Empty); // use a dummy guid while swapping executors newWorkflowExecutor.Initialize(clonedRootActivity, this.workflowExecutor.WorkflowRuntime, this.workflowExecutor); // enqueue the activity notifier Activity activityContext = newWorkflowExecutor.GetContextActivityForId(this.activityContextId); Activity activity = activityContext.GetActivityByName(this.activityQualifiedName); using (new ServiceEnvironment(activity)) { using (newWorkflowExecutor.SetCurrentActivity(activity)) { using (ActivityExecutionContext executionContext = new ActivityExecutionContext(activity)) executionContext.Invoke<EventArgs>(this.callbackHandler, this.callbackData); } } // // Push the batch item ordering id to the new instance newWorkflowExecutor.BatchCollection.WorkItemOrderId = this.workflowExecutor.BatchCollection.WorkItemOrderId; // replace pending batch items foreach (KeyValuePair<object, WorkBatch> batch in this.workflowExecutor.BatchCollection) { batch.Value.SetWorkBatchCollection(newWorkflowExecutor.BatchCollection); Activity oldActivity = batch.Key as Activity; // no need to add the transient state batch if (oldActivity != null) { Activity newactivity = activityContext.GetActivityByName(oldActivity.QualifiedName); newWorkflowExecutor.BatchCollection.Add(newactivity, batch.Value); } } this.workflowExecutor.BatchCollection.Clear(); Debug.Assert(this.completedContextActivities != null); newWorkflowExecutor.CompletedContextActivities = this.completedContextActivities; // replace with the WorkflowRuntime Debug.Assert(this.workflowExecutor.IsInstanceValid); this.workflowExecutor.WorkflowRuntime.ReplaceWorkflowExecutor(this.workflowExecutor.InstanceId, this.workflowExecutor, newWorkflowExecutor); // now resume or suspend the scheduler as needed if (!this.suspendOnRevert) { // get the new one going newWorkflowExecutor.Scheduler.Resume(); } else { // this call will be old scheduler's thread newWorkflowExecutor.SuspendOnIdle(this.suspendOnRevertInfo); } DisposeCheckpointState(); }
Activity IWorkflowCoreRuntime.LoadContextActivity(ActivityExecutionContextInfo contextInfo, Activity outerActivity) { if (!ServiceEnvironment.IsInServiceThread(this.InstanceId)) throw new InvalidOperationException(ExecutionStringManager.MustUseRuntimeThread); Activity contextActivity = null; if (this.completedContextActivities.Contains(contextInfo)) { contextActivity = (Activity)this.completedContextActivities[contextInfo]; this.completedContextActivities.Remove(contextInfo); if (contextActivity.Parent != outerActivity.Parent) contextActivity.parent = outerActivity.Parent; } else { using (RuntimeEnvironment runtimeEnv = new RuntimeEnvironment(this.WorkflowRuntime)) { contextActivity = this.WorkflowRuntime.WorkflowPersistenceService.LoadCompletedContextActivity(contextInfo.ContextGuid, outerActivity); if (contextActivity == null) throw new InvalidOperationException(ExecutionStringManager.LoadContextActivityFailed); } } return contextActivity; }
internal void RevertToCheckpointState() { Debug.Assert(this.clonedInstanceStateStream != null, "cloned instance-state stream null at restore time"); // deserialize only on first access Activity clonedRootActivity = null; this.clonedInstanceStateStream.Position = 0; using (RuntimeEnvironment runtimeEnv = new RuntimeEnvironment(this.workflowExecutor.WorkflowRuntime)) { clonedRootActivity = Activity.Load(this.clonedInstanceStateStream, (Activity)this.workflowDefinition); } Debug.Assert(clonedRootActivity != null); // // Set the trackingListenerBroker before initializing the executor so the tracking // runtime gets a reference to the correct object clonedRootActivity.SetValue(WorkflowExecutor.TrackingListenerBrokerProperty, workflowExecutor.RootActivity.GetValue(WorkflowExecutor.TrackingListenerBrokerProperty)); // create the new workflowExecutor WorkflowExecutor newWorkflowExecutor = new WorkflowExecutor(Guid.Empty); // use a dummy guid while swapping executors newWorkflowExecutor.Initialize(clonedRootActivity, this.workflowExecutor.WorkflowRuntime, this.workflowExecutor); // enqueue the activity notifier Activity activityContext = newWorkflowExecutor.GetContextActivityForId(this.activityContextId); Activity activity = activityContext.GetActivityByName(this.activityQualifiedName); using (new ServiceEnvironment(activity)) { using (newWorkflowExecutor.SetCurrentActivity(activity)) { using (ActivityExecutionContext executionContext = new ActivityExecutionContext(activity)) executionContext.Invoke <EventArgs>(this.callbackHandler, this.callbackData); } } // // Push the batch item ordering id to the new instance newWorkflowExecutor.BatchCollection.WorkItemOrderId = this.workflowExecutor.BatchCollection.WorkItemOrderId; // replace pending batch items foreach (KeyValuePair <object, WorkBatch> batch in this.workflowExecutor.BatchCollection) { batch.Value.SetWorkBatchCollection(newWorkflowExecutor.BatchCollection); Activity oldActivity = batch.Key as Activity; // no need to add the transient state batch if (oldActivity != null) { Activity newactivity = activityContext.GetActivityByName(oldActivity.QualifiedName); newWorkflowExecutor.BatchCollection.Add(newactivity, batch.Value); } } this.workflowExecutor.BatchCollection.Clear(); Debug.Assert(this.completedContextActivities != null); newWorkflowExecutor.CompletedContextActivities = this.completedContextActivities; // replace with the WorkflowRuntime Debug.Assert(this.workflowExecutor.IsInstanceValid); this.workflowExecutor.WorkflowRuntime.ReplaceWorkflowExecutor(this.workflowExecutor.InstanceId, this.workflowExecutor, newWorkflowExecutor); // now resume or suspend the scheduler as needed if (!this.suspendOnRevert) { // get the new one going newWorkflowExecutor.Scheduler.Resume(); } else { // this call will be old scheduler's thread newWorkflowExecutor.SuspendOnIdle(this.suspendOnRevertInfo); } DisposeCheckpointState(); }