private bool RunLoop() { if (_provider.HasPendingRecords) { while (_currentParticipant < _provider._trackingParticipants.Count) { TrackingParticipant participant = _provider._trackingParticipants[_currentParticipant]; RuntimeTrackingProfile runtimeProfile = _provider.GetRuntimeTrackingProfile(participant); if (_provider._pendingTrackingRecords != null) { while (_currentRecord < _provider._pendingTrackingRecords.Count) { bool completedSynchronously = PostTrackingRecord(participant, runtimeProfile); if (!completedSynchronously) { return(false); } } } _currentRecord = 0; _currentParticipant++; } } // We've now tracked all of the records. _provider.ClearPendingRecords(); return(true); }
public void FlushPendingRecords(TimeSpan timeout) { try { if (this.HasPendingRecords) { TimeoutHelper helper = new TimeoutHelper(timeout); for (int i = 0; i < _trackingParticipants.Count; i++) { TrackingParticipant participant = _trackingParticipants[i]; RuntimeTrackingProfile runtimeProfile = GetRuntimeTrackingProfile(participant); // HasPendingRecords can be true for the sole purpose of populating our initial profiles, so check again here if (_pendingTrackingRecords != null) { for (int j = 0; j < _pendingTrackingRecords.Count; j++) { TrackingRecord currentRecord = _pendingTrackingRecords[j]; Fx.Assert(currentRecord != null, "We should never come across a null context."); TrackingRecord preparedRecord = null; bool shouldClone = _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(); } }
private bool PostTrackingRecord(TrackingParticipant participant, RuntimeTrackingProfile runtimeProfile) { TrackingRecord originalRecord = _provider._pendingTrackingRecords[_currentRecord]; _currentRecord++; bool isSuccessful = false; try { TrackingRecord preparedRecord = null; bool shouldClone = _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, _timeoutHelper.RemainingTime(), PrepareAsyncCompletion(s_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) { _provider.ClearPendingRecords(); } } return(true); }
private RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingParticipant participant) { TrackingProfile profile; RuntimeTrackingProfile runtimeProfile; if (!_profileSubscriptions.TryGetValue(participant, out runtimeProfile)) { profile = participant.TrackingProfile; if (profile != null) { runtimeProfile = RuntimeTrackingProfile.GetRuntimeTrackingProfile(profile, _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 <string> activityNames = runtimeProfile.GetSubscribedActivityNames(); if (activityNames != null) { if (_activitySubscriptions == null) { _activitySubscriptions = new Dictionary <string, string>(); } foreach (string name in activityNames) { if (_activitySubscriptions.ContainsKey(name)) { _activitySubscriptions.Add(name, name); } else { _activitySubscriptions[name] = name; } } } } else { //for null profiles, set all the filter flags. Merge(new TrackingRecordPreFilter(true)); } _profileSubscriptions.Add(participant, runtimeProfile); } return(runtimeProfile); }
public RuntimeTrackingProfile GetRuntimeTrackingProfile(TrackingProfile profile, Activity rootElement) { Fx.Assert(rootElement != null, "Root element must be valid"); RuntimeTrackingProfile foundRuntimeProfile = null; HybridCollection <RuntimeTrackingProfile> runtimeProfileList = null; lock (_cache) { if (!_cache.TryGetValue(rootElement, out runtimeProfileList)) { foundRuntimeProfile = new RuntimeTrackingProfile(profile, rootElement); runtimeProfileList = new HybridCollection <RuntimeTrackingProfile>(); runtimeProfileList.Add(foundRuntimeProfile); _cache.Add(rootElement, runtimeProfileList); } else { ReadOnlyCollection <RuntimeTrackingProfile> runtimeProfileCollection = runtimeProfileList.AsReadOnly(); foreach (RuntimeTrackingProfile runtimeProfile in runtimeProfileCollection) { if (string.CompareOrdinal(profile.Name, runtimeProfile._associatedProfile.Name) == 0 && string.CompareOrdinal(profile.ActivityDefinitionId, runtimeProfile._associatedProfile.ActivityDefinitionId) == 0) { foundRuntimeProfile = runtimeProfile; break; } } if (foundRuntimeProfile == null) { foundRuntimeProfile = new RuntimeTrackingProfile(profile, rootElement); runtimeProfileList.Add(foundRuntimeProfile); } } } return(foundRuntimeProfile); }