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
- MediaSystem.cs
- ComplexBindingPropertiesAttribute.cs
- CompressionTransform.cs
- UrlPropertyAttribute.cs
- FaultDesigner.cs
- DataGridViewRowHeaderCell.cs
- FamilyMapCollection.cs
- PanelStyle.cs
- SystemBrushes.cs
- JsonWriterDelegator.cs
- BamlLocalizableResourceKey.cs
- WindowsSpinner.cs
- ActivityExecutionContextCollection.cs
- Model3DGroup.cs
- EffectiveValueEntry.cs
- XamlSerializerUtil.cs
- InputScopeManager.cs
- WebBrowsableAttribute.cs
- FlowDocument.cs
- SpeechSynthesizer.cs
- ErrorWrapper.cs
- DataSourceXmlSerializer.cs
- UriTemplateVariableQueryValue.cs
- ToolbarAUtomationPeer.cs
- TagMapInfo.cs
- DebugInfoGenerator.cs
- EndEvent.cs
- AssemblyInfo.cs
- ModelUtilities.cs
- UnicastIPAddressInformationCollection.cs
- DataControlFieldHeaderCell.cs
- PageTheme.cs
- SectionXmlInfo.cs
- ParserExtension.cs
- TokenBasedSetEnumerator.cs
- CollectionContainer.cs
- DataGridAddNewRow.cs
- NameValuePair.cs
- IriParsingElement.cs
- ChangeBlockUndoRecord.cs
- MsdtcClusterUtils.cs
- IBuiltInEvidence.cs
- XamlHostingSectionGroup.cs
- Misc.cs
- ManagementNamedValueCollection.cs
- PathTooLongException.cs
- XmlTextEncoder.cs
- RtfControls.cs
- ClientType.cs
- SemanticAnalyzer.cs
- LogLogRecordEnumerator.cs
- TextTreeInsertUndoUnit.cs
- Helpers.cs
- XmlKeywords.cs
- IDReferencePropertyAttribute.cs
- SystemException.cs
- SessionEndedEventArgs.cs
- SourceFileInfo.cs
- ColorAnimation.cs
- LayoutSettings.cs
- Token.cs
- ListView.cs
- SupportsEventValidationAttribute.cs
- CodeGeneratorAttribute.cs
- MessageQueueTransaction.cs
- BulletedListEventArgs.cs
- MemberMaps.cs
- ParallelRangeManager.cs
- DataGridTextBox.cs
- SaveFileDialog.cs
- BitmapEffectvisualstate.cs
- MultiPageTextView.cs
- ComplexBindingPropertiesAttribute.cs
- WebScriptEnablingElement.cs
- DataGridViewRowsRemovedEventArgs.cs
- RequestCacheValidator.cs
- BinaryObjectInfo.cs
- StringConcat.cs
- ParamArrayAttribute.cs
- ElementNotAvailableException.cs
- KeyInstance.cs
- MachineKeySection.cs
- EntityContainerEmitter.cs
- PaperSize.cs
- SByteStorage.cs
- GridLengthConverter.cs
- PersonalizationProvider.cs
- ManagedFilter.cs
- DeferredElementTreeState.cs
- Viewport3DAutomationPeer.cs
- ToolboxDataAttribute.cs
- NativeWindow.cs
- indexingfiltermarshaler.cs
- StateItem.cs
- CaseInsensitiveOrdinalStringComparer.cs
- BmpBitmapEncoder.cs
- ComPlusThreadInitializer.cs
- ClientBuildManagerCallback.cs
- CharEnumerator.cs
- JavaScriptObjectDeserializer.cs