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
- EventRoute.cs
- WindowsGraphics.cs
- RuntimeComponentFilter.cs
- HtmlPanelAdapter.cs
- WsdlHelpGeneratorElement.cs
- RadioButtonAutomationPeer.cs
- SqlClientWrapperSmiStreamChars.cs
- HttpListener.cs
- ParameterReplacerVisitor.cs
- RSAOAEPKeyExchangeFormatter.cs
- MD5CryptoServiceProvider.cs
- ComplexLine.cs
- DES.cs
- DesignerVerbCollection.cs
- JsonDataContract.cs
- RegexReplacement.cs
- DrawTreeNodeEventArgs.cs
- DbBuffer.cs
- OneOfConst.cs
- CmsInterop.cs
- XPathQilFactory.cs
- Compiler.cs
- EventBuilder.cs
- ResizingMessageFilter.cs
- ErrorHandlingAcceptor.cs
- SafeWaitHandle.cs
- ClientUtils.cs
- ExpressionTextBoxAutomationPeer.cs
- DesignerTextViewAdapter.cs
- Rfc4050KeyFormatter.cs
- WebPartDescription.cs
- Size3D.cs
- SqlGatherProducedAliases.cs
- DriveInfo.cs
- TreeNodeStyle.cs
- ProfileModule.cs
- Underline.cs
- RepeaterItemCollection.cs
- ITextView.cs
- NativeMethods.cs
- MethodRental.cs
- SqlDataReader.cs
- TextCompositionEventArgs.cs
- DetailsViewRow.cs
- ControlBindingsConverter.cs
- StatusBarDrawItemEvent.cs
- StatusBarPanel.cs
- Converter.cs
- ConfigurationCollectionAttribute.cs
- CommentEmitter.cs
- CardSpaceSelector.cs
- OptimizerPatterns.cs
- Site.cs
- BoundPropertyEntry.cs
- AssemblyInfo.cs
- ApplicationServiceManager.cs
- InputLanguageManager.cs
- Transform3DGroup.cs
- AdapterUtil.cs
- SchemaNames.cs
- QuestionEventArgs.cs
- DocumentReference.cs
- ListMarkerLine.cs
- ContextMenu.cs
- GraphicsContext.cs
- SiteMapNode.cs
- WindowsUserNameCachingSecurityTokenAuthenticator.cs
- RadialGradientBrush.cs
- QilStrConcat.cs
- SourceFilter.cs
- DefaultBinder.cs
- DataFormats.cs
- DataGridTextBox.cs
- TableColumn.cs
- ColumnPropertiesGroup.cs
- Errors.cs
- RepeaterItemEventArgs.cs
- EmptyQuery.cs
- HandlerBase.cs
- ActiveXMessageFormatter.cs
- DesignerActionKeyboardBehavior.cs
- EventLogSession.cs
- ExpressionTable.cs
- RawStylusSystemGestureInputReport.cs
- ClientTargetCollection.cs
- LinkUtilities.cs
- ObjRef.cs
- GlobalizationAssembly.cs
- PermissionSetEnumerator.cs
- ResourceDictionary.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- DocumentXmlWriter.cs
- HitTestWithPointDrawingContextWalker.cs
- ChannelSinkStacks.cs
- XmlWriter.cs
- StrokeCollection2.cs
- Animatable.cs
- ISAPIRuntime.cs
- TextRangeEditTables.cs
- RowsCopiedEventArgs.cs