Example #1
0
        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);
            }
        }
Example #2
0
        protected override void UpdateInstance(NativeActivityUpdateContext updateContext)
        {
            TryCatchState state = updateContext.GetValue(this.state);

            if (state != null && !state.SuppressCancel && state.CaughtException != null && this.FindCatch(state.CaughtException.Exception) == null)
            {
                // This is a very small window of time in which we want to block update inside TryCatch.
                // This is in between OnExceptionFromTry faultHandler and OnTryComplete completionHandler.
                // A Catch handler could be found at OnExceptionFromTry before update, yet that appropriate Catch handler could have been removed during update and not be found at OnTryComplete.
                // In such case, the exception can be unintentionally ----ed without ever propagating it upward.
                // Such TryCatch state is detected by inspecting the TryCatchState private variable for SuppressCancel == false && CaughtException != Null && this.FindCatch(state.CaughtException.Exception) == null.
                updateContext.DisallowUpdate(SR.TryCatchInvalidStateForUpdate(state.CaughtException.Exception));
            }
        }
Example #3
0
        /// <summary>
        /// Used for Dynamic Update: after the instance is updated, if the statemachine is already transitioning, the index of the to-be-scheduled state 
        /// would need to be updated.
        /// </summary>
        /// <param name="updateContext">Dynamic Update context</param>
        /// <param name="eventManager">Internal StateMachineEventManager</param>
        /// <returns>True, 1. if update is successful and the instanced is updated with the new indexes, and 2 all the trigger ID in the queue are updated;
        /// false otherwise and the update should fail.</returns>
        private bool UpdateEventManager(
            NativeActivityUpdateContext updateContext,
            StateMachineEventManager eventManager)
        {
            Fx.Assert(null != eventManager.CurrentBeingProcessedEvent, "The eventManager must have some info that needs to be updated during transition.");

            int updatedEventsInQueue = 0;
            int originalTriggerId = int.MinValue;
            int originalConditionIndex = int.MinValue;
            bool updateCurrentEventSucceed = null == eventManager.CurrentBeingProcessedEvent ? true : false;

            foreach (InternalTransition transition in this.internalTransitions)
            {
                object savedTriggerIndex = updateContext.GetSavedOriginalValue(transition.Trigger);
                if (savedTriggerIndex != null)
                {
                    Fx.Assert(!updateContext.IsNewlyAdded(transition.Trigger), "the trigger in transition already exist.");

                    if (null != eventManager.CurrentBeingProcessedEvent &&
                        eventManager.CurrentBeingProcessedEvent.TriggedId == (int)savedTriggerIndex)
                    {
                        // found a match of the running trigger update the current processed event
                        // Don't match the trigger ID, match only when the Condition is also matched.
                        if (eventManager.CurrentConditionIndex == -1)
                        {
                            if (transition.IsUnconditional)
                            {
                                // executing transition before persist is unconditional
                                originalTriggerId = eventManager.CurrentBeingProcessedEvent.TriggedId;
                                originalConditionIndex = 0;
                                eventManager.CurrentBeingProcessedEvent.TriggedId = transition.InternalTransitionIndex;

                                if (updateContext.GetValue(this.isExiting))
                                {
                                    Fx.Assert(eventManager.OnTransition, "The state is transitioning.");
                                    updateContext.SetValue(this.Result, GetTo(transition.InternalTransitionIndex));
                                }

                                updateCurrentEventSucceed = true;
                            }
                            else
                            {
                                updateContext.DisallowUpdate(SR.ChangeTransitionTypeDuringTransitioningBlockDU);
                                return false;
                            }
                        }
                        else if (eventManager.CurrentConditionIndex >= 0)
                        {
                            Fx.Assert(!transition.IsUnconditional, "Cannot update a running conditional transition with a unconditional one.");

                            if (!transition.IsUnconditional)
                            {
                                // executing transition before and after are conditional
                                for (int updatedIndex = 0; updatedIndex < transition.TransitionDataList.Count; updatedIndex++)
                                {
                                    Activity condition = transition.TransitionDataList[updatedIndex].Condition;
                                    Fx.Assert(null != condition, "Conditional transition must have Condition activity.");
                                    int? savedCondIndex = updateContext.GetSavedOriginalValue(condition) as int?;

                                    if (eventManager.CurrentConditionIndex == savedCondIndex)
                                    {
                                        originalTriggerId = eventManager.CurrentBeingProcessedEvent.TriggedId;
                                        originalConditionIndex = eventManager.CurrentConditionIndex;
                                        eventManager.CurrentBeingProcessedEvent.TriggedId = transition.InternalTransitionIndex;
                                        eventManager.CurrentConditionIndex = updatedIndex;

                                        if (updateContext.GetValue(this.isExiting))
                                        {
                                            Fx.Assert(eventManager.OnTransition, "The state is transitioning.");
                                            updateContext.SetValue(this.Result, this.GetTo(transition.InternalTransitionIndex, (int)updatedIndex));
                                        }

                                        updateCurrentEventSucceed = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    foreach (TriggerCompletedEvent completedEvent in eventManager.Queue)
                    {
                        if ((int)savedTriggerIndex == completedEvent.TriggedId)
                        {
                            completedEvent.TriggedId = transition.InternalTransitionIndex;
                            updatedEventsInQueue++;
                        }
                    }
                }
            }

            return eventManager.Queue.Count() == updatedEventsInQueue ? updateCurrentEventSucceed : false;
        }
        protected override void UpdateInstance(NativeActivityUpdateContext updateContext)
        {
            // we only care about the server-side Receive since the client-side Receive is not persistable.
            // only valid instance update condition is when a bookmark with OperationBookmarkName is found.

            CorrelationHandle followingCorrelation = (this.CorrelatesWith == null) ? null : (CorrelationHandle)updateContext.GetValue(this.CorrelatesWith);
            if (followingCorrelation == null)
            {
                followingCorrelation = updateContext.FindExecutionProperty(CorrelationHandle.StaticExecutionPropertyName) as CorrelationHandle;
            }

            BookmarkScope bookmarkScope;
            if (followingCorrelation != null && followingCorrelation.Scope != null)
            {
                bookmarkScope = followingCorrelation.Scope;
            }
            else
            {
                bookmarkScope = updateContext.DefaultBookmarkScope;
            }

            string savedOriginalOperationName = (string)updateContext.GetSavedOriginalValue(OperationNamePropertyName);
            XName savedOriginalServiceContractName = (XName)updateContext.GetSavedOriginalValue(ServiceContractNamePropertyName);
            if ((savedOriginalOperationName == null && savedOriginalServiceContractName == null) || (savedOriginalOperationName == this.OperationName && savedOriginalServiceContractName == this.ServiceContractName))
            {
                // neither ServiceContractName nor OperationName have changed
                // nothing to do, so exit early.
                return;
            }

            string originalOperationBookmarkName = BookmarkNameHelper.CreateBookmarkName(savedOriginalOperationName ?? this.OperationName, savedOriginalServiceContractName ?? this.ServiceContractName);
            if (updateContext.RemoveBookmark(originalOperationBookmarkName, bookmarkScope))
            {
                // if we are here, it means Receive is on the server-side and waiting for a request message to arrive
                updateContext.CreateBookmark(this.OperationBookmarkName, new BookmarkCallback(this.OnMessage), bookmarkScope);
            }
            else
            {
                // this means Receive is in a state DU is not allowed.
                updateContext.DisallowUpdate(SR.InvalidReceiveStateForDU);
            }
        }