Example #1
0
        private void ProcessTransitions(NativeActivityMetadata metadata)
        {
            for (int i = 0; i < this.Transitions.Count; i++)
            {
                Transition         transition         = this.Transitions[i];
                InternalTransition internalTransition = null;
                Activity           triggerActivity    = transition.ActiveTrigger;

                if (!_triggerInternalTransitionMapping.TryGetValue(triggerActivity, out internalTransition))
                {
                    metadata.AddChild(triggerActivity);

                    internalTransition = new InternalTransition
                    {
                        Trigger = triggerActivity,
                        InternalTransitionIndex = _internalTransitions.Count,
                    };

                    _triggerInternalTransitionMapping.Add(triggerActivity, internalTransition);
                    _internalTransitions.Add(internalTransition);
                }

                AddTransitionData(metadata, internalTransition, transition);
            }
        }
Example #2
0
        private void OnConditionComplete(NativeActivityContext context, ActivityInstance completedInstance, bool result)
        {
            StateMachineEventManager eventManager = this.EventManager.Get(context);
            int triggerId = eventManager.CurrentBeingProcessedEvent.TriggedId;

            if (result)
            {
                this.TakeTransition(context, eventManager, triggerId);
            }
            else
            {
                // condition failed: reschedule trigger
                int currentConditionIndex = eventManager.CurrentConditionIndex;
                Fx.Assert(eventManager.CurrentConditionIndex >= 0, "Conditional Transition must have non-negative index.");
                InternalTransition transition = this.GetInternalTransition(triggerId);
                currentConditionIndex++;

                if (currentConditionIndex < transition.TransitionDataList.Count)
                {
                    eventManager.CurrentConditionIndex = currentConditionIndex;
                    context.ScheduleActivity <bool>(transition.TransitionDataList[currentConditionIndex].Condition, _onConditionComplete, null);
                }
                else
                {
                    // Schedule current trigger again firstly.
                    context.ScheduleActivity(transition.Trigger, _onTriggerComplete);
                    _currentRunningTriggers.Set(context, _currentRunningTriggers.Get(context) + 1);

                    // check whether there is any other trigger completed.
                    ProcessNextTriggerCompletedEvent(context, eventManager);
                }
            }
        }
Example #3
0
        private void OnTriggerComplete(NativeActivityContext context, ActivityInstance completedInstance)
        {
            int runningTriggers = _currentRunningTriggers.Get(context);

            _currentRunningTriggers.Set(context, --runningTriggers);
            bool isOnExit = _isExiting.Get(context);

            if (!context.IsCancellationRequested && runningTriggers == 0 && isOnExit)
            {
                this.ScheduleExit(context);
            }
            else if (completedInstance.State == ActivityInstanceState.Closed)
            {
                InternalTransition internalTransition = null;
                _triggerInternalTransitionMapping.TryGetValue(completedInstance.Activity, out internalTransition);
                Fx.Assert(internalTransition != null, "internalTransition should be added into triggerInternalTransitionMapping in CacheMetadata.");

                StateMachineEventManager eventManager = this.EventManager.Get(context);
                bool canBeProcessedImmediately;
                eventManager.RegisterCompletedEvent(
                    new TriggerCompletedEvent {
                    Bookmark = _evaluateConditionBookmark.Get(context), TriggedId = internalTransition.InternalTransitionIndex
                },
                    out canBeProcessedImmediately);

                if (canBeProcessedImmediately)
                {
                    ProcessNextTriggerCompletedEvent(context, eventManager);
                }
            }
        }
