Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / Tracking / TrackingProvider.cs / 1305376 / TrackingProvider.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.Activities.Tracking { using System; using System.Activities; using System.Collections; using System.Collections.Generic; using System.Runtime; class TrackingProvider { ListtrackingParticipants; Dictionary profileSubscriptions; IList pendingTrackingRecords; Activity definition; bool filterValuesSetExplicitly; Hashtable activitySubscriptions; long nextTrackingRecordNumber; public TrackingProvider(Activity definition) { this.definition = definition; this.ShouldTrack = true; this.ShouldTrackActivityStateRecords = true; this.ShouldTrackActivityStateRecordsExecutingState = true; this.ShouldTrackActivityStateRecordsClosedState = true; this.ShouldTrackBookmarkResumptionRecords = true; this.ShouldTrackActivityScheduledRecords = true; this.ShouldTrackCancelRequestedRecords = true; this.ShouldTrackFaultPropagationRecords = true; this.ShouldTrackWorkflowInstanceRecords = true; } public bool HasPendingRecords { get { return (this.pendingTrackingRecords != null && this.pendingTrackingRecords.Count > 0) || !this.filterValuesSetExplicitly; } } public long NextTrackingRecordNumber { get { return this.nextTrackingRecordNumber; } } public bool ShouldTrack { get; private set; } public bool ShouldTrackWorkflowInstanceRecords { get; private set; } public bool ShouldTrackBookmarkResumptionRecords { get; private set; } public bool ShouldTrackActivityScheduledRecords { get; private set; } public bool ShouldTrackActivityStateRecords { get; private set; } public bool ShouldTrackActivityStateRecordsExecutingState { get; private set; } public bool ShouldTrackActivityStateRecordsClosedState { get; private set; } public bool ShouldTrackCancelRequestedRecords { get; private set; } public bool ShouldTrackFaultPropagationRecords { get; private set; } long GetNextRecordNumber() { // We blindly do this. On the off chance that a workflow causes it to loop back // around it shouldn't cause the workflow to fail and the tracking information // will still be salvagable. return this.nextTrackingRecordNumber++; } public void OnDeserialized(long nextTrackingRecordNumber) { this.nextTrackingRecordNumber = nextTrackingRecordNumber; } public void AddRecord(TrackingRecord record) { if (this.pendingTrackingRecords == null) { this.pendingTrackingRecords = new List (); } record.RecordNumber = GetNextRecordNumber(); this.pendingTrackingRecords.Add(record); } public void AddParticipant(TrackingParticipant participant) { if (this.trackingParticipants == null) { this.trackingParticipants = new List (); this.profileSubscriptions = new Dictionary (); } this.trackingParticipants.Add(participant); } public void FlushPendingRecords(TimeSpan timeout) { try { if (this.HasPendingRecords) { TimeoutHelper helper = new TimeoutHelper(timeout); for (int i = 0; i < this.trackingParticipants.Count; i++) { TrackingParticipant participant = this.trackingParticipants[i]; RuntimeTrackingProfile runtimeProfile = GetRuntimeTrackingProfile(participant); // HasPendingRecords can be true for the sole purpose of populating our initial profiles, so check again here if (this.pendingTrackingRecords != null) { for (int j = 0; j < this.pendingTrackingRecords.Count; j++) { TrackingRecord currentRecord = this.pendingTrackingRecords[j]; Fx.Assert(currentRecord != null, "We should never come across a null context."); TrackingRecord preparedRecord = null; bool shouldClone = this.trackingParticipants.Count > 1; if (runtimeProfile == null) { preparedRecord = shouldClone ? currentRecord.Clone() : currentRecord; } else { preparedRecord = runtimeProfile.Match(currentRecord, shouldClone); } if (preparedRecord != null) { participant.Track(preparedRecord, helper.RemainingTime()); if (TD.TrackingRecordRaisedIsEnabled()) { TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString()); } } } } } } } finally { // Note that if we fail to track yet the workflow manages to recover // we will attempt to track those records again. ClearPendingRecords(); } } public IAsyncResult BeginFlushPendingRecords(TimeSpan timeout, AsyncCallback callback, object state) { return new FlushPendingRecordsAsyncResult(this, timeout, callback, state); } public void EndFlushPendingRecords(IAsyncResult result) { FlushPendingRecordsAsyncResult.End(result); } public bool ShouldTrackActivity(string name) { return this.activitySubscriptions == null || this.activitySubscriptions.ContainsKey(name) || this.activitySubscriptions.ContainsKey("*"); } void ClearPendingRecords() { if (this.pendingTrackingRecords != null) { //since the number of records is small, it is faster to remove from end than to call List.Clear for (int i = this.pendingTrackingRecords.Count - 1; i >= 0; i--) { this.pendingTrackingRecords.RemoveAt(i); } } } RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingParticipant participant) { TrackingProfile profile; RuntimeTrackingProfile runtimeProfile; if (!this.profileSubscriptions.TryGetValue(participant, out runtimeProfile)) { profile = participant.TrackingProfile; if (profile != null) { runtimeProfile = RuntimeTrackingProfile.GetRuntimeTrackingProfile(profile, this.definition); Merge(runtimeProfile.Filter); //Add the names to the list of activities that have subscriptions. This provides a quick lookup //for the runtime to check if a TrackingRecord has to be created. IEnumerable activityNames = runtimeProfile.GetSubscribedActivityNames(); if (activityNames != null) { if (this.activitySubscriptions == null) { this.activitySubscriptions = new Hashtable(); } foreach (string name in activityNames) { if (this.activitySubscriptions[name] == null) { this.activitySubscriptions[name] = name; } } } } else { //for null profiles, set all the filter flags. Merge(new TrackingRecordPreFilter(true)); } this.profileSubscriptions.Add(participant, runtimeProfile); } return runtimeProfile; } void Merge(TrackingRecordPreFilter filter) { if (!this.filterValuesSetExplicitly) { // This it the first filter we are merging this.filterValuesSetExplicitly = true; this.ShouldTrackActivityStateRecordsExecutingState = filter.TrackActivityStateRecordsExecutingState; this.ShouldTrackActivityScheduledRecords = filter.TrackActivityScheduledRecords; this.ShouldTrackActivityStateRecords = filter.TrackActivityStateRecords; this.ShouldTrackActivityStateRecordsClosedState = filter.TrackActivityStateRecordsClosedState; this.ShouldTrackBookmarkResumptionRecords = filter.TrackBookmarkResumptionRecords; this.ShouldTrackCancelRequestedRecords = filter.TrackCancelRequestedRecords; this.ShouldTrackFaultPropagationRecords = filter.TrackFaultPropagationRecords; this.ShouldTrackWorkflowInstanceRecords = filter.TrackWorkflowInstanceRecords; } else { this.ShouldTrackActivityStateRecordsExecutingState |= filter.TrackActivityStateRecordsExecutingState; this.ShouldTrackActivityScheduledRecords |= filter.TrackActivityScheduledRecords; this.ShouldTrackActivityStateRecords |= filter.TrackActivityStateRecords; this.ShouldTrackActivityStateRecordsClosedState |= filter.TrackActivityStateRecordsClosedState; this.ShouldTrackBookmarkResumptionRecords |= filter.TrackBookmarkResumptionRecords; this.ShouldTrackCancelRequestedRecords |= filter.TrackCancelRequestedRecords; this.ShouldTrackFaultPropagationRecords |= filter.TrackFaultPropagationRecords; this.ShouldTrackWorkflowInstanceRecords |= filter.TrackWorkflowInstanceRecords; } } class FlushPendingRecordsAsyncResult : AsyncResult { static AsyncCompletion trackingCompleteCallback = new AsyncCompletion(OnTrackingComplete); int currentRecord; int currentParticipant; TrackingProvider provider; TimeoutHelper timeoutHelper; public FlushPendingRecordsAsyncResult(TrackingProvider provider, TimeSpan timeout, AsyncCallback callback, object state) : base(callback, state) { this.provider = provider; this.timeoutHelper = new TimeoutHelper(timeout); if (RunLoop()) { Complete(true); } } bool RunLoop() { if (this.provider.HasPendingRecords) { while (this.currentParticipant < this.provider.trackingParticipants.Count) { TrackingParticipant participant = this.provider.trackingParticipants[this.currentParticipant]; RuntimeTrackingProfile runtimeProfile = this.provider.GetRuntimeTrackingProfile(participant); if (this.provider.pendingTrackingRecords != null) { while (this.currentRecord < this.provider.pendingTrackingRecords.Count) { bool completedSynchronously = PostTrackingRecord(participant, runtimeProfile); if (!completedSynchronously) { return false; } } } this.currentRecord = 0; this.currentParticipant++; } } // We've now tracked all of the records. this.provider.ClearPendingRecords(); return true; } static bool OnTrackingComplete(IAsyncResult result) { Fx.Assert(!result.CompletedSynchronously, "TrackingAsyncResult.OnTrackingComplete should not get called with a result that is CompletedSynchronously"); FlushPendingRecordsAsyncResult thisPtr = (FlushPendingRecordsAsyncResult)result.AsyncState; TrackingParticipant participant = thisPtr.provider.trackingParticipants[thisPtr.currentParticipant]; bool isSuccessful = false; try { participant.EndTrack(result); isSuccessful = true; } finally { if (!isSuccessful) { thisPtr.provider.ClearPendingRecords(); } } return thisPtr.RunLoop(); } bool PostTrackingRecord(TrackingParticipant participant, RuntimeTrackingProfile runtimeProfile) { TrackingRecord originalRecord = this.provider.pendingTrackingRecords[this.currentRecord]; this.currentRecord++; bool isSuccessful = false; try { TrackingRecord preparedRecord = null; bool shouldClone = this.provider.trackingParticipants.Count > 1; if (runtimeProfile == null) { preparedRecord = shouldClone ? originalRecord.Clone() : originalRecord; } else { preparedRecord = runtimeProfile.Match(originalRecord, shouldClone); } if (preparedRecord != null) { IAsyncResult result = participant.BeginTrack(preparedRecord, this.timeoutHelper.RemainingTime(), PrepareAsyncCompletion(trackingCompleteCallback), this); if (TD.TrackingRecordRaisedIsEnabled()) { TD.TrackingRecordRaised(preparedRecord.ToString(), participant.GetType().ToString()); } if (result.CompletedSynchronously) { participant.EndTrack(result); } else { isSuccessful = true; return false; } } isSuccessful = true; } finally { if (!isSuccessful) { this.provider.ClearPendingRecords(); } } return true; } public static void End(IAsyncResult result) { AsyncResult.End (result); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SoapSchemaExporter.cs
- SerializerDescriptor.cs
- StylusButtonEventArgs.cs
- ValidatorUtils.cs
- CodeArrayIndexerExpression.cs
- ScrollBar.cs
- SynchronizationLockException.cs
- Stroke2.cs
- MissingMethodException.cs
- PriorityBinding.cs
- CompensatableSequenceActivity.cs
- GridViewColumnCollection.cs
- ModuleBuilderData.cs
- CommandHelpers.cs
- Int16.cs
- SimpleTypeResolver.cs
- XmlSchemaObjectTable.cs
- XmlElementCollection.cs
- TokenBasedSet.cs
- dtdvalidator.cs
- PrimaryKeyTypeConverter.cs
- HyperLinkStyle.cs
- TCPClient.cs
- LinqDataSourceStatusEventArgs.cs
- ExtensionQuery.cs
- Char.cs
- ProcessHost.cs
- WebPartCollection.cs
- BinaryReader.cs
- ScrollData.cs
- HttpUnhandledOperationInvoker.cs
- Image.cs
- DataGridTextBoxColumn.cs
- HorizontalAlignConverter.cs
- PackWebRequestFactory.cs
- MinimizableAttributeTypeConverter.cs
- TextSearch.cs
- MappingException.cs
- FileSystemEnumerable.cs
- DataGridRelationshipRow.cs
- AttributeQuery.cs
- AsymmetricKeyExchangeFormatter.cs
- EventMappingSettings.cs
- ParseNumbers.cs
- SecUtil.cs
- CallbackValidatorAttribute.cs
- printdlgexmarshaler.cs
- GenericWebPart.cs
- RequestContext.cs
- IncrementalCompileAnalyzer.cs
- Label.cs
- ProfileSettings.cs
- TableDetailsCollection.cs
- DefaultTextStoreTextComposition.cs
- FlowDocumentView.cs
- UniqueSet.cs
- XsdValidatingReader.cs
- SQLInt32Storage.cs
- StrokeIntersection.cs
- TreeBuilder.cs
- CodeVariableReferenceExpression.cs
- ContextMenu.cs
- ObjectListCommand.cs
- LineSegment.cs
- MarkupCompilePass1.cs
- WindowsFormsLinkLabel.cs
- PositiveTimeSpanValidator.cs
- GeneratedCodeAttribute.cs
- ReplyChannelAcceptor.cs
- DataGridViewDesigner.cs
- CompositeScriptReferenceEventArgs.cs
- ExceptionUtil.cs
- HScrollBar.cs
- FontSource.cs
- StateRuntime.cs
- GuidTagList.cs
- DataContractSerializer.cs
- DbParameterHelper.cs
- CharEnumerator.cs
- SecurityUtils.cs
- WmpBitmapDecoder.cs
- Paragraph.cs
- Help.cs
- LinqToSqlWrapper.cs
- OrderablePartitioner.cs
- UnmanagedMemoryStreamWrapper.cs
- HybridCollection.cs
- MenuStrip.cs
- StringUtil.cs
- GenericTypeParameterBuilder.cs
- DatagramAdapter.cs
- HtmlTextViewAdapter.cs
- WebCategoryAttribute.cs
- XPathNode.cs
- XmlSiteMapProvider.cs
- ConfigurationException.cs
- DocumentCollection.cs
- PropertyCondition.cs
- PieceNameHelper.cs
- OleDbCommand.cs