/// <summary> /// Start any child activities that need to be run /// </summary> /// <param name="cag"></param> /// <param name="context"></param> internal void TriggerChildren(ConditionedActivityGroup cag, ActivityExecutionContext context) { Debug.Assert(cag != null); Debug.Assert(context != null); #if LOG Log("TriggerChildren on " + cag.QualifiedName); cag.CAGState.DumpState("Before TriggerChildren"); #endif Dictionary <string, CAGChildStats> childrenStats = cag.CAGState.ChildrenStats; // until condition is false, so let's look at all children foreach (Activity act in cag.EnabledActivities) { // do we think this child needs to run? if (childrenStats[act.QualifiedName].State != CAGChildState.Pending) { continue; } // find the run-time activity Activity activity = GetRuntimeInitializedActivity(context, act); if (activity.ExecutionStatus == ActivityExecutionStatus.Initialized) { ExecuteChild(cag, activity, context); } } #if LOG cag.CAGState.DumpState("After TriggerChildren"); #endif }
protected override void OnActivityChangeRemove(ActivityExecutionContext executionContext, Activity removedActivity) { if (executionContext == null) { throw new ArgumentNullException("executionContext"); } if (removedActivity == null) { throw new ArgumentNullException("removedActivity"); } if (!removedActivity.Enabled) { return; } ConditionedActivityGroup cag = executionContext.Activity as ConditionedActivityGroup; Debug.Assert(cag != null); // find out the status of the cag ConditionedActivityGroupStateInfo state = cag.CAGState; if ((cag.ExecutionStatus == ActivityExecutionStatus.Executing) && (state != null)) { state.ChildrenStats.Remove(removedActivity.QualifiedName); } }
protected override void OnWorkflowChangesCompleted(ActivityExecutionContext executionContext) { if (executionContext == null) { throw new ArgumentNullException("executionContext"); } // find out the status of the cag ConditionedActivityGroup currentActivity = executionContext.Activity as ConditionedActivityGroup; // if CAG is executing... fire the conditions on the net result if (currentActivity.ExecutionStatus == ActivityExecutionStatus.Executing) { // but hold on, a derived cag could be applying model changes before it // "really" starts executing the activities. In that case it will evaluate // the conditions later, at the appropriate time. ConditionedActivityGroupStateInfo state = currentActivity.CAGState; if ((state != null) && (!state.Testing)) { // fire away... fire away... said the CAG if (this.EvaluateConditions(currentActivity, executionContext)) { // CAG until indicates we are done, so no children execute this.Cleanup(currentActivity, executionContext); } else { // start any pending activity required this.TriggerChildren(currentActivity, executionContext); } } } }
protected override void OnActivityChangeAdd(ActivityExecutionContext executionContext, Activity addedActivity) { if (executionContext == null) { throw new ArgumentNullException("executionContext"); } if (addedActivity == null) { throw new ArgumentNullException("addedActivity"); } if (!addedActivity.Enabled) { return; } ConditionedActivityGroup currentActivity = executionContext.Activity as ConditionedActivityGroup; Debug.Assert(currentActivity != null); ConditionedActivityGroupStateInfo state = currentActivity.CAGState; if (currentActivity.ExecutionStatus == ActivityExecutionStatus.Executing && state != null) { Debug.Assert(currentActivity == addedActivity.Parent, "Attempting to add wrong activity to CAG"); state.ChildrenStats[addedActivity.QualifiedName] = new CAGChildStats(); } }
internal bool Cleanup(ConditionedActivityGroup cag, ActivityExecutionContext context) { // the completion condition has fired, or we are canceling // either way, we want to cleanup ConditionedActivityGroupStateInfo state = cag.CAGState; state.Completed = true; // cancel any children currently running bool childrenActive = false; Dictionary <string, CAGChildStats> childrenStats = state.ChildrenStats; foreach (Activity act in cag.EnabledActivities) { // reset any Pending Execution for all child activity if (childrenStats[act.QualifiedName].State == CAGChildState.Pending) { childrenStats[act.QualifiedName].State = CAGChildState.Idle; } // find the run-time activity ActivityExecutionContext childContext = GetChildExecutionContext(context, act, false); if (childContext != null) { // child must be running somewhere Activity activity = GetRuntimeInitializedActivity(context, act); switch (activity.ExecutionStatus) { case ActivityExecutionStatus.Executing: // schedule cancellation on child childContext.CancelActivity(activity); childrenActive = true; break; case ActivityExecutionStatus.Canceling: case ActivityExecutionStatus.Faulting: childrenActive = true; break; case ActivityExecutionStatus.Closed: CleanupChildAtClosure(context, activity); break; default: // unhook our handler // others will be removed when we get the complete/cancel notification act.UnregisterForStatusChange(Activity.ClosedEvent, this); break; } } } // if the CAG is quiet, we are all done if (!childrenActive) { context.CloseActivity(); } return(!childrenActive); }
private void ExecuteChild(ConditionedActivityGroup cag, Activity childActivity, ActivityExecutionContext context) { ActivityExecutionContext context2 = GetChildExecutionContext(context, childActivity, true); cag.CAGState.ChildrenStats[childActivity.QualifiedName].State = CAGChildState.Excuting; context2.Activity.RegisterForStatusChange(Activity.ClosedEvent, this); context2.ExecuteActivity(context2.Activity); }
internal ConditionedActivityGroupStateInfo(ConditionedActivityGroup cag) { int len = cag.EnabledActivities.Count; this.childActivityStats = new Dictionary <string, CAGChildStats>(len); foreach (Activity act in cag.EnabledActivities) { this.childActivityStats[act.QualifiedName] = new CAGChildStats(); } }
public override ValidationErrorCollection Validate(ValidationManager manager, object obj) { ValidationErrorCollection validationErrors = base.Validate(manager, obj); ConditionedActivityGroup conditionedActivityGroup = obj as ConditionedActivityGroup; if (conditionedActivityGroup == null) { throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(ConditionedActivityGroup).FullName), "obj"); } return(validationErrors); }
internal bool Cleanup(ConditionedActivityGroup cag, ActivityExecutionContext context) { ConditionedActivityGroupStateInfo cAGState = cag.CAGState; cAGState.Completed = true; bool flag = false; Dictionary <string, CAGChildStats> childrenStats = cAGState.ChildrenStats; foreach (Activity activity in cag.EnabledActivities) { if (childrenStats[activity.QualifiedName].State == CAGChildState.Pending) { childrenStats[activity.QualifiedName].State = CAGChildState.Idle; } ActivityExecutionContext context2 = GetChildExecutionContext(context, activity, false); if (context2 != null) { Activity runtimeInitializedActivity = this.GetRuntimeInitializedActivity(context, activity); switch (runtimeInitializedActivity.ExecutionStatus) { case ActivityExecutionStatus.Executing: { context2.CancelActivity(runtimeInitializedActivity); flag = true; continue; } case ActivityExecutionStatus.Canceling: case ActivityExecutionStatus.Faulting: { flag = true; continue; } case ActivityExecutionStatus.Closed: { this.CleanupChildAtClosure(context, runtimeInitializedActivity); continue; } } activity.UnregisterForStatusChange(Activity.ClosedEvent, this); } } if (!flag) { context.CloseActivity(); } return(!flag); }
private bool AllChildrenQuiet(ConditionedActivityGroup cag, ActivityExecutionContext context) { if (context == null) { throw new ArgumentNullException("context"); } foreach (ActivityExecutionContext context2 in context.ExecutionContextManager.ExecutionContexts) { if (cag.GetActivityByName(context2.Activity.QualifiedName, true) != null) { return(false); } } return(true); }
internal void TriggerChildren(ConditionedActivityGroup cag, ActivityExecutionContext context) { Dictionary <string, CAGChildStats> childrenStats = cag.CAGState.ChildrenStats; foreach (Activity activity in cag.EnabledActivities) { if (childrenStats[activity.QualifiedName].State == CAGChildState.Pending) { Activity runtimeInitializedActivity = this.GetRuntimeInitializedActivity(context, activity); if (runtimeInitializedActivity.ExecutionStatus == ActivityExecutionStatus.Initialized) { this.ExecuteChild(cag, runtimeInitializedActivity, context); } } } }
private bool EvaluateChildConditions(ConditionedActivityGroup cag, Activity child, ActivityExecutionContext context) { bool flag; ConditionedActivityGroupStateInfo cAGState = cag.CAGState; try { cAGState.Testing = true; ActivityCondition condition = (ActivityCondition)child.GetValue(WhenConditionProperty); flag = (condition != null) ? condition.Evaluate(child, context) : (cAGState.ChildrenStats[child.QualifiedName].ExecutedCount == 0); } finally { cAGState.Testing = false; } return(flag); }
private void ExecuteChild(ConditionedActivityGroup cag, Activity childActivity, ActivityExecutionContext context) { Debug.Assert(cag != null); Debug.Assert(childActivity != null); Debug.Assert(context != null); Debug.Assert(childActivity.ExecutionStatus == ActivityExecutionStatus.Initialized); #if LOG Log("ExecuteChild " + childActivity.QualifiedName + " inside " + cag.QualifiedName); #endif ActivityExecutionContext childContext = GetChildExecutionContext(context, childActivity, true); cag.CAGState.ChildrenStats[childActivity.QualifiedName].State = CAGChildState.Excuting; // subscribe for child closure childContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, this); // execute child in inner context childContext.ExecuteActivity(childContext.Activity); }
bool AllChildrenQuiet(ConditionedActivityGroup cag, ActivityExecutionContext context) { if (context == null) { throw new ArgumentNullException("context"); } // if there are any execution contexts, 1 or more children still doing something foreach (ActivityExecutionContext activeContext in context.ExecutionContextManager.ExecutionContexts) { if (cag.GetActivityByName(activeContext.Activity.QualifiedName, true) != null) { return(false); } } // no children return(true); }
protected override void OnActivityChangeRemove(ActivityExecutionContext executionContext, Activity removedActivity) { if (executionContext == null) { throw new ArgumentNullException("executionContext"); } if (removedActivity == null) { throw new ArgumentNullException("removedActivity"); } if (removedActivity.Enabled) { ConditionedActivityGroup activity = executionContext.Activity as ConditionedActivityGroup; ConditionedActivityGroupStateInfo cAGState = activity.CAGState; if ((activity.ExecutionStatus == ActivityExecutionStatus.Executing) && (cAGState != null)) { cAGState.ChildrenStats.Remove(removedActivity.QualifiedName); } } }
/// <summary> /// Evaluate the While condition for a particular child of the CAG /// If no While condition, it becomes "execute once" /// </summary> /// <param name="cag"></param> /// <param name="child"></param> /// <param name="context"></param> /// <returns></returns> private bool EvaluateChildConditions(ConditionedActivityGroup cag, Activity child, ActivityExecutionContext context) { #if LOG Log("EvaluateChildConditions on activity " + child.QualifiedName + " inside " + cag.QualifiedName); #endif // determine the result of the when condition (evaluate once if not specified) ConditionedActivityGroupStateInfo state = cag.CAGState; try { state.Testing = true; ActivityCondition whenCondition = (ActivityCondition)child.GetValue(ConditionedActivityGroup.WhenConditionProperty); return((whenCondition != null) ? whenCondition.Evaluate(child, context) : (state.ChildrenStats[child.QualifiedName].ExecutedCount == 0)); } finally { state.Testing = false; } }
internal bool EvaluateConditions(ConditionedActivityGroup cag, ActivityExecutionContext context) { if (cag.CAGState.Completed) { return(false); } if ((cag.UntilCondition == null) || !cag.UntilCondition.Evaluate(cag, context)) { int num = 0; Dictionary <string, CAGChildStats> childrenStats = cag.CAGState.ChildrenStats; foreach (Activity activity in cag.EnabledActivities) { if (childrenStats[activity.QualifiedName].State == CAGChildState.Excuting) { num++; } else { Activity runtimeInitializedActivity = this.GetRuntimeInitializedActivity(context, activity); if (this.EvaluateChildConditions(cag, runtimeInitializedActivity, context)) { num++; childrenStats[activity.QualifiedName].State = CAGChildState.Pending; } } } if (num > 0) { return(false); } if (cag.UntilCondition != null) { throw new InvalidOperationException(SR.GetString("Error_CAGQuiet", new object[] { cag.QualifiedName })); } } return(true); }
protected override void OnWorkflowChangesCompleted(ActivityExecutionContext executionContext) { if (executionContext == null) { throw new ArgumentNullException("executionContext"); } ConditionedActivityGroup activity = executionContext.Activity as ConditionedActivityGroup; if (activity.ExecutionStatus == ActivityExecutionStatus.Executing) { ConditionedActivityGroupStateInfo cAGState = activity.CAGState; if ((cAGState != null) && !cAGState.Testing) { if (this.EvaluateConditions(activity, executionContext)) { this.Cleanup(activity, executionContext); } else { this.TriggerChildren(activity, executionContext); } } } }
internal void HandleEvent(ActivityExecutionContext context, SubscriptionEventArg e) { if (context == null) { throw new ArgumentNullException("context"); } if (e == null) { throw new ArgumentNullException("e"); } ConditionedActivityGroup activity = context.Activity as ConditionedActivityGroup; if (activity == null) { throw new ArgumentException(SR.GetString("Error_InvalidCAGActivityType"), "activity"); } if (activity.ExecutionStatus != ActivityExecutionStatus.Closed) { EventType subscriptionType = e.SubscriptionType; ActivityExecutionStatusChangedEventArgs args = (ActivityExecutionStatusChangedEventArgs)e.Args; bool flag = false; Dictionary <string, CAGChildStats> childrenStats = activity.CAGState.ChildrenStats; if (childrenStats.ContainsKey(args.Activity.QualifiedName)) { if (args.ExecutionStatus != ActivityExecutionStatus.Executing) { childrenStats[args.Activity.QualifiedName].State = CAGChildState.Idle; } if (args.ExecutionStatus == ActivityExecutionStatus.Closed) { CAGChildStats local1 = childrenStats[args.Activity.QualifiedName]; local1.ExecutedCount++; } try { if (activity.ExecutionStatus == ActivityExecutionStatus.Executing) { flag = this.EvaluateConditions(activity, context); } } finally { this.CleanupChildAtClosure(context, args.Activity); } } else if (activity.ExecutionStatus == ActivityExecutionStatus.Executing) { flag = this.EvaluateConditions(activity, context); } if (flag) { this.Cleanup(activity, context); } else if (activity.CAGState.Completed) { if (this.AllChildrenQuiet(activity, context)) { context.CloseActivity(); } } else { this.TriggerChildren(activity, context); } } }
/// <summary> /// Evaluate the conditions on the CAG /// </summary> /// <param name="cag"></param> /// <param name="context"></param> /// <returns>True if CAG is complete (UNTIL == true, or no UNTIL and no children execute), false otherwise</returns> internal bool EvaluateConditions(ConditionedActivityGroup cag, ActivityExecutionContext context) { Debug.Assert(cag != null); Debug.Assert(context != null); #if LOG Log("EvaluateConditions on " + cag.QualifiedName); cag.CAGState.DumpState("Before EvaluateConditions"); #endif // if we've already decided to quit this CAG, don't do anything if (cag.CAGState.Completed) { return(false); } // if the cag has an UNTIL condition, execute it if ((cag.UntilCondition != null) && cag.UntilCondition.Evaluate(cag, context)) { // UNTIL condition says we're done, no need to look at children #if LOG Log("Until condition is true"); #endif return(true); } // until condition is false, so let's look at all children int childExecuting = 0; // keep track of children executing Dictionary <string, CAGChildStats> childrenStats = cag.CAGState.ChildrenStats; foreach (Activity act in cag.EnabledActivities) { // if we think the child is executing, do nothing if (childrenStats[act.QualifiedName].State == CAGChildState.Excuting) { ++childExecuting; continue; } // find the run-time activity Activity activity = GetRuntimeInitializedActivity(context, act); // should it execute? if (EvaluateChildConditions(cag, activity, context)) { ++childExecuting; childrenStats[act.QualifiedName].State = CAGChildState.Pending; } } #if LOG cag.CAGState.DumpState("After EvaluateConditions"); #endif // if any work to do, CAG not yet done if (childExecuting > 0) { return(false); } // CAG is quiet (nothing more to do) // if specified an UNTIL condition but we have nothing to do if (cag.UntilCondition != null) { #if LOG Log("CAG quiet, but UNTIL condition is false, so error time"); #endif throw new InvalidOperationException(SR.GetString(SR.Error_CAGQuiet, cag.QualifiedName)); } #if LOG Log("CAG quiet"); #endif return(true); }
internal void HandleEvent(ActivityExecutionContext context, SubscriptionEventArg e) { if (context == null) { throw new ArgumentNullException("context"); } if (e == null) { throw new ArgumentNullException("e"); } ConditionedActivityGroup cag = context.Activity as ConditionedActivityGroup; if (cag == null) { throw new ArgumentException(SR.GetString(SR.Error_InvalidCAGActivityType), "activity"); } // Already done the cleanup from another child's signalling if (cag.ExecutionStatus == ActivityExecutionStatus.Closed) { return; } if (e.SubscriptionType != EventType.StatusChange) { // split into seperate test to keep FxCop happy (only place SubscriptionType used) Debug.Assert(false, "This CAG activity handler does not handle this event"); } ActivityExecutionStatusChangedEventArgs args1 = (ActivityExecutionStatusChangedEventArgs)e.Args; #if LOG Log("HandleEvent for " + cag.QualifiedName); Log("event = " + e.ToString()); Log("activity = " + args1.Activity.QualifiedName); #endif bool timeToQuit = false; // is this event is for an immediate child? Debug.Assert(cag == args1.Activity.Parent, "Received event for non-child of CAG"); Dictionary <string, CAGChildStats> childrenStats = cag.CAGState.ChildrenStats; // it is possible that dynamic update has removed the child before we get the closed event // if that is the case, we don't need to update it's stats since it's not there if (childrenStats.ContainsKey(args1.Activity.QualifiedName)) { // update our state about the child if (args1.ExecutionStatus != ActivityExecutionStatus.Executing) { childrenStats[args1.Activity.QualifiedName].State = CAGChildState.Idle; } // @undone: this will break if scopes move to "Delayed" closing after Completed. if (args1.ExecutionStatus == ActivityExecutionStatus.Closed) { childrenStats[args1.Activity.QualifiedName].ExecutedCount++; } try { // re-evaluate the conditions on any status change, as long as the CAG is still executing if (cag.ExecutionStatus == ActivityExecutionStatus.Executing) { timeToQuit = EvaluateConditions(cag, context); } } finally { // get rid of the child that just completed // do this in the finally so that the child is cleaned up, // even if EvaluateConditions throws beause the CAG is stalled CleanupChildAtClosure(context, args1.Activity); } } else { // child has been removed // we still need to see if the CAG is done, provided we are still executing if (cag.ExecutionStatus == ActivityExecutionStatus.Executing) { timeToQuit = EvaluateConditions(cag, context); } } // is the CAG just completed? if (timeToQuit) { Cleanup(cag, context); } else if (cag.CAGState.Completed) { // if the CAG is simply waiting for all children to complete, see if this is the last one if (AllChildrenQuiet(cag, context)) { // Mark the CAG as closed, if it hasn't already been marked so. context.CloseActivity(); } } else { // CAG not done, so see if any children need to start TriggerChildren(cag, context); } }