peernodestatemanager.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 / ServiceModel / System / ServiceModel / Channels / peernodestatemanager.cs / 1 / peernodestatemanager.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.ServiceModel.Diagnostics;
    using System.Threading; 


    partial class PeerNodeImplementation
    { 
        // A simple state manager for the PeerNode. Unlike the state managers used for channels and other
        // classes, a PeerNode's Open/Close is counted, a PeerNode is re-openable, and Abort only 
        // takes effect if the outstanding number of Opens is 1. 
        // The PeerNode defers to this object for all state related operations.
        // 
        // Whenever a call is made that may change the state of the object (openCount transitions between 0 and 1),
        // an operation is queued. When an operation is removed from the queue, if the target state is still the
        // same as the operation (e.g. openCount > 0 and operation == Open) and the object is not already in that
        // state, the operation is performed by calling back into the PeerNode 
        //
        // Because each operation is pulled form the queue one at a time, the open and close of the 
        // PeerNode is serialized 
        class SimpleStateManager
        { 
            internal enum State { NotOpened, Opening, Opened, Closing };
            State currentState = State.NotOpened;
            object thisLock = new object();
            Queue queue = new Queue(); 
            bool queueRunning;
            int openCount; 
            PeerNodeImplementation peerNode; 

            public SimpleStateManager(PeerNodeImplementation peerNode) 
            {
                this.peerNode = peerNode;
            }
 
            object ThisLock
            { 
                get { return thisLock; } 
            }
 
            public  void Abort()
            {
                lock (ThisLock)
                { 
                    bool runAbort = false;
                    if (openCount <= 1 && currentState != State.NotOpened) 
                    { 
                        runAbort = true;
                    } 
                    if (openCount > 0)
                    {
                        --openCount;
                    } 
                    if(runAbort)
                    { 
                        try 
                        {
                            peerNode.OnAbort(); 
                        }
                        finally
                        {
                            currentState = State.NotOpened; 
                        }
                    } 
                } 
            }
 
            public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
            {
                CloseOperation op = null;
                lock (ThisLock) 
                {
                    if (openCount > 0) 
                    { 
                        --openCount;
                    } 
                    if (openCount > 0)
                    {
                        return new CompletedAsyncResult(callback, state);
                    } 
                    else
                    { 
                        op = new CloseOperation(this, peerNode, timeout, callback, state); 
                        queue.Enqueue(op);
                        RunQueue(); 
                    }
                }
                return op;
            } 

 
            public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state, bool waitForOnline) 
            {
                bool completedSynchronously = false; 
                OpenOperation op = null;
                lock (ThisLock)
                {
                    openCount++; 
                    if (openCount > 1 && currentState == State.Opened)
                    { 
                        completedSynchronously = true; 
                    }
                    else 
                    {
                        op = new OpenOperation(this, peerNode, timeout, callback, state, waitForOnline);
                        queue.Enqueue(op);
                        RunQueue(); 
                    }
                } 
                if(completedSynchronously) 
                {
                    return new CompletedAsyncResult(callback, state); 
                }

                return op;
            } 

            public void Close(TimeSpan timeout) 
            { 
                EndClose(BeginClose(timeout, null, null));
            } 

            public static void EndOpen(IAsyncResult result)
            {
                // result can be either an OpenOperation or a CompletedAsyncResult 
                if (result is CompletedAsyncResult)
                    CompletedAsyncResult.End(result); 
                else 
                    OpenOperation.End(result);
            } 

            public static void EndClose(IAsyncResult result)
            {
                // result can be either an CloseOperation or a CompletedAsyncResult 
                if (result is CompletedAsyncResult)
                    CompletedAsyncResult.End(result); 
                else 
                    CloseOperation.End(result);
            } 

            // Process IP Address change event from IP helper
            public void OnIPAddressesChanged(object sender, EventArgs e)
            { 
                IPAddressChangeOperation op = null;
                lock (ThisLock) 
                { 
                    op = new IPAddressChangeOperation(peerNode);
                    queue.Enqueue(op); 
                    RunQueue();
                }
            }
 
            public void Open(TimeSpan timeout, bool waitForOnline)
            { 
                EndOpen(BeginOpen(timeout, null, null, waitForOnline)); 
            }
 
            // Start running operations from the queue (must be called within lock)
            void RunQueue()
            {
                if (queueRunning) 
                    return;
 
                queueRunning = true; 
                IOThreadScheduler.ScheduleCallback(new WaitCallback(RunQueueCallback), null);
            } 

            void RunQueueCallback(object state)
            {
                IOperation op; 

                // remove an operation from the queue 
                lock (ThisLock) 
                {
                    DiagnosticUtility.DebugAssert(queue.Count > 0, "queue should not be empty"); 
                    op = queue.Dequeue();
                }
                try
                { 
                    // execute the operation
                    op.Run(); 
                } 
                finally
                { 
                    lock (ThisLock)
                    {
                        // if there are still pending operations, schedule another thread
                        if (queue.Count > 0) 
                        {
                            try 
                            { 
                                IOThreadScheduler.ScheduleCallback(new WaitCallback(RunQueueCallback), null);
                            } 
                            catch(Exception e)
                            {
                                if(DiagnosticUtility.IsFatal(e)) throw;
                                DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                            }
                        } 
                        else 
                        {
                            queueRunning = false; 
                        }
                    }
                }
            } 

            interface IOperation 
            { 
                void Run();
            } 

            class CloseOperation : OperationBase
            {
                PeerNodeImplementation peerNode; 

                public CloseOperation(SimpleStateManager stateManager, 
                    PeerNodeImplementation peerNode, TimeSpan timeout, AsyncCallback callback, object state) 
                    : base(stateManager, timeout, callback, state)
                { 
                    this.peerNode = peerNode;
                }

                protected override void Run() 
                {
                    Exception lclException = null; 
                    try 
                    {
                        lock (ThisLock) 
                        {
                            if (stateManager.openCount > 0)
                            {
                                // the current target state is no longer Closed 
                                invokeOperation = false;
                            } 
                            else if (stateManager.currentState == State.NotOpened) 
                            {
                                // the state is already Closed 
                                invokeOperation = false;
                            }
                            else if(timeoutHelper.RemainingTime() <= TimeSpan.Zero)
                            { 
                                // Time out has already happened complete will be taken care of in the
                                // OperationBase class 
                                invokeOperation = false; 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException());
                            } 
                            else
                            {
                                // the PeerNode needs to be closed
                                if (!(stateManager.currentState != State.Opening && stateManager.currentState != State.Closing)) 
                                {
                                    DiagnosticUtility.DebugAssert("Open and close are serialized by queue We should not be either in Closing or Opening state at this point"); 
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                                }
                                if(stateManager.currentState != State.NotOpened) 
                                {
                                    stateManager.currentState = State.Closing;
                                    invokeOperation = true;
                                } 
                            }
                        } 
                    } 
                    catch(Exception e)
                    { 
                        if(DiagnosticUtility.IsFatal(e)) throw;
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                        lclException = e;
                    } 

                    if (invokeOperation) 
                    { 
                        try
                        { 
                            peerNode.OnClose(timeoutHelper.RemainingTime());
                        }
                        catch (Exception e)
                        { 
                            if(DiagnosticUtility.IsFatal(e)) throw;
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                            lclException = e; 
                        }
                        lock (ThisLock) 
                        {
                            stateManager.currentState = State.NotOpened;
                        }
                    } 
                    Complete(lclException);
                } 
            } 

            class OpenOperation : OperationBase 
            {
                PeerNodeImplementation peerNode;
                bool waitForOnline;
 
                public OpenOperation(SimpleStateManager stateManager, PeerNodeImplementation peerNode, TimeSpan timeout,
                    AsyncCallback callback, object state, bool waitForOnline) : base(stateManager, timeout, callback, state) 
                { 
                    this.peerNode = peerNode;
                    this.waitForOnline = waitForOnline; 
                }

                protected override void Run()
                { 
                    Exception lclException = null;
                    try 
                    { 
                        lock (ThisLock)
                        { 
                            if (stateManager.openCount < 1)
                            {
                                // the current target state is no longer Opened
                                invokeOperation = false; 
                            }
                            else if (stateManager.currentState == State.Opened) 
                            { 
                                // the state is already Opened
                                invokeOperation = false; 
                            }
                            else if(timeoutHelper.RemainingTime() <= TimeSpan.Zero)
                            {
                                // Time out has already happened complete will be taken care of in the 
                                // OperationBase class
                                invokeOperation = false; 
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new TimeoutException()); 
                            }
                            else 
                            {
                                // the PeerNode needs to be opened
                                if (!(stateManager.currentState != State.Opening && stateManager.currentState != State.Closing))
                                { 
                                    DiagnosticUtility.DebugAssert("Open and close are serialized by queue We should not be either in Closing or Opening state at this point");
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                                } 
                                if(stateManager.currentState != State.Opened)
                                { 
                                    stateManager.currentState = State.Opening;
                                    invokeOperation = true;
                                }
                            } 
                        }
                    } 
                    catch(Exception e) 
                    {
                        if(DiagnosticUtility.IsFatal(e)) throw; 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                        lclException = e;
                    }
 
                    if (invokeOperation)
                    { 
                        try 
                        {
                            peerNode.OnOpen(timeoutHelper.RemainingTime(), waitForOnline); 
                            lock (ThisLock)
                            {
                                stateManager.currentState = State.Opened;
                            } 
                        }
                        catch(Exception e) 
                        { 
                            if(DiagnosticUtility.IsFatal(e)) throw;
                            lock (ThisLock) 
                            {
                                stateManager.currentState = State.NotOpened;
                                // since Open is throwing, we roll back the openCount because a matching Close is not
                                // expected 
                                stateManager.openCount--;
                            } 
                            lclException = e; 
                            DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                        } 
                    }
                    Complete(lclException);
                }
            } 

            // Base class for Open and Cose 
            abstract class OperationBase : AsyncResult, IOperation 
            {
                protected SimpleStateManager stateManager; 
                protected TimeoutHelper timeoutHelper;
                AsyncCallback callback;
                protected bool invokeOperation;
                bool completed; 

                public OperationBase(SimpleStateManager stateManager, TimeSpan timeout, 
                    AsyncCallback callback, object state) : base(callback, state) 
                {
                    this.stateManager = stateManager; 
                    timeoutHelper = new TimeoutHelper(timeout);
                    this.callback = callback;
                    invokeOperation = false;
                    completed = false; 
                }
 
                void AsyncComplete(object o) 
                {
                    try 
                    {
                        base.Complete(false, (Exception)o);
                    }
                    catch(Exception e) 
                    {
                        if(DiagnosticUtility.IsFatal(e)) throw; 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(SR.GetString(SR.AsyncCallbackException), e); 
                    }
                } 

                protected abstract void Run();

                void IOperation.Run() 
                {
                    Run(); 
                } 

                protected void Complete(Exception exception) 
                {
                    if(completed)
                    {
                        return; 
                    }
                    lock(ThisLock) 
                    { 
                        if(completed)
                        { 
                            return;
                        }
                        completed = true;
                    } 
                    try
                    { 
                        if (callback != null) 
                        {
                            // complete the AsyncResult on a separate thread so that the queue can progress. 
                            // this prevents a deadlock when the callback attempts to call Close.
                            // this may cause the callbacks to be called in a differnet order in which they completed, but that
                            // is ok because each callback is associated with a different object (channel or listener factory)
                            IOThreadScheduler.ScheduleCallback(new WaitCallback(AsyncComplete), exception); 
                        }
                        else 
                        { 
                            AsyncComplete(exception);
                        } 
                    }
                    catch(Exception e)
                    {
                        if(DiagnosticUtility.IsFatal(e)) throw; 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(SR.GetString(SR.MessagePropagationException), e);
                    } 
                } 

                protected object ThisLock 
                {
                    get { return stateManager.thisLock; }
                }
 
                static public void End(IAsyncResult result)
                { 
                     AsyncResult.End(result); 
                }
            } 

            // To serialize IP address change processing
            class IPAddressChangeOperation : IOperation
            { 
                PeerNodeImplementation peerNode;
 
                public IPAddressChangeOperation(PeerNodeImplementation peerNode) 
                {
                    this.peerNode = peerNode; 
                }

                void IOperation.Run()
                { 
                    peerNode.OnIPAddressChange();
                } 
            } 
        }
    } 
}

// 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