Example #4
0
        //protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
        //{
        //    InternalState originalInternalState = (InternalState)originalActivity;

        //    // NOTE: State.Entry/Exit are allowed to be removed, because it doesn't change the execution semantics of SM
        //    // if this removed activity was executing, WF runtime would disallow the update.
        //    Activity entryActivityMatch = metadata.GetMatch(this.Entry);
        //    Activity exitActivityMatch = metadata.GetMatch(this.Exit);

        //    if ((null != entryActivityMatch && !object.ReferenceEquals(entryActivityMatch, originalInternalState.Entry)) ||
        //        (null != exitActivityMatch && !object.ReferenceEquals(exitActivityMatch, originalInternalState.Exit)))
        //    {
        //        // original State.Entry/Exit is replaced with another child activities with InternalState
        //        // new State.Entry/Exit is moved from another child activities within InternalState.
        //        metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
        //        return;
        //    }

        //    int originalTriggerInUpdatedDefinition = 0;

        //    foreach (InternalTransition originalTransition in originalInternalState.internalTransitions)
        //    {
        //        if (metadata.IsReferenceToImportedChild(originalTransition.Trigger))
        //        {
        //            metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
        //            return;
        //        }

        //        if (!originalTransition.IsUnconditional)
        //        {
        //            // new Trigger activity
        //            foreach (TransitionData transitionData in originalTransition.TransitionDataList)
        //            {
        //                if (metadata.IsReferenceToImportedChild(transitionData.Condition))
        //                {
        //                    metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
        //                    return;
        //                }
        //            }
        //        }
        //    }

        //    foreach (InternalTransition updatedTransition in this.internalTransitions)
        //    {
        //        if (metadata.IsReferenceToImportedChild(updatedTransition.Trigger))
        //        {
        //            // if the trigger is referenced, it might have another save values already.
        //            metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
        //            return;
        //        }

        //        Activity triggerMatch = metadata.GetMatch(updatedTransition.Trigger);

        //        if (null != triggerMatch)
        //        {
        //            InternalTransition originalTransition;

        //            if (originalInternalState.triggerInternalTransitionMapping.TryGetValue(triggerMatch, out originalTransition))
        //            {
        //                originalTriggerInUpdatedDefinition++;

        //                if (originalTransition.IsUnconditional)
        //                {
        //                    string errorMessage;
        //                    bool canTransitionBeUpdated = ValidateDUInUnconditionalTransition(metadata, updatedTransition, originalTransition, out errorMessage);

        //                    if (!canTransitionBeUpdated)
        //                    {
        //                        metadata.DisallowUpdateInsideThisActivity(errorMessage);
        //                        return;
        //                    }
        //                }
        //                else
        //                {
        //                    if (updatedTransition.IsUnconditional)
        //                    {
        //                        // cannot change the transition from condition to unconditional.
        //                        metadata.DisallowUpdateInsideThisActivity(SR.ChangeConditionalTransitionToUnconditionalBlockDU);
        //                        return;
        //                    }
        //                    else
        //                    {
        //                        string errorMessage;
        //                        bool canTransitionBeUpdated = ValidateDUInConditionTransition(metadata, updatedTransition, originalTransition, out errorMessage);

        //                        if (!canTransitionBeUpdated)
        //                        {
        //                            metadata.DisallowUpdateInsideThisActivity(errorMessage);
        //                            return;
        //                        }
        //                    }
        //                }
        //            }
        //            else
        //            {
        //                // the trigger is an child activity moved from elsewhere within the state
        //                metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
        //                return;
        //            }
        //        }
        //        else
        //        {
        //            // new Trigger activity
        //            foreach (TransitionData transitionData in updatedTransition.TransitionDataList)
        //            {
        //                if ((null != transitionData.Condition && null != metadata.GetMatch(transitionData.Condition)) ||
        //                    (null != transitionData.Action && null != metadata.GetMatch(transitionData.Action)))
        //                {
        //                    // if a new transition is added, it is expected that the Condition/Action
        //                    // are newly created.
        //                    metadata.DisallowUpdateInsideThisActivity(SR.ChangingTriggerOrUseOriginalConditionActionBlockDU);
        //                    return;
        //                }
        //            }
        //        }
        //    }

        //    if (originalTriggerInUpdatedDefinition != originalInternalState.internalTransitions.Count)
        //    {
        //        // NOTE: in general, if the transition is removed when there are pending triggers,
        //        // runtime would be able to detect the missing child activities.  However, in cases,
        //        // where the transition is happening already (in between completion of Transition.Action
        //        // callback but before InternalState is completed), the workflow definition can be unloaded
        //        // and updated.  The InternalState is unable to trace the original transition that set the
        //        // destination state index.  In that case, the update would fail at UpdateInstance.
        //        // To simplify the model, it is more convenient to disallow removing existing transitions
        //        // from an executing InternalState.  The only extra restriction it brings, is that it disables
        //        // update even if the InternalState is uploaded at State.Entry.  This scenario, however, is uncommon.
        //        metadata.DisallowUpdateInsideThisActivity(SR.RemovingTransitionsBlockDU);
        //    }
        //}

        //protected override void UpdateInstance(NativeActivityUpdateContext updateContext)
        //{
        //    StateMachineEventManager eventManager = updateContext.GetValue(this.EventManager) as StateMachineEventManager;
        //    Fx.Assert(eventManager != null, "eventManager is available in every internalActivity.");

        //    if (eventManager.CurrentBeingProcessedEvent != null || eventManager.Queue.Any())
        //    {
        //        // Updated state is evaluating conditions or transitioning to another state,
        //        // Then we need to update the index of the current evaluated trigger (in case the trigger is moved)
        //        // and the condition index.
        //        // if the state is transitioning already, then we should update destination state id.
        //        bool isUpdateSuccessful = this.UpdateEventManager(updateContext, eventManager);

        //        if (!isUpdateSuccessful)
        //        {
        //            updateContext.DisallowUpdate(SR.DUTriggerOrConditionChangedDuringTransitioning);
        //            return;
        //        }

        //        if (updateContext.GetValue(this.isExiting) != true)
        //        {
        //            this.RescheduleNewlyAddedTriggers(updateContext);
        //        }
        //    }
        //    else if (updateContext.GetValue(this.currentRunningTriggers) > 0)
        //    {
        //        Fx.Assert(updateContext.GetValue(this.isExiting) != true, "No triggers have completed, state should not be transitioning.");

        //        // the state is not transitioning yet and is persisted at trigger.
        //        this.RescheduleNewlyAddedTriggers(updateContext);
        //    }
        //}

        private static void AddTransitionData(NativeActivityMetadata metadata, InternalTransition internalTransition, Transition transition)
        {
            TransitionData  transitionData = new TransitionData();
            Activity <bool> condition      = transition.Condition;

            transitionData.Condition = condition;

            if (condition != null)
            {
                metadata.AddChild(condition);
            }

            Activity action = transition.Action;

            transitionData.Action = action;

            if (action != null)
            {
                metadata.AddChild(action);
            }

            if (transition.To != null)
            {
                transitionData.To = transition.To.InternalState;
            }

            internalTransition.TransitionDataList.Add(transitionData);
        }
