StateMachineTimers.cs source code in C# .NET

Source code for the .NET framework in C#

                        

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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK