protected internal virtual void HandleChildRemovalInScope(ExecutionEntity removedExecution) { // TODO: the following should be closer to PvmAtomicOperationDeleteCascadeFireActivityEnd // (note though that e.g. boundary events expect concurrent executions to be preserved) // // Idea: attempting to prune and synchronize on the parent is the default behavior when // a concurrent child is removed, but scope activities implementing ModificationObserverBehavior // override this default (and thereforemust* take care of reorganization themselves) // notify the behavior that a concurrent execution has been removed // must be set due to deleteCascade behavior ActivityImpl activity = removedExecution.Activity as ActivityImpl; ScopeImpl flowScope = activity.FlowScope; IActivityExecution scopeExecution = removedExecution.GetParentScopeExecution(false); IActivityExecution executionInParentScope = removedExecution.IsConcurrent ? removedExecution : removedExecution.Parent; if (flowScope.ActivityBehavior != null && flowScope.ActivityBehavior is IModificationObserverBehavior) { // let child removal be handled by the scope itself IModificationObserverBehavior behavior = (IModificationObserverBehavior)flowScope.ActivityBehavior; behavior.DestroyInnerInstance(executionInParentScope); } else { if (executionInParentScope.IsConcurrent) { executionInParentScope.Remove(); scopeExecution.TryPruneLastConcurrentChild(); scopeExecution.ForceUpdate(); } } }
public virtual void ConcurrentChildExecutionEnded(IActivityExecution scopeExecution, IActivityExecution endedExecution) { // join endedExecution.Remove(); scopeExecution.TryPruneLastConcurrentChild(); scopeExecution.ForceUpdate(); }
public override void DestroyInnerInstance(IActivityExecution concurrentExecution) { var scopeExecution = concurrentExecution.Parent; concurrentExecution.Remove(); scopeExecution.ForceUpdate(); var nrOfActiveInstances = GetLoopVariable(scopeExecution, NumberOfActiveInstances); SetLoopVariable(scopeExecution, NumberOfActiveInstances, nrOfActiveInstances - 1); }
protected internal virtual void SignalCompensationDone(IActivityExecution execution) { // default behavior is to join compensating executions and propagate the signal if all executions have compensated // only wait for non-event-scope executions cause a compensation event subprocess consume the compensation event and // do not have to compensate embedded subprocesses (which are still non-event-scope executions) if (((PvmExecutionImpl)execution).NonEventScopeExecutions.Count == 0) { if (execution.Parent != null) { var parent = execution.Parent; execution.Remove(); parent.Signal(CompensationUtil.SignalCompensationDone, null); } } }
/// <summary> /// Tolerates the broken execution trees fixed with CAM-3727 where there may be more /// ancestor scope executions than ancestor flow scopes; /// In that case, the argument execution is removed, the parent execution of the argument /// is returned such that one level of mismatch is corrected. /// Note that this does not necessarily skip the correct scope execution, since /// the broken parent-child relationships may be anywhere in the tree (e.g. consider a non-interrupting /// boundary event followed by a subprocess (i.e. scope), when the subprocess ends, we would /// skip the subprocess's execution). /// </summary> public static IActivityExecution DeterminePropagatingExecutionOnEnd(IActivityExecution propagatingExecution, IDictionary <ScopeImpl, PvmExecutionImpl> activityExecutionMapping) { if (!propagatingExecution.IsScope) { return(propagatingExecution); } // superfluous scope executions won't be contained in the activity-execution mapping if (activityExecutionMapping.Values.Contains((PvmExecutionImpl)propagatingExecution)) { return(propagatingExecution); } // skip one scope propagatingExecution.Remove(); var parent = propagatingExecution.Parent; parent.Activity = (propagatingExecution.Activity); return(propagatingExecution.Parent); }
public static bool EventSubprocessConcurrentChildExecutionEnded(IActivityExecution scopeExecution, IActivityExecution endedExecution) { var performLegacyBehavior = IsLegacyBehaviorRequired(endedExecution); if (performLegacyBehavior) { Log.EndConcurrentExecutionInEventSubprocess(); // notify the grandparent flow scope in a similar way PvmAtomicOperationAcitivtyEnd does var flowScope = endedExecution.Activity.FlowScope; if (flowScope != null) { flowScope = flowScope.FlowScope; if (flowScope != null) { if (flowScope == endedExecution.Activity.ProcessDefinition) { endedExecution.Remove(); scopeExecution.TryPruneLastConcurrentChild(); scopeExecution.ForceUpdate(); } else { var flowScopeActivity = (IPvmActivity)flowScope; var activityBehavior = flowScopeActivity.ActivityBehavior; if (activityBehavior is ICompositeActivityBehavior) { ((ICompositeActivityBehavior)activityBehavior).ConcurrentChildExecutionEnded( scopeExecution, endedExecution); } } } } } return(performLegacyBehavior); }
public void ConcurrentChildExecutionEnded(IActivityExecution scopeExecution, IActivityExecution endedExecution) { endedExecution.Remove(); scopeExecution.TryPruneLastConcurrentChild(); }