private void cmdUpdateInstance_Click(object sender, RoutedEventArgs e) { SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore(); instanceStore.ConnectionString = @"Data Source=(LocalDB)\v11.0;Initial Catalog=WFPersist;Integrated Security=True"; WorkflowApplicationInstance wfInstance = WorkflowApplication.GetInstance(new Guid(txtUpdateInstance.Text), instanceStore); DataContractSerializer s = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = File.Open(txtUpdateMapFile.Text, FileMode.Open)) { updateMap = s.ReadObject(fs) as DynamicUpdateMap; } var wfApp = new WorkflowApplication(new MovieRentalProcess(), new WorkflowIdentity { Name = "v2MovieRentalProcess", Version = new System.Version(2, 0, 0, 0) }); IList <ActivityBlockingUpdate> act; if (wfInstance.CanApplyUpdate(updateMap, out act)) { wfApp.Load(wfInstance, updateMap); wfApp.Unload(); } }
private void cmdSaveUpdateMap_Click(object sender, RoutedEventArgs e) { DeltaWF = LoadActivityBuilder(txtWorkflowSnapshot.Text); updateMap = DynamicUpdateServices.CreateUpdateMap(DeltaWF); SaveUpdateMap(updateMap, txtWorkflowSnapshot.Text); }
protected static IList <ActivityBlockingUpdate> GetActivitiesBlockingUpdate(object deserializedRuntimeState, DynamicUpdateMap updateMap) { ActivityExecutor executor = deserializedRuntimeState as ActivityExecutor; if (executor == null) { throw FxTrace.Exception.Argument("deserializedRuntimeState", SR.InvalidRuntimeState); } if (updateMap == null) { throw FxTrace.Exception.ArgumentNull("updateMap"); } DynamicUpdateMap rootMap = updateMap; if (updateMap.IsForImplementation) { rootMap = updateMap.AsRootMap(); } IList <ActivityBlockingUpdate> result = executor.GetActivitiesBlockingUpdate(rootMap); if (result == null) { result = new List <ActivityBlockingUpdate>(); } return(result); }
public void UpdateRawInstance(DynamicUpdateMap updateMap, Activity targetDefinition, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { this.updateList = GetInstanceListsNeedingUpdate(updateMap, targetDefinition, secondaryRootInstances, ref updateErrors); if (updateErrors != null && updateErrors.Count > 0) { // error found. // there is no need to proceed to updating the instances return; } // if UpdateType is either MapEntryExists or ParentIdShiftOnly, // update the ActivityIDs and update Environments // also, update the ImplementationVersion. foreach (InstanceListNeedingUpdate update in this.updateList) { Fx.Assert(update.InstanceList != null, "update.InstanceList must not be null."); if (update.NothingChanged) { continue; } Fx.Assert(update.NewId != null, "update.NewId must not be null."); InstanceList instanceList = update.InstanceList; instanceList.ActivityId = update.NewId.AsByteArray(); if (update.ParentIdShiftOnly) { // this InstanceList must have been one of those whose IDs shifted by their parent's ID change, // but no involvement in DU. continue; } bool implementationVersionUpdateNeeded = false; if (update.MapEntry.ImplementationUpdateMap != null) { implementationVersionUpdateNeeded = true; } if (update.MapEntry.HasEnvironmentUpdates) { // update LocationEnvironemnt Fx.Assert(update.NewActivity != null, "TryGetUpdateMapEntryFromRootMap should have thrown if it couldn't map to an activity"); instanceList.UpdateEnvironments(update.MapEntry.EnvironmentUpdateMap, update.NewActivity); } for (int i = 0; i < instanceList.Count; i++) { ActivityInstance activityInstance = instanceList[i] as ActivityInstance; if (implementationVersionUpdateNeeded) { activityInstance.ImplementationVersion = update.NewActivity.ImplementationVersion; } } } }
private void cmdSaveUpdateMap_Click(object sender, RoutedEventArgs e) { DeltaWF = LoadActivityBuilder(txtWorkflowSnapshot.Text); updateMap = DynamicUpdateServices.CreateUpdateMap(DeltaWF); SaveUpdateMap(updateMap, txtWorkflowSnapshot.Text); }
internal DynamicUpdateMapQuery(DynamicUpdateMap map, Activity updatedWorkflowDefinition, Activity originalWorkflowDefinition) { Fx.Assert(updatedWorkflowDefinition == updatedWorkflowDefinition.RootActivity, "This parameter must be root of workflow"); Fx.Assert(originalWorkflowDefinition == originalWorkflowDefinition.RootActivity, "This parameter must be root of workflow"); this.map = map; this.updatedWorkflowDefinition = updatedWorkflowDefinition; this.originalWorkflowDefinition = originalWorkflowDefinition; }
private static void UpgradeExistingWorkflow(Guid id, DynamicUpdateMap map) { SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(ConfigurationManager.ConnectionStrings["db"].ConnectionString); WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(id, store); WorkflowApplication app = new WorkflowApplication(GetUpdatedWorkflow()); app.Load(instance, map); app.Unload(); }
//[SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters, Justification = "Approved Design. Returning a bool makes the intent much clearer than something that just returns a list.")] public bool CanApplyUpdate(DynamicUpdateMap updateMap, out IList <ActivityBlockingUpdate> activitiesBlockingUpdate) { if (updateMap == null) { throw FxTrace.Exception.ArgumentNull("updateMap"); } activitiesBlockingUpdate = WorkflowApplication.GetActivitiesBlockingUpdate(this, updateMap); return(activitiesBlockingUpdate == null || activitiesBlockingUpdate.Count == 0); }
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { DynamicUpdateMap map = value as DynamicUpdateMap; if (destinationType == typeof(MarkupExtension) && map != null) { return(new DynamicUpdateMapExtension(map)); } return(base.ConvertTo(context, culture, value, destinationType)); }
public void SaveUpdateMap(DynamicUpdateMap map, string fileName) { var path = System.IO.Path.ChangeExtension(fileName, "map"); DataContractSerializer serialize = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = File.Open(path, FileMode.Create)) { serialize.WriteObject(fs, map); } txtUpdateMapFile.Text = path; }
/// <summary> /// Load update map from updated defintion and save it to file *.map /// </summary> /// <param name="fileName"></param> public static void SaveUpdateMap(String fileName) { ActivityBuilder wf = LoadActivityBuilder(fileName); DynamicUpdateMap map = DynamicUpdateServices.CreateUpdateMap(wf); String path = System.IO.Path.ChangeExtension(fileName, "map"); DataContractSerializer serialize = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = File.Open(path, FileMode.Create)) { serialize.WriteObject(fs, map); } }
private static void CreateUpdateMaps(ActivityBuilder wf, string name) { // Create the UpdateMap. DynamicUpdateMap map = DynamicUpdateServices.CreateUpdateMap(wf); // Serialize it to a file. string path = Path.Combine(mapPath, name); DataContractSerializer sz = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = System.IO.File.Open(path, FileMode.Create)) { sz.WriteObject(fs, map); } }
static void Main(string[] args) { // Create a workflow instance from the original definition and persist to SQL Guid id = CreateAndUnloadInitialWorkflow(); // Now create the update map that converts from the original workflow to the updated workflow DynamicUpdateMap map = CreateUpdateMap(); // Now upgrade the existing workflow to the new workflow definition UpgradeExistingWorkflow(id, map); // Now run the existing workflow, which is now using the new workflow definition LoadAndRunWorkflow(id); }
public LoadAsyncResult(WorkflowApplication application, PersistenceManager persistenceManager, IDictionary <XName, InstanceValue> values, DynamicUpdateMap updateMap, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.application = application; this.persistenceManager = persistenceManager; this.values = values; this.timeoutHelper = new TimeoutHelper(timeout); this.updateMap = updateMap; this.Initialize(); }
static IDictionary <WorkflowIdentity, DynamicUpdateInfo> LoadMaps() { // There are 3 update maps to describe the changes to update v1 workflows, // one for reach of the 3 workflow types in the tutorial. Dictionary <WorkflowIdentity, DynamicUpdateInfo> maps = new Dictionary <WorkflowIdentity, DynamicUpdateInfo>(); DynamicUpdateMap sequentialMap = LoadMap("SequentialNumberGuessWorkflow.map"); DynamicUpdateInfo sequentialInfo = new DynamicUpdateInfo { updateMap = sequentialMap, newIdentity = WorkflowVersionMap.SequentialNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.SequentialNumberGuessIdentity_v1, sequentialInfo); DynamicUpdateMap stateMap = LoadMap("StateMachineNumberGuessWorkflow.map"); DynamicUpdateInfo stateInfo = new DynamicUpdateInfo { updateMap = stateMap, newIdentity = WorkflowVersionMap.StateMachineNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.StateMachineNumberGuessIdentity_v1, stateInfo); DynamicUpdateMap flowchartMap = LoadMap("FlowchartNumberGuessWorkflow.map"); DynamicUpdateInfo flowchartInfo = new DynamicUpdateInfo { updateMap = flowchartMap, newIdentity = WorkflowVersionMap.FlowchartNumberGuessIdentity_v15 }; maps.Add(WorkflowVersionMap.FlowchartNumberGuessIdentity_v1, flowchartInfo); return(maps); }
public static WorkflowServiceInstance InitializeInstance(PersistenceContext persistenceContext, Guid instanceId, Activity workflowDefinition, WorkflowIdentity definitionIdentity, IDictionary<XName, InstanceValue> loadedObject, WorkflowCreationContext creationContext, SynchronizationContext synchronizationContext, WorkflowServiceHost serviceHost, DynamicUpdateMap updateMap = null) { Fx.Assert(workflowDefinition != null, "workflowDefinition cannot be null."); Fx.Assert(serviceHost != null, "serviceHost cannot be null!"); Fx.Assert(instanceId != Guid.Empty, "instanceId cannot be empty."); WorkflowServiceInstance workflowInstance = new WorkflowServiceInstance(workflowDefinition, definitionIdentity, instanceId, serviceHost, persistenceContext) { SynchronizationContext = synchronizationContext }; // let us initalize the instance level extensions here workflowInstance.SetupExtensions(serviceHost.WorkflowExtensions); if (loadedObject != null) { InstanceValue stateValue; object deserializedRuntimeState; if (!loadedObject.TryGetValue(WorkflowNamespace.Workflow, out stateValue) || stateValue.Value == null) { throw FxTrace.Exception.AsError( new InstancePersistenceException(SR.WorkflowInstanceNotFoundInStore(instanceId))); } deserializedRuntimeState = stateValue.Value; if (loadedObject.TryGetValue(WorkflowServiceNamespace.CreationContext, out stateValue)) { workflowInstance.creationContext = (WorkflowCreationContext)stateValue.Value; } if (persistenceContext.IsSuspended) { workflowInstance.state = State.Suspended; } try { workflowInstance.Initialize(deserializedRuntimeState, updateMap); } catch (InstanceUpdateException) { // Need to flush the tracking record for the update failure workflowInstance.ScheduleAbortTracking(true); throw; } if (updateMap != null) { workflowInstance.HasBeenUpdated = true; } } else { IList<Handle> rootExecutionProperties = null; IDictionary<string, object> workflowArguments = null; // Provide default CorrelationScope if root activity is not CorrelationScope if (!(workflowDefinition is CorrelationScope)) { rootExecutionProperties = new List<Handle>(1) { new CorrelationHandle() }; } if (creationContext != null) { workflowArguments = creationContext.RawWorkflowArguments; workflowInstance.creationContext = creationContext; } workflowInstance.Initialize(workflowArguments, rootExecutionProperties); } return workflowInstance; }
public bool CanApplyUpdate(DynamicUpdateMap updateMap, out IList<ActivityBlockingUpdate> activitiesBlockingUpdate) { if (updateMap == null) { throw FxTrace.Exception.ArgumentNull("updateMap"); } activitiesBlockingUpdate = WorkflowApplication.GetActivitiesBlockingUpdate(this, updateMap); return activitiesBlockingUpdate == null || activitiesBlockingUpdate.Count == 0; }
public DynamicUpdateMapExtension(DynamicUpdateMap updateMap) { this.content = new NetDataContractXmlSerializable <DynamicUpdateMap>(updateMap); }
private static bool CanCompensationOrConfirmationHandlerReferenceAddedSymbols(InstanceList instanceList, DynamicUpdateMap rootUpdateMap, IdSpace rootIdSpace, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { for (int j = 0; j < instanceList.Count; j++) { ActivityInstance activityInstance = instanceList[j] as ActivityInstance; if (activityInstance == null || !IsNonDefaultSecondaryRoot(activityInstance, secondaryRootInstances)) { continue; } // here, find out if the given non-default secondary root references an environment to which a symbol is to be added via DU. // we start from a secondary root instead of starting from the enviroment with the already completed owner that was added symbols. // It is becuase for the case of adding symbols to noSymbols activities, the environment doesn't even exist from which we can start looking for referencing secondary root. int[] secondaryRootOriginalQID = new QualifiedId(instanceList.ActivityId).AsIDArray(); Fx.Assert(secondaryRootOriginalQID != null && secondaryRootOriginalQID.Length > 1, "CompensationParticipant is always an implementation child of a CompensableActivity, therefore it's IdSpace must be at least one level deep."); int[] parentOfSecondaryRootOriginalQID = new int[secondaryRootOriginalQID.Length - 1]; Array.Copy(secondaryRootOriginalQID, parentOfSecondaryRootOriginalQID, secondaryRootOriginalQID.Length - 1); List <int> currentQIDBuilder = new List <int>(); for (int i = 0; i < parentOfSecondaryRootOriginalQID.Length; i++) { // // for each iteration of this for-loop, // we are finding out if at every IdSpace level the map has any map entry whose activity has the CompensableActivity as an implementation decendant. // The map may not exist for every IdSpace between the root and the CompensableActivity. // If the matching map and the entry is found, then we find out if that matching entry's activity is a public decendant of any NoSymbols activity DU is to add variables or arguments to. // // This walk on the definition activity tree determines the hypothetical execution-time chain of instances and environments. // The ultimate goal is to prevent adding variables or arguments to a NoSymbols activity which has already completed, // but its decendant CompensableActivity's compensation or confirmation handlers in the future may need to reference the added variables or arguments. currentQIDBuilder.Add(parentOfSecondaryRootOriginalQID[i]); DynamicUpdateMap.UpdatedActivity updatedActivity = rootUpdateMap.GetUpdatedActivity(new QualifiedId(currentQIDBuilder.ToArray()), rootIdSpace); if (updatedActivity.MapEntry != null) { // the activity of this entry either has the CompensableActivity as an implementation decendant, or is the CompensableActivity itself. // walk the same-IdSpace-parent chain of the entry, // look for an entry whose EnvironmentUpdateMap.IsAdditionToNoSymbols is true. DynamicUpdateMapEntry entry = updatedActivity.MapEntry; do { if (!entry.IsRemoval && entry.HasEnvironmentUpdates && entry.EnvironmentUpdateMap.IsAdditionToNoSymbols) { int[] noSymbolAddActivityIDArray = currentQIDBuilder.ToArray(); noSymbolAddActivityIDArray[noSymbolAddActivityIDArray.Length - 1] = entry.OldActivityId; QualifiedId noSymbolAddActivityQID = new QualifiedId(noSymbolAddActivityIDArray); DynamicUpdateMap.UpdatedActivity noSymbolAddUpdatedActivity = rootUpdateMap.GetUpdatedActivity(noSymbolAddActivityQID, rootIdSpace); AddBlockingActivity(ref updateErrors, noSymbolAddUpdatedActivity, noSymbolAddActivityQID, SR.VariableOrArgumentAdditionToReferencedEnvironmentNoDUSupported, null); return(true); } entry = entry.Parent; } while (entry != null); } } } return(false); }
public DynamicUpdateMapExtension(DynamicUpdateMap updateMap) { this.content = new NetDataContractXmlSerializable<DynamicUpdateMap>(updateMap); }
internal static EnvironmentUpdateMap Merge(EnvironmentUpdateMap first, EnvironmentUpdateMap second, DynamicUpdateMap.MergeErrorContext errorContext) { if (first == null || second == null) { return first ?? second; } ThrowIfMapsIncompatible(first, second, errorContext); EnvironmentUpdateMap result = new EnvironmentUpdateMap { OldArgumentCount = first.OldArgumentCount, NewArgumentCount = second.NewArgumentCount, OldVariableCount = first.OldVariableCount, NewVariableCount = second.NewVariableCount, OldPrivateVariableCount = first.OldPrivateVariableCount, NewPrivateVariableCount = second.NewPrivateVariableCount, }; result.variableEntries = Merge(result.NewVariableCount, first.VariableEntries, second.VariableEntries); result.privateVariableEntries = Merge(result.NewPrivateVariableCount, first.PrivateVariableEntries, second.PrivateVariableEntries); result.argumentEntries = Merge(result.NewArgumentCount, first.ArgumentEntries, second.ArgumentEntries); if (result.OldArgumentCount != result.NewArgumentCount || result.OldVariableCount != result.NewVariableCount || result.OldPrivateVariableCount != result.NewPrivateVariableCount || result.HasArgumentEntries || result.HasVariableEntries || result.HasPrivateVariableEntries) { return result; } else { return null; } }
static void ThrowIfMapsIncompatible(EnvironmentUpdateMap first, EnvironmentUpdateMap second, DynamicUpdateMap.MergeErrorContext errorContext) { if (first.NewArgumentCount != second.OldArgumentCount || first.NewVariableCount != second.OldVariableCount || first.NewPrivateVariableCount != second.OldPrivateVariableCount) { errorContext.Throw(SR.InvalidMergeMapEnvironmentCount( first.NewArgumentCount, first.NewVariableCount, first.NewPrivateVariableCount, second.OldArgumentCount, second.OldVariableCount, second.OldPrivateVariableCount)); } }
internal static DynamicUpdateMapEntry Merge(DynamicUpdateMapEntry first, DynamicUpdateMapEntry second, DynamicUpdateMapEntry newParent, DynamicUpdateMap.MergeErrorContext errorContext) { Fx.Assert(first.NewActivityId == second.OldActivityId, "Merging mismatched entries"); Fx.Assert((first.Parent == null && second.Parent == null) || (first.Parent.NewActivityId == second.Parent.OldActivityId), "Merging mismatched parents"); DynamicUpdateMapEntry result = new DynamicUpdateMapEntry(first.OldActivityId, second.NewActivityId) { Parent = newParent }; if (second.IsRemoval) { if (!result.IsParentRemovedOrBlocked) { result.DisplayName = second.DisplayName; } } else { result.SavedOriginalValues = Merge(first.SavedOriginalValues, second.SavedOriginalValues); result.SavedOriginalValueFromParent = first.SavedOriginalValueFromParent ?? second.SavedOriginalValueFromParent; if (first.BlockReason == UpdateBlockedReason.NotBlocked) { result.BlockReason = second.BlockReason; result.BlockReasonMessage = second.BlockReasonMessage; } else { result.BlockReason = first.BlockReason; result.BlockReasonMessage = second.BlockReasonMessage; } result.IsUpdateBlockedByUpdateAuthor = first.IsUpdateBlockedByUpdateAuthor || second.IsUpdateBlockedByUpdateAuthor; errorContext.PushIdSpace(result.NewActivityId); result.EnvironmentUpdateMap = EnvironmentUpdateMap.Merge(first.EnvironmentUpdateMap, second.EnvironmentUpdateMap, errorContext); if (!result.IsRuntimeUpdateBlocked && !result.IsUpdateBlockedByUpdateAuthor && !result.IsParentRemovedOrBlocked) { result.ImplementationUpdateMap = DynamicUpdateMap.Merge(first.ImplementationUpdateMap, second.ImplementationUpdateMap, errorContext); } errorContext.PopIdSpace(); }; return result; }
// targetDefinition argument is optional. private IList <InstanceListNeedingUpdate> GetInstanceListsNeedingUpdate(DynamicUpdateMap updateMap, Activity targetDefinition, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { IList <InstanceListNeedingUpdate> instanceListsToUpdate = new List <InstanceListNeedingUpdate>(); if (this.rawDeserializedLists == null) { // This instance doesn't have any active instances (it is complete). return(instanceListsToUpdate); } IdSpace rootIdSpace = null; if (targetDefinition != null) { rootIdSpace = targetDefinition.MemberOf; } for (int i = 0; i < this.rawDeserializedLists.Length; i++) { InstanceList list = this.rawDeserializedLists[i]; QualifiedId oldQualifiedId = new QualifiedId(list.ActivityId); if (updateMap.IsImplementationAsRoot) { int[] oldIdArray = oldQualifiedId.AsIDArray(); if (oldIdArray.Length == 1 && oldIdArray[0] != 1) { throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidImplementationAsWorkflowRootForRuntimeState)); } } string error; InstanceListNeedingUpdate update; DynamicUpdateMap.UpdatedActivity updatedActivity = updateMap.GetUpdatedActivity(oldQualifiedId, rootIdSpace); if (CanCompensationOrConfirmationHandlerReferenceAddedSymbols(list, updateMap, rootIdSpace, secondaryRootInstances, ref updateErrors)) { update = null; } else if (updatedActivity.MapEntry == null) { if (updatedActivity.IdChanged) { // this newQualifiedId is the new id for those InstanceLists whose IDs shifted by their parents' ID change update = new InstanceListNeedingUpdate { InstanceList = list, NewId = updatedActivity.NewId }; } else { // nothing changed, no map, no mapEntry update = new InstanceListNeedingUpdate { InstanceList = list, NewId = null, }; } } else if (updatedActivity.MapEntry.IsParentRemovedOrBlocked) { update = null; } else if (IsRemovalOrRTUpdateBlockedOrBlockedByUser(updatedActivity, oldQualifiedId, out error)) { string instanceId = null; for (int j = 0; j < list.Count; j++) { ActivityInstance activityInstance = list[j] as ActivityInstance; if (activityInstance != null) { instanceId = activityInstance.Id; break; } } AddBlockingActivity(ref updateErrors, updatedActivity, oldQualifiedId, error, instanceId); update = null; } else if (IsInvalidEnvironmentUpdate(list, updatedActivity, ref updateErrors)) { update = null; } else { // no validation error for this InstanceList // add it to the list of InstanceLists to be updated update = new InstanceListNeedingUpdate { InstanceList = list, NewId = updatedActivity.NewId, UpdateMap = updatedActivity.Map, MapEntry = updatedActivity.MapEntry, NewActivity = updatedActivity.NewActivity }; } if (update != null) { update.OriginalId = list.ActivityId; instanceListsToUpdate.Add(update); } } return(instanceListsToUpdate); }
private void cmdUpdateInstance_Click(object sender, RoutedEventArgs e) { SqlWorkflowInstanceStore instanceStore = new SqlWorkflowInstanceStore(); instanceStore.ConnectionString = @"Data Source=(LocalDB)\v11.0;Initial Catalog=WFPersist;Integrated Security=True"; WorkflowApplicationInstance wfInstance = WorkflowApplication.GetInstance(new Guid(txtUpdateInstance.Text), instanceStore); DataContractSerializer s = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = File.Open(txtUpdateMapFile.Text, FileMode.Open)) { updateMap = s.ReadObject(fs) as DynamicUpdateMap; } var wfApp = new WorkflowApplication(new MovieRentalProcess(), new WorkflowIdentity { Name = "v2MovieRentalProcess", Version = new System.Version(2, 0, 0, 0) }); IList<ActivityBlockingUpdate> act; if (wfInstance.CanApplyUpdate(updateMap, out act)) { wfApp.Load(wfInstance, updateMap); wfApp.Unload(); } }
public void SaveUpdateMap(DynamicUpdateMap map, string fileName) { var path = System.IO.Path.ChangeExtension(fileName, "map"); DataContractSerializer serialize = new DataContractSerializer(typeof(DynamicUpdateMap)); using (FileStream fs = File.Open(path, FileMode.Create)) { serialize.WriteObject(fs, map); } txtUpdateMapFile.Text = path; }
public static void SetImplementationMap(Activity targetActivity, DynamicUpdateMap implementationMap) { if (implementationMap != null) { AttachablePropertyServices.SetProperty(targetActivity, implementationMapProperty, implementationMap); } else { AttachablePropertyServices.RemoveProperty(targetActivity, implementationMapProperty); } }
// this is called after all instances have been loaded and fixedup public void UpdateInstanceByActivityParticipation(ActivityExecutor activityExecutor, DynamicUpdateMap rootMap, ref Collection <ActivityBlockingUpdate> updateErrors) { foreach (InstanceListNeedingUpdate participant in this.updateList) { if (participant.NothingChanged || participant.ParentIdShiftOnly) { Fx.Assert(participant.UpdateMap == null && participant.MapEntry == null, "UpdateMap and MapEntry must be null if we are here."); // create a temporary NoChanges UpdateMap as well as a temporary no change MapEntry // so that we can create a NativeActivityUpdateContext object in order to invoke UpdateInstance() on an activity which // doesn't have a corresponding map and an map entry. // The scenario enabled here is scheduling a newly added reference branch to a Parallel inside an activity's implementation. participant.UpdateMap = DynamicUpdateMap.DummyMap; participant.MapEntry = DynamicUpdateMapEntry.DummyMapEntry; } // now let activities participate in update for (int i = 0; i < participant.InstanceList.Count; i++) { ActivityInstance instance = participant.InstanceList[i] as ActivityInstance; if (instance == null) { continue; } IInstanceUpdatable activity = instance.Activity as IInstanceUpdatable; if (activity != null && instance.SubState == ActivityInstance.Substate.Executing) { NativeActivityUpdateContext updateContext = new NativeActivityUpdateContext(this, activityExecutor, instance, participant.UpdateMap, participant.MapEntry, rootMap); try { activity.InternalUpdateInstance(updateContext); if (updateContext.IsUpdateDisallowed) { ActivityBlockingUpdate.AddBlockingActivity(ref updateErrors, instance.Activity, new QualifiedId(participant.OriginalId).ToString(), updateContext.DisallowedReason, instance.Id); continue; } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.NativeActivityUpdateInstanceThrewException(e.Message), e)); } finally { updateContext.Dispose(); } } } } // Schedule evaluation of newly added arguments and newly added variables. // This needs to happen after all the invokations of UpdateInstance above, so that newly // added arguments and newly added variables get evaluated before any newly added activities get executed. // We iterate the list in reverse so that parents are always scheduled after (and thus // execute before) their children, which may depend on the parents. for (int i = this.updateList.Count - 1; i >= 0; i--) { InstanceListNeedingUpdate participant = this.updateList[i]; if (!participant.MapEntryExists) { // if the given InstanceList has no map entry, // then there is no new LocationReferences to resolve. continue; } Fx.Assert(participant.MapEntry != null, "MapEntry must be non-null here."); if (!participant.MapEntry.HasEnvironmentUpdates) { // if there is no environment updates for this MapEntry, // then there is no new LocationReferences to resolve. continue; } for (int j = 0; j < participant.InstanceList.Count; j++) { ActivityInstance instance = participant.InstanceList[j] as ActivityInstance; if (instance == null || instance.SubState != ActivityInstance.Substate.Executing) { // if the given ActivityInstance is not in Substate.Executing, // then, do not try to resolve new LocationReferences continue; } List <int> addedArgumentIndexes; List <int> addedVariableIndexes; List <int> addedPrivateVariableIndexes; EnvironmentUpdateMap envMap = participant.MapEntry.EnvironmentUpdateMap; if (envMap.HasVariableEntries && TryGatherSchedulableExpressions(envMap.VariableEntries, out addedVariableIndexes)) { // schedule added variable default expressions instance.ResolveNewVariableDefaultsDuringDynamicUpdate(activityExecutor, addedVariableIndexes, false); } if (envMap.HasPrivateVariableEntries && TryGatherSchedulableExpressions(envMap.PrivateVariableEntries, out addedPrivateVariableIndexes)) { // schedule added private variable default expressions // HasPrivateMemberChanged() check disallows addition of private variable default that offsets the private IdSpace, // However, the added private variable default expression can be an imported activity, which has no affect on the private IdSpace. // For such case, we want to be able to schedule the imported default expressions here. instance.ResolveNewVariableDefaultsDuringDynamicUpdate(activityExecutor, addedPrivateVariableIndexes, true); } if (envMap.HasArgumentEntries && TryGatherSchedulableExpressions(envMap.ArgumentEntries, out addedArgumentIndexes)) { // schedule added arguments instance.ResolveNewArgumentsDuringDynamicUpdate(activityExecutor, addedArgumentIndexes); } } } }
public void GetActivitiesBlockingUpdate(DynamicUpdateMap updateMap, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { this.GetInstanceListsNeedingUpdate(updateMap, null, secondaryRootInstances, ref updateErrors); }
protected void Initialize(object deserializedRuntimeState, DynamicUpdateMap updateMap) { ThrowIfAborted(); ThrowIfReadOnly(); this.executor = deserializedRuntimeState as ActivityExecutor; if (this.executor == null) { throw FxTrace.Exception.Argument("deserializedRuntimeState", SR.InvalidRuntimeState); } this.executor.ThrowIfNonSerializable(); EnsureDefinitionReady(); WorkflowIdentity originalDefinitionIdentity = this.executor.WorkflowIdentity; bool success = false; Collection <ActivityBlockingUpdate> updateErrors = null; try { if (updateMap != null) { // check if map is for implementaiton, if (updateMap.IsForImplementation) { // if so, the definition root must be an activity // with no public/imported children and no public/imported delegates. if (DynamicUpdateMap.CanUseImplementationMapAsRoot(this.WorkflowDefinition)) { updateMap = updateMap.AsRootMap(); } else { throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidImplementationAsWorkflowRoot)); } } updateMap.ThrowIfInvalid(this.WorkflowDefinition); this.executor.WorkflowIdentity = this.DefinitionIdentity; this.executor.UpdateInstancePhase1(updateMap, this.WorkflowDefinition, ref updateErrors); ThrowIfDynamicUpdateErrorExists(updateErrors); } InitializeCore(null, null); if (updateMap != null) { this.executor.UpdateInstancePhase2(updateMap, ref updateErrors); ThrowIfDynamicUpdateErrorExists(updateErrors); // Track that dynamic update is successful if (this.Controller.TrackingEnabled) { this.Controller.Track(new WorkflowInstanceUpdatedRecord(this.Id, this.WorkflowDefinition.DisplayName, originalDefinitionIdentity, this.executor.WorkflowIdentity)); } } success = true; } catch (InstanceUpdateException updateException) { // Can't track through the controller because initialization failed if (this.HasTrackingParticipant && this.TrackingProvider.ShouldTrackWorkflowInstanceRecords) { IList <ActivityBlockingUpdate> blockingActivities = updateException.BlockingActivities; if (blockingActivities.Count == 0) { blockingActivities = new List <ActivityBlockingUpdate> { new ActivityBlockingUpdate(this.WorkflowDefinition, this.WorkflowDefinition.Id, updateException.Message) }.AsReadOnly(); } this.TrackingProvider.AddRecord(new WorkflowInstanceUpdatedRecord(this.Id, this.WorkflowDefinition.DisplayName, originalDefinitionIdentity, this.DefinitionIdentity, blockingActivities)); } throw; } finally { if (updateMap != null && !success) { executor.MakeNonSerializable(); } } }
public bool TryGetDefinitionAndMap(WorkflowIdentity currentIdentity, WorkflowIdentity updatedIdentity, out Activity workflowDefinition, out DynamicUpdateMap updateMap) { WorkflowService workflowService; if (object.Equals(updatedIdentity, this.DefaultDefinitionIdentity)) { workflowService = this.defaultWorkflowService; } else { this.definitionCollection.TryGetValue(new WorkflowIdentityKey(updatedIdentity), out workflowService); } if (workflowService != null && workflowService.UpdateMaps.TryGetValue(currentIdentity, out updateMap) && updateMap != null) { workflowDefinition = workflowService.Body; return(true); } workflowDefinition = null; updateMap = null; return(false); }