Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Filters / CompensationHandlingFilter.cs / 1305376 / CompensationHandlingFilter.cs
namespace System.Workflow.ComponentModel { using System; using System.Collections.Generic; using System.Workflow.ComponentModel.Design; internal class CompensationHandlingFilter : ActivityExecutionFilter, IActivityEventListener{ public static DependencyProperty CompensateProcessedProperty = DependencyProperty.RegisterAttached("CompensateProcessed", typeof(bool), typeof(CompensationHandlingFilter), new PropertyMetadata(false)); internal static DependencyProperty LastCompensatedOrderIdProperty = DependencyProperty.RegisterAttached("LastCompensatedOrderId", typeof(int), typeof(CompensationHandlingFilter), new PropertyMetadata(false)); #region Compensate Signal public override ActivityExecutionStatus Compensate(Activity activity, ActivityExecutionContext executionContext) { if (activity == null) throw new ArgumentNullException("activity"); if (executionContext == null) throw new ArgumentNullException("executionContext"); executionContext.Activity.HoldLockOnStatusChange(this); return NextActivityExecutorInChain(activity).Compensate(activity, executionContext); } #endregion #region IActivityEventListener Members void IActivityEventListener .OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e) { ActivityExecutionContext context = sender as ActivityExecutionContext; if (context == null) throw new ArgumentException("sender"); if (e.Activity == context.Activity) { if (context.Activity.HasPrimaryClosed && !(bool)context.Activity.GetValue(CompensateProcessedProperty)) { context.Activity.SetValue(CompensateProcessedProperty, true); if (context.Activity.ExecutionResult == ActivityExecutionResult.Compensated) { // run compensation handler or do default compensation handling Activity compensationHandler = GetCompensationHandler(context.Activity); if (compensationHandler != null) { // subscribe for status change on compensation handler compensationHandler.RegisterForStatusChange(Activity.ClosedEvent, this); // execute compensation handler context.ExecuteActivity(compensationHandler); } else { // do default compensation if (!CompensationUtils.TryCompensateLastCompletedChildActivity(context, context.Activity, this)) { // let activity get into closed state context.Activity.ReleaseLockOnStatusChange(this); } } } else { // let activity get into closed state context.Activity.ReleaseLockOnStatusChange(this); } } } else if (e.Activity is CompensationHandlerActivity && e.ExecutionStatus == ActivityExecutionStatus.Closed) { // remove subscriber for status change on compensation handler e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this); // release lock on the primary activity context.Activity.ReleaseLockOnStatusChange(this); } else if (e.ExecutionStatus == ActivityExecutionStatus.Closed) { // remove subscriber for status change on compensated activity e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this); if (!CompensationUtils.TryCompensateLastCompletedChildActivity(context, context.Activity, this)) { // release lock on the primary activity context.Activity.ReleaseLockOnStatusChange(this); } } } #endregion #region Helper Methods internal static Activity GetCompensationHandler(Activity activityWithCompensation) { Activity compensationHandler = null; CompositeActivity compositeActivity = activityWithCompensation as CompositeActivity; if (compositeActivity != null) { foreach (Activity activity in ((ISupportAlternateFlow)compositeActivity).AlternateFlowActivities) { if (activity is CompensationHandlerActivity) { compensationHandler = activity; break; } } } return compensationHandler; } #endregion } #region CompensationUtils internal static class CompensationUtils { internal static bool TryCompensateLastCompletedChildActivity(ActivityExecutionContext context, Activity targetActivity, IActivityEventListener statusChangeHandler) { try { return TryCompensateLastCompletedChildActivity(context, targetActivity, statusChangeHandler, true); } catch (Exception) { //If root compensation failed. then flush Execution Contexts, which we opened //up now. if(targetActivity.Parent == null) CompleteRevokedExecutionContext(targetActivity, context); throw; } } private static bool TryCompensateLastCompletedChildActivity(ActivityExecutionContext context, Activity targetActivity, IActivityEventListener statusChangeHandler, bool isimmediateCompensation) { SortedDictionary sortedListOfCompensatableTargets = new SortedDictionary (); if (!(targetActivity is CompositeActivity)) return false; //Walk through all of the direct children which are compensatable and add them in the sorted order of their completion //bail out if any of the compensatable children is currently compensating/faulting or canceling if (CollectCompensatableTargetActivities(targetActivity as CompositeActivity, sortedListOfCompensatableTargets, isimmediateCompensation)) return true; // walk through active contexts that contain compensatable child, add them in the sorted order of the completion // this also, walks through the completed contexts which are compensatable and are nested directly within the active contexts and adds them in the order of their completion // bail out if any activity is currently compensating/faulting or cancelling if (CollectCompensatableActiveContexts(context, targetActivity, sortedListOfCompensatableTargets, isimmediateCompensation)) return true; // walk through all completed execution contexts which are compensatable and are directly nested under the target activity, //and add them to our sorted list CollectCompensatableCompletedContexts(context, targetActivity, sortedListOfCompensatableTargets, isimmediateCompensation); //if there were no compensatable targets found, bail out if (sortedListOfCompensatableTargets.Count == 0) { CompleteRevokedExecutionContext(targetActivity, context); return false; } int? lastCompletedOrderId = targetActivity.GetValue(CompensationHandlingFilter.LastCompensatedOrderIdProperty) as Nullable ; int nextLastCompletedOrderId = -1; //get the last compensatable target - this could be an activity, contextInfo or a Context CompensationInfo lastCompensatableTarget = null; foreach(int completedOrderId in sortedListOfCompensatableTargets.Keys) { if (lastCompletedOrderId.HasValue && lastCompletedOrderId < completedOrderId) break; lastCompensatableTarget = sortedListOfCompensatableTargets[completedOrderId]; nextLastCompletedOrderId = completedOrderId; } //We are done with compensation on entire branch, now complete execution contexts //recursilvely which we might have opened up. if (lastCompensatableTarget == null) { CompleteRevokedExecutionContext(targetActivity, context); return false; } targetActivity.SetValue(CompensationHandlingFilter.LastCompensatedOrderIdProperty, nextLastCompletedOrderId); //the last compensatable target could be an activity if (lastCompensatableTarget.TargetActivity != null && lastCompensatableTarget.TargetActivity is ICompensatableActivity) { lastCompensatableTarget.TargetActivity.RegisterForStatusChange(Activity.StatusChangedEvent, statusChangeHandler); context.CompensateActivity(lastCompensatableTarget.TargetActivity); return true; } //or get the last compensatable "completed" context else if (lastCompensatableTarget.TargetExecutionInfo != null && lastCompensatableTarget.TargetExecutionContextManager != null) { ActivityExecutionContext revokedExecutionContext = lastCompensatableTarget.TargetExecutionContextManager.DiscardPersistedExecutionContext(lastCompensatableTarget.TargetExecutionInfo); //get the "first" compensatable child and compensate it if (revokedExecutionContext.Activity is ICompensatableActivity) { revokedExecutionContext.Activity.RegisterForStatusChange(Activity.StatusChangedEvent, statusChangeHandler); revokedExecutionContext.CompensateActivity(revokedExecutionContext.Activity); return true; } else if (revokedExecutionContext.Activity is CompositeActivity) { //get the last compensatable child of the revoked context Activity compensatableChild = GetLastCompensatableChild(revokedExecutionContext.Activity as CompositeActivity); if (compensatableChild != null) { compensatableChild.RegisterForStatusChange(Activity.StatusChangedEvent, statusChangeHandler); revokedExecutionContext.CompensateActivity(compensatableChild); return true; } else// recursively, walk the context tree and keep revoking the compensatable contexts return TryCompensateLastCompletedChildActivity(revokedExecutionContext, revokedExecutionContext.Activity, statusChangeHandler, false); } } else if (lastCompensatableTarget.TargetExecutionContext != null) //or get the last compensatable "active" context { if (lastCompensatableTarget.TargetExecutionContext.Activity is CompositeActivity) { //get the last compensatable child of the active context Activity compensatableChild = GetLastCompensatableChild(lastCompensatableTarget.TargetExecutionContext.Activity as CompositeActivity); if (compensatableChild != null) { compensatableChild.RegisterForStatusChange(Activity.StatusChangedEvent, statusChangeHandler); lastCompensatableTarget.TargetExecutionContext.CompensateActivity(compensatableChild); return true; } else // recursively, walk the context tree and keep revoking the compensatable contexts return TryCompensateLastCompletedChildActivity(lastCompensatableTarget.TargetExecutionContext, lastCompensatableTarget.TargetExecutionContext.Activity, statusChangeHandler, false); } } return false; } private static void CompleteRevokedExecutionContext(Activity targetActivity, ActivityExecutionContext context) { ActivityExecutionContext[] activeContextsClone = new ActivityExecutionContext[context.ExecutionContextManager.ExecutionContexts.Count]; context.ExecutionContextManager.ExecutionContexts.CopyTo(activeContextsClone, 0); foreach (ActivityExecutionContext childContext in activeContextsClone) { if (targetActivity.GetActivityByName(childContext.Activity.QualifiedName, true) != null) { if (childContext.Activity.ExecutionStatus == ActivityExecutionStatus.Closed) CompleteRevokedExecutionContext(childContext.Activity, childContext); context.ExecutionContextManager.CompleteExecutionContext(childContext); } } } #region helpers private sealed class CompensationInfo { private Activity targetActivity = null; private ActivityExecutionContext targetExecutionContext = null; private ActivityExecutionContextInfo targetExecutionInfo = null; private ActivityExecutionContextManager targetExecutionContextManager = null; internal CompensationInfo(ActivityExecutionContextInfo targetExecutionInfo, ActivityExecutionContextManager targetExecutionContextManager) { this.targetExecutionInfo = targetExecutionInfo; this.targetExecutionContextManager = targetExecutionContextManager; } internal CompensationInfo(Activity targetActivity) { this.targetActivity = targetActivity; } internal CompensationInfo(ActivityExecutionContext targetExecutionContext) { this.targetExecutionContext = targetExecutionContext; } internal Activity TargetActivity { get { return targetActivity; } } internal ActivityExecutionContext TargetExecutionContext { get { return targetExecutionContext; } } internal ActivityExecutionContextInfo TargetExecutionInfo { get { return targetExecutionInfo; } } internal ActivityExecutionContextManager TargetExecutionContextManager { get { return targetExecutionContextManager; } } } //Walk through all of the direct children which are compensatable and add them in the sorted order of their completion //bail out if any of the compensatable children is currently compensating/faulting or canceling private static bool CollectCompensatableTargetActivities(CompositeActivity compositeActivity, SortedDictionary sortedListOfCompensatableTargets, bool immediateCompensation) { // walk through all compensatable children and compensate them Queue completedActivities = new Queue (Helpers.GetAllEnabledActivities(compositeActivity)); while (completedActivities.Count > 0) { Activity completedChild = completedActivities.Dequeue(); if (completedChild.ExecutionStatus == ActivityExecutionStatus.Compensating || completedChild.ExecutionStatus == ActivityExecutionStatus.Faulting || completedChild.ExecutionStatus == ActivityExecutionStatus.Canceling) return true; //Don't walk activities which are part of reverse work of target activity. if (immediateCompensation && IsActivityInBackWorkBranch(compositeActivity, completedChild)) continue; if (completedChild is ICompensatableActivity && completedChild.ExecutionStatus == ActivityExecutionStatus.Closed && completedChild.ExecutionResult == ActivityExecutionResult.Succeeded) sortedListOfCompensatableTargets.Add((int)completedChild.GetValue(Activity.CompletedOrderIdProperty), new CompensationInfo(completedChild)); else if (completedChild is CompositeActivity) { foreach (Activity nestedCompletedActivity in Helpers.GetAllEnabledActivities((CompositeActivity)completedChild)) completedActivities.Enqueue(nestedCompletedActivity); } } return false; } // walk through active contexts that contain compensatable child, add them in the sorted order of the completion // this also, walks through the completed contexts which are compensatable and are nested directly within the active contexts and adds them in the order of their completion // bail out if any activity is currently compensating/faulting or cancelling private static bool CollectCompensatableActiveContexts(ActivityExecutionContext context, Activity targetActivity, SortedDictionary sortedListOfCompensatableTargets, bool immediateCompensation) { ActivityExecutionContextManager contextManager = context.ExecutionContextManager; foreach (ActivityExecutionContext activeContext in contextManager.ExecutionContexts) { if (targetActivity.GetActivityByName(activeContext.Activity.QualifiedName, true) != null) { //Dont walk context which are part of reverse work. if (immediateCompensation && IsActivityInBackWorkBranch(targetActivity, activeContext.Activity)) continue; if (activeContext.Activity is ICompensatableActivity && (activeContext.Activity.ExecutionStatus == ActivityExecutionStatus.Compensating ||activeContext.Activity.ExecutionStatus == ActivityExecutionStatus.Faulting || activeContext.Activity.ExecutionStatus == ActivityExecutionStatus.Canceling)) return true; else if (activeContext.Activity is CompositeActivity) { Activity[] activities = GetCompensatableChildren(activeContext.Activity as CompositeActivity); if (activities != null) { int lastcompletedContextOrderId = 0; foreach (Activity childActivity in activities) { int completedOrderId = (int)childActivity.GetValue(Activity.CompletedOrderIdProperty); if (lastcompletedContextOrderId < completedOrderId) lastcompletedContextOrderId = completedOrderId; } if (lastcompletedContextOrderId != 0) sortedListOfCompensatableTargets.Add(lastcompletedContextOrderId, new CompensationInfo(activeContext)); } CollectCompensatableActiveContexts(activeContext, targetActivity, sortedListOfCompensatableTargets, immediateCompensation); CollectCompensatableCompletedContexts(activeContext, targetActivity,sortedListOfCompensatableTargets, immediateCompensation); } } } return false; } private static bool IsActivityInBackWorkBranch(Activity targetParent, Activity childActivity) { //Find immediate child in targetParent, which is in path to childActivity. Activity immediateChild = childActivity; while (immediateChild.Parent != targetParent) immediateChild = immediateChild.Parent; return Helpers.IsFrameworkActivity(immediateChild); } // walk through all completed execution contexts which are compensatable and are directly nested under the target activity, //and add them to our sorted list private static void CollectCompensatableCompletedContexts(ActivityExecutionContext context, Activity targetActivity, SortedDictionary sortedListOfCompensatableTargets, bool immediateCompensation) { // walk through all completed execution contexts, add them to our sorted list ActivityExecutionContextManager contextManager = context.ExecutionContextManager; for (int index = contextManager.CompletedExecutionContexts.Count - 1; index >= 0; index--) { //if the context does not have any compensatable children, continue ActivityExecutionContextInfo completedActivityInfo = contextManager.CompletedExecutionContexts[index]; if ((completedActivityInfo.Flags & PersistFlags.NeedsCompensation) == 0) continue; //ok, found a compensatable child. Activity completedActivity = targetActivity.GetActivityByName(completedActivityInfo.ActivityQualifiedName, true); if (completedActivity != null && !(immediateCompensation && IsActivityInBackWorkBranch(targetActivity, completedActivity))) sortedListOfCompensatableTargets.Add(completedActivityInfo.CompletedOrderId, new CompensationInfo(completedActivityInfo, contextManager)); } } internal static Activity[] GetCompensatableChildren(CompositeActivity compositeActivity) { SortedDictionary sortedListOfCompensatableTargets = new SortedDictionary (); Queue completedActivities = new Queue (Helpers.GetAllEnabledActivities(compositeActivity)); while (completedActivities.Count > 0) { Activity completedChild = completedActivities.Dequeue(); if (completedChild is ICompensatableActivity && completedChild.ExecutionStatus == ActivityExecutionStatus.Closed && completedChild.ExecutionResult == ActivityExecutionResult.Succeeded) sortedListOfCompensatableTargets.Add((int)completedChild.GetValue(Activity.CompletedOrderIdProperty), completedChild); else if (completedChild is CompositeActivity) { foreach (Activity nestedCompletedActivity in Helpers.GetAllEnabledActivities((CompositeActivity)completedChild)) completedActivities.Enqueue(nestedCompletedActivity); } } Activity[] ar = new Activity[sortedListOfCompensatableTargets.Count]; sortedListOfCompensatableTargets.Values.CopyTo(ar,0); return ar; } internal static Activity GetLastCompensatableChild(CompositeActivity compositeActivity) { Activity[] activities = CompensationUtils.GetCompensatableChildren(compositeActivity); if (activities != null && activities.Length > 0 && activities[activities.Length - 1] != null) return activities[activities.Length - 1]; return null; } #endregion helpers } #endregion CompensationUtils } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- COM2ExtendedUITypeEditor.cs
- X500Name.cs
- Configuration.cs
- RenameRuleObjectDialog.Designer.cs
- SortKey.cs
- Matrix3DStack.cs
- CompilerGeneratedAttribute.cs
- FloaterBaseParaClient.cs
- CharEntityEncoderFallback.cs
- RowUpdatedEventArgs.cs
- ComMethodElement.cs
- Exceptions.cs
- MimeTypeAttribute.cs
- OracleRowUpdatingEventArgs.cs
- WebPartConnectionsConfigureVerb.cs
- ConfigXmlElement.cs
- SequentialOutput.cs
- NavigateEvent.cs
- HttpModuleAction.cs
- BuildProviderUtils.cs
- HtmlInputFile.cs
- DataGridViewCellValueEventArgs.cs
- DateRangeEvent.cs
- SourceLineInfo.cs
- Latin1Encoding.cs
- CompositionCommandSet.cs
- OleDbCommand.cs
- WinEventWrap.cs
- ProfileSection.cs
- QilStrConcatenator.cs
- TraceRecord.cs
- ReflectionUtil.cs
- ObjectCache.cs
- QilPatternVisitor.cs
- CodePageEncoding.cs
- UpdateExpressionVisitor.cs
- ListControl.cs
- TextModifierScope.cs
- InputMethodStateTypeInfo.cs
- FindSimilarActivitiesVerb.cs
- ToolStripContainer.cs
- SqlMethodCallConverter.cs
- XmlNavigatorStack.cs
- Context.cs
- RuntimeConfigLKG.cs
- AnnotationResource.cs
- ConditionCollection.cs
- NamespaceDisplay.xaml.cs
- CrossAppDomainChannel.cs
- MDIClient.cs
- DrawingVisual.cs
- CompositeDataBoundControl.cs
- BindingObserver.cs
- BaseCollection.cs
- SafeRightsManagementHandle.cs
- OpenTypeLayout.cs
- SerialPinChanges.cs
- glyphs.cs
- EntityContainerEmitter.cs
- Page.cs
- DateTimeConverter2.cs
- Line.cs
- CodeSnippetExpression.cs
- SqlException.cs
- PtsPage.cs
- ImportContext.cs
- StringHelper.cs
- CollaborationHelperFunctions.cs
- RoleGroupCollection.cs
- Focus.cs
- CheckBoxField.cs
- RegexStringValidatorAttribute.cs
- XmlQueryOutput.cs
- MdImport.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- DependentList.cs
- TagMapCollection.cs
- EdmSchemaError.cs
- RouteCollection.cs
- GPPOINTF.cs
- WindowManager.cs
- ToggleButton.cs
- FlowDocumentPaginator.cs
- BindingOperations.cs
- MarshalByRefObject.cs
- Int16Converter.cs
- XmlCharacterData.cs
- UserMapPath.cs
- HexParser.cs
- ParamArrayAttribute.cs
- PointLight.cs
- CodeDirectionExpression.cs
- BamlLocalizerErrorNotifyEventArgs.cs
- DetailsViewPageEventArgs.cs
- SafeSystemMetrics.cs
- ObjectHandle.cs
- ClientRolePrincipal.cs
- StretchValidation.cs
- DataGrid.cs
- XmlValidatingReaderImpl.cs