Example #5
0
        private void TakeTransition(NativeActivityContext context, StateMachineEventManager eventManager, int triggerId)
        {
            this.EventManager.Get(context).OnTransition = true;
            InternalTransition transition = this.GetInternalTransition(triggerId);

            if (transition.IsUnconditional)
            {
                Fx.Assert(-1 == eventManager.CurrentConditionIndex, "CurrentConditionIndex should be -1, if the transition is unconditional.");
                this.PrepareForExit(context, this.GetTo(triggerId));
            }
            else
            {
                Fx.Assert(-1 != eventManager.CurrentConditionIndex, "CurrentConditionIndex should not be -1, if the transition is conditional.");
                this.PrepareForExit(context, this.GetTo(triggerId, eventManager.CurrentConditionIndex));
            }
        }
Example #6
0
        private void ScheduleAction(NativeActivityContext context)
        {
            StateMachineEventManager eventManager = this.EventManager.Get(context);

            if (eventManager.IsReferredByBeingProcessedEvent(_evaluateConditionBookmark.Get(context)))
            {
                InternalTransition transition = this.GetInternalTransition(eventManager.CurrentBeingProcessedEvent.TriggedId);
                Activity           action     = transition.TransitionDataList[-1 == eventManager.CurrentConditionIndex ? 0 : eventManager.CurrentConditionIndex].Action;

                if (action != null)
                {
                    context.ScheduleActivity(action);
                }
            }

            this.RemoveBookmarks(context);
        }
