Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / TransactionBridge / Microsoft / Transactions / Wsat / StateMachines / StateMachineTimers.cs / 1 / StateMachineTimers.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- // This file contains timer logic for WS-AT state machines using System; using System.Diagnostics; using System.Threading; using Microsoft.Transactions.Bridge; using Microsoft.Transactions.Wsat.InputOutput; using Microsoft.Transactions.Wsat.Messaging; using Microsoft.Transactions.Wsat.Protocol; namespace Microsoft.Transactions.Wsat.StateMachines { enum TimerProfile { None, Preparing, Prepared, Replaying, Committing, VolatileOutcomeAssurance, } class TimerInstance { TimerProfile profile; public TimerInstance(TimerProfile profile) { this.profile = profile; } public TimerProfile Profile { get { return this.profile; } } public static readonly TimerInstance Preparing = new TimerInstance(TimerProfile.Preparing); public static readonly TimerInstance Prepared = new TimerInstance(TimerProfile.Prepared); public static readonly TimerInstance Replaying = new TimerInstance(TimerProfile.Replaying); public static readonly TimerInstance Committing = new TimerInstance(TimerProfile.Committing); public static readonly TimerInstance VolatileOutcomeAssurance = new TimerInstance(TimerProfile.VolatileOutcomeAssurance); } abstract partial class StateMachine : ITimerRecipient { public TimeSpan NextNotification { get { return this.timer.NextNotification; } } protected virtual void OnTimer(TimerProfile profile) { // Do nothing } struct TimerState { public TimerInstance Instance; public TimerPolicy Policy; public long Notifications; public bool Active; public TimeSpan CurrentInterval; public TimeSpan NextNotification; } TimerState timer; object timerLock = new object(); public bool StartTimer(TimerProfile profile) { lock (this.timerLock) { // Cancel any existing policy we might have CancelTimer(); if (!ChooseProfile(profile)) { return false; } this.timer.Active = true; this.timer.Notifications = 0; this.timer.CurrentInterval = this.timer.Policy.InitialDelay; this.timer.NextNotification = state.ElapsedTime + this.timer.CurrentInterval; this.state.TimerManager.Add(this, this.timer.Instance); } return true; } public void OnTimerNotification(object token) { TimerInstance instance = (TimerInstance) token; lock (this.timerLock) { // If we were cancelled, discard the notification if (!this.timer.Active) { DebugTrace.Trace(TraceLevel.Verbose, "Notification discarded due to inactive timer"); return; } // If the notification has a different policy, discard it if (!ReferenceEquals(instance, this.timer.Instance)) { DebugTrace.Trace(TraceLevel.Verbose, "Notification discarded due to mismatched policy"); return; } // Increment the number of real notifications received this.timer.Notifications++; if (this.timer.Policy.MaxNotifications == 0 || this.timer.Notifications < this.timer.Policy.MaxNotifications) { if (this.timer.Notifications == 1) { // Use the first interval specified by the policy this.timer.CurrentInterval = this.timer.Policy.NotificationInterval; } else { int increase = this.timer.Policy.IntervalIncreasePercentage; long nextIntervalTicks = this.timer.CurrentInterval.Ticks; nextIntervalTicks += nextIntervalTicks / 100 * increase; if (nextIntervalTicks < 0) { nextIntervalTicks = long.MaxValue - 1; } TimeSpan nextInterval = new TimeSpan(nextIntervalTicks); if (nextInterval > this.timer.Policy.MaxNotificationInterval) { nextInterval = this.timer.Policy.MaxNotificationInterval; } this.timer.CurrentInterval = nextInterval; } this.timer.NextNotification = state.ElapsedTime + this.timer.CurrentInterval; // Re-add the timer to the timer manager state.TimerManager.Add(this, timer.Instance); } else { this.timer.Active = false; // Don't dispatch if this is an extra notification if (this.timer.Notifications > this.timer.Policy.MaxNotifications) { return; } } } // Finally dispatch the notification OnTimer(instance.Profile); } public void CancelTimer() { lock (this.timerLock) { if (this.timer.Active) { if (DebugTrace.Verbose) { DebugTrace.TxTrace(TraceLevel.Verbose, this.enlistment.EnlistmentId, "Removing active timer"); } // Remove ourselves from the timer manager. We may still receive // a notification after making this call. Such is life. this.state.TimerManager.Remove(this); this.timer.Instance = null; this.timer.Active = false; } } } bool ChooseProfile(TimerProfile profile) { bool active = true; switch (profile) { case TimerProfile.Preparing: // We are superior to a participant that has been asked to prepare // When the timer fires, we retry the prepare message ParticipantEnlistment participant = (ParticipantEnlistment)this.enlistment; TimeSpan remaining = participant.TimeoutEstimate - state.ElapsedTime; if (remaining < state.Config.PreparePolicy.InitialDelay) { // There isn't a realistic amount of time remaining on the transaction // for a new prepare retry timer to make sense active = false; } else { this.timer.Instance = TimerInstance.Preparing; this.timer.Policy = state.Config.PreparePolicy; } break; case TimerProfile.Committing: // We are superior to a participant that is in failed to notify. // We keep sending commit messages until we hear a response. this.timer.Instance = TimerInstance.Committing; this.timer.Policy = state.Config.CommitPolicy; break; case TimerProfile.Prepared: // We are subordinate to a coordinator that has not sent us outcome // We are indoubt. We keep sending replay until we hear outcome this.timer.Instance = TimerInstance.Prepared; this.timer.Policy = state.Config.PreparedPolicy; break; case TimerProfile.Replaying: // We are subordinate to a coordinator that has not sent us outcome // We are indoubt. We keep sending prepared until we hear outcome this.timer.Instance = TimerInstance.Replaying; this.timer.Policy = state.Config.ReplayPolicy; break; case TimerProfile.VolatileOutcomeAssurance: // We are superior to a volatile participant to whom we have sent outcome // If we don't hear back from the participant for three minutes, we give up this.timer.Instance = TimerInstance.VolatileOutcomeAssurance; this.timer.Policy = state.Config.VolatileOutcomePolicy; break; default: // An invalid Enum value on this internal code path indicates // a product bug and violates assumptions about // valid values in MSDTC. DiagnosticUtility.FailFast("Invalid TimerProfile"); break; // Keep the compiler happy } return active; } } } // 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
- ParameterCollection.cs
- SqlExpander.cs
- PageAdapter.cs
- SettingsBase.cs
- XmlDataFileEditor.cs
- DataKeyArray.cs
- ValidationHelper.cs
- FlagsAttribute.cs
- iisPickupDirectory.cs
- ValuePattern.cs
- BypassElement.cs
- SnapLine.cs
- Size.cs
- VectorCollectionConverter.cs
- ScrollPatternIdentifiers.cs
- ContextMarshalException.cs
- OperationResponse.cs
- IImplicitResourceProvider.cs
- AutoResetEvent.cs
- DLinqDataModelProvider.cs
- QueryStringHandler.cs
- DataBoundControlHelper.cs
- ClassDataContract.cs
- XmlConvert.cs
- CalendarAutoFormatDialog.cs
- SystemIPGlobalStatistics.cs
- PeekCompletedEventArgs.cs
- GifBitmapEncoder.cs
- ListViewInsertionMark.cs
- XmlLoader.cs
- TextChangedEventArgs.cs
- TrustManagerPromptUI.cs
- HttpApplication.cs
- ClientSettingsStore.cs
- InternalPolicyElement.cs
- FilteredDataSetHelper.cs
- ConsumerConnectionPoint.cs
- _AutoWebProxyScriptEngine.cs
- DependsOnAttribute.cs
- MessageEncodingBindingElement.cs
- DataFormats.cs
- Int16Converter.cs
- TreeNodeStyleCollection.cs
- SelectionHighlightInfo.cs
- ValidatedControlConverter.cs
- SqlMethodAttribute.cs
- TypeListConverter.cs
- SmiXetterAccessMap.cs
- KnownBoxes.cs
- HyperLinkColumn.cs
- SocketStream.cs
- ScriptingWebServicesSectionGroup.cs
- ADMembershipUser.cs
- CancellationToken.cs
- AbandonedMutexException.cs
- FormViewPageEventArgs.cs
- Panel.cs
- NoClickablePointException.cs
- DetailsViewCommandEventArgs.cs
- Visual3D.cs
- SafeNativeMemoryHandle.cs
- ViewBox.cs
- HyperLinkDesigner.cs
- __Filters.cs
- MetadataUtil.cs
- HtmlTableRow.cs
- TextRange.cs
- XamlSerializerUtil.cs
- DecimalKeyFrameCollection.cs
- _FixedSizeReader.cs
- DesignerLoader.cs
- DoubleConverter.cs
- ScrollEvent.cs
- Wildcard.cs
- Column.cs
- HtmlInputRadioButton.cs
- SafeMILHandle.cs
- TextViewBase.cs
- ConfigXmlAttribute.cs
- ComponentChangingEvent.cs
- DefaultShape.cs
- VersionedStream.cs
- ObjectTokenCategory.cs
- ControlBuilderAttribute.cs
- XPathScanner.cs
- PathFigureCollection.cs
- RenderData.cs
- DataSourceSelectArguments.cs
- StructuralComparisons.cs
- LocalizationComments.cs
- DataPointer.cs
- DropShadowBitmapEffect.cs
- SqlBulkCopyColumnMappingCollection.cs
- PrivateUnsafeNativeCompoundFileMethods.cs
- RetrieveVirtualItemEventArgs.cs
- ConsoleCancelEventArgs.cs
- CompoundFileReference.cs
- ReadOnlyDictionary.cs
- PageThemeBuildProvider.cs
- CheckedListBox.cs