Example #7
0
        private void StartEvaluateCondition(NativeActivityContext context, Bookmark bookmark, object value)
        {
            // Start to evaluate conditions of the trigger which represented by currentTriggerIndex
            StateMachineEventManager eventManager = this.EventManager.Get(context);
            int triggerId = eventManager.CurrentBeingProcessedEvent.TriggedId;
            InternalTransition transition = this.GetInternalTransition(triggerId);

            if (transition.IsUnconditional)
            {
                eventManager.CurrentConditionIndex = -1;
                this.TakeTransition(context, eventManager, triggerId);
            }
            else
            {
                eventManager.CurrentConditionIndex = 0;
                context.ScheduleActivity <bool>(
                    this.GetCondition(
                        triggerId,
                        eventManager.CurrentConditionIndex),
                    _onConditionComplete,
                    null);
            }
        }
        private static bool ValidateDUInUnconditionalTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage)
        {
            Fx.Assert(originalTransition.IsUnconditional, "Transition should be unconditional in the original definition.");
            Activity originalAction = originalTransition.TransitionDataList[0].Action;

            foreach (TransitionData transitionData in updatedTransition.TransitionDataList)
            {
                Activity updatedAction  = transitionData.Action;
                Activity actionMatch    = metadata.GetMatch(updatedAction);
                Activity conditionMatch = metadata.GetMatch(transitionData.Condition);

                if ((null == originalAction && null != actionMatch) ||
                    (null != originalAction && null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch)))
                {
                    // Transition.Action is an activity moved from elsewhere within the InternalState
                    errorMessage = SR.MovingActivitiesInStateBlockDU;
                    return(false);
                }
            }

            errorMessage = string.Empty;
            metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex);
            return(true);
        }
        private static bool ValidateDUInConditionTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage)
        {
            Fx.Assert(!originalTransition.IsUnconditional, "Transition should be conditional in the original definition.");
            errorMessage = string.Empty;

            foreach (TransitionData updatedTData in updatedTransition.TransitionDataList)
            {
                if (metadata.IsReferenceToImportedChild(updatedTData.Condition))
                {
                    // if the trigger is referenced, it might have another save values already.
                    errorMessage = SR.TriggerOrConditionIsReferenced;
                    return(false);
                }

                Fx.Assert(null != updatedTData.Condition, "Must be a condition transition.");
                Activity conditionMatch = metadata.GetMatch(updatedTData.Condition);

                if (null == conditionMatch && null != metadata.GetMatch(updatedTData.Action))
                {
                    // new Transition.Condition with an Transition.Action moved from within the InternalState.
                    errorMessage = SR.MovingActivitiesInStateBlockDU;
                    return(false);
                }
                else if (null != conditionMatch)
                {
                    bool foundMatchingOriginalCondition = false;

                    for (int transitionIndex = 0; transitionIndex < originalTransition.TransitionDataList.Count; transitionIndex++)
                    {
                        if (object.ReferenceEquals(originalTransition.TransitionDataList[transitionIndex].Condition, conditionMatch))
                        {
                            foundMatchingOriginalCondition = true;

                            // found the original matching condition in updated transition definition.
                            TransitionData originalTData = originalTransition.TransitionDataList[transitionIndex];

                            Activity originalAction = originalTData.Action;

                            // NOTE: Transition.Action is allowed to be removed, because it doesn't change the execution semantics of SM
                            // if this removed activity was executing, WF runtime would disallow the update.
                            Activity actionMatch = metadata.GetMatch(updatedTData.Action);

                            if (null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch))
                            {
                                // Transition.Action is an activity moved from elsewhere within the InternalState
                                errorMessage = SR.MovingActivitiesInStateBlockDU;
                                return(false);
                            }

                            metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex);
                            metadata.SaveOriginalValue(updatedTData.Condition, transitionIndex);
                        }
                    }

                    if (!foundMatchingOriginalCondition)
                    {
                        // another child activity is move to the Transition.Condition.
                        errorMessage = SR.DUDisallowIfCannotFindingMatchingCondition;
                        return(false);
                    }
                }
            }

            return(true);
        }