ConnectAlgorithms.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 / ConnectAlgorithms.cs / 1 / ConnectAlgorithms.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.Diagnostics; 
    using System.ServiceModel;
    using System.ServiceModel.Diagnostics; 
    using System.Threading;

    // Graph maintainence algorithms.
    sealed class ConnectAlgorithms : IConnectAlgorithms 
    {
        static Random random = new Random(); 
 
        int wantedConnectionCount = 0;
        EventWaitHandle addNeighbor = new EventWaitHandle(true, EventResetMode.ManualReset); 
        EventWaitHandle maintainerClosed = new EventWaitHandle(false, EventResetMode.ManualReset);
        EventWaitHandle welcomeReceived = new EventWaitHandle(false, EventResetMode.ManualReset);

        Dictionary nodeAddresses = new Dictionary(); 
        PeerNodeConfig config;
        Dictionary pendingConnectedNeighbor = new Dictionary(); 
        object thisLock = new object(); 
        IPeerMaintainer maintainer = null;
        bool disposed = false; 

        public void Initialize(IPeerMaintainer maintainer, PeerNodeConfig config, int wantedConnectionCount, Dictionary referralCache)
        {
            this.maintainer = maintainer; 
            this.config = config;
            this.wantedConnectionCount = wantedConnectionCount; 
            UpdateEndpointsCollection(referralCache.Values);        // Add to the endpoints connection anything in the referralsCache 

            // Hook up the event handlers 
            maintainer.NeighborClosed += OnNeighborClosed;
            maintainer.NeighborConnected += OnNeighborConnected;
            maintainer.MaintainerClosed += OnMaintainerClosed;
            maintainer.ReferralsAdded += OnReferralsAdded; 
        }
 
        // instance lock 
        object ThisLock
        { 
            get { return thisLock; }
        }

        public void Connect(TimeSpan timeout) 
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            addNeighbor.Set();              // We are trying to add a neighbor 

            List results = new List(); 
            List handles = new List();

            // While we have more to endpoints try and we have connections pending and we are not connected upto ideal yet, and the maintainer is still open
            while (results.Count != 0 
                || (((nodeAddresses.Count != 0 || pendingConnectedNeighbor.Count != 0) && maintainer.IsOpen)
                && maintainer.ConnectedNeighborCount < wantedConnectionCount)) 
            { 
                try
                { 
                    handles.Clear();
                    foreach (IAsyncResult iar in results)
                    {
                        handles.Add(iar.AsyncWaitHandle); 
                    }
                    handles.Add(welcomeReceived);                               // One of our connect requests resulted in a welcome or neighborManager was shutting down 
                    handles.Add(maintainerClosed);                              // One of our connect requests resulted in a welcome or neighborManager was shutting down 
                    handles.Add(addNeighbor);                                   // Make the last waithandle the add a neighbor signal
 
                    int index = WaitHandle.WaitAny(handles.ToArray(), config.ConnectTimeout, false);
                    if (index == results.Count)                                 // welcomeReceived was signalled
                    {
                        welcomeReceived.Reset(); 
                    }
                    else if (index == results.Count + 1)                        // maintainerClosed was signalled 
                    { 
                        maintainerClosed.Reset();
                        lock (ThisLock) 
                        {
                            nodeAddresses.Clear();
                        }
                    } 
                    else if (index == results.Count + 2)                        // addNeighbor was signalled
                    { 
                        // We need to open a new neighbor 
                        if (nodeAddresses.Count > 0)
                        { 
                            if (pendingConnectedNeighbor.Count + maintainer.ConnectedNeighborCount < wantedConnectionCount)
                            {
                                PeerNodeAddress epr = null;
                                lock (ThisLock) 
                                {
                                    if (nodeAddresses.Count == 0 || !maintainer.IsOpen)   // nodeAddresses or maintainer is closed got updated better cycle 
                                    { 
                                        addNeighbor.Reset();
                                        continue; 
                                    }
                                    int index2 = random.Next() % nodeAddresses.Count;
                                    ICollection keys = nodeAddresses.Keys;
                                    int i = 0; 
                                    Uri key = null;
                                    foreach (Uri uri in keys) 
                                    { 
                                        if (i++ == index2)
                                        { 
                                            key = uri;
                                            break;
                                        }
                                    } 
                                    DiagnosticUtility.DebugAssert(key != null, "key cannot be null here");
                                    epr = nodeAddresses[key]; 
                                    DiagnosticUtility.DebugAssert(epr != null, "epr cannot be null here"); 
                                    nodeAddresses.Remove(key);
                                } 
                                if (maintainer.FindDuplicateNeighbor(epr) == null
                                && pendingConnectedNeighbor.ContainsKey(GetEndpointUri(epr)) == false)
                                {
                                    lock (ThisLock) 
                                    {
                                        pendingConnectedNeighbor.Add(GetEndpointUri(epr), epr); 
                                    } 

                                    // If the neighborManager is not open this call is going to throw. 
                                    // It throws ObjectDisposed exception.
                                    // This check merely eliminates the perf hit, this check is not strictly necessary
                                    // but cuts down the window for the race that will result in a throw to a miniscule level
                                    // We consume the throw because we are closing down 
                                    try
                                    { 
                                        if (maintainer.IsOpen) 
                                        {
                                            if (DiagnosticUtility.ShouldTraceInformation) 
                                            {
                                                PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerConnect,epr, this.config.MeshId));
                                                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity,
                                                    record, this, null); 
                                            }
                                            IAsyncResult iar = maintainer.BeginOpenNeighbor(epr, timeoutHelper.RemainingTime(), null, epr); 
                                            results.Add(iar); 
                                        }
 
                                    }
                                    catch (Exception e)
                                    {
                                        if(DiagnosticUtility.IsFatal(e)) throw; 
                                            if (DiagnosticUtility.ShouldTraceInformation)
                                            { 
                                                PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerConnectFailure,epr, this.config.MeshId, e.Message)); 
                                                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity,
                                                    record, this, null); 
                                            }

                                        // I need to remove the epr just began because the BeginOpen threw.
                                        // However Object Disposed can arise as a result of a race between PeerNode.Close() 
                                        // and Connect trying to reconnect nodes.
                                        pendingConnectedNeighbor.Remove(GetEndpointUri(epr)); 
                                        if (!(e is ObjectDisposedException)) throw; 

                                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                                    }
                                }
                            }
                        } 

                        if (nodeAddresses.Count == 0 || pendingConnectedNeighbor.Count + maintainer.ConnectedNeighborCount == wantedConnectionCount) 
                        { 
                            addNeighbor.Reset();
                        } 
                    }
                    else if (index != WaitHandle.WaitTimeout)
                    {
                        // We have completed this thing remove it from results 
                        IAsyncResult iar = results[index];
                        results.RemoveAt(index); 
                        IPeerNeighbor neighbor = null; 
                        try
                        { 
                            // Get opened neighbor and fire NeighborOpened notification
                            neighbor = maintainer.EndOpenNeighbor(iar);
                        }
                        catch(Exception e) 
                        {
                            if(DiagnosticUtility.IsFatal(e)) throw; 
                            pendingConnectedNeighbor.Remove(GetEndpointUri((PeerNodeAddress)iar.AsyncState)); 
                            throw;
                        } 
                    }
                    else
                    {
                        //A timeout occured no connections progressed, try some more connections 
                        //This may result in more than wantedConnectionCount connections if the timeout connections were
                        // merely being slow 
                        pendingConnectedNeighbor.Clear(); 
                        results.Clear();
                        addNeighbor.Set(); 
                    }
                }
                catch (CommunicationException e)
                { 
                    // mostly likely the endpoint could not be reached, but any channel exception means we should try another node
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    addNeighbor.Set(); 
                }
                catch (TimeoutException e) 
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    addNeighbor.Set();
                } 
            }
        } 
 

        void IDisposable.Dispose() 
        {
            if (!disposed)
            {
                lock (ThisLock) 
                {
                    if (!disposed) 
                    { 
                        disposed = true;
                        maintainer.ReferralsAdded -= OnReferralsAdded; 
                        maintainer.MaintainerClosed -= OnMaintainerClosed;
                        maintainer.NeighborClosed -= OnNeighborClosed;
                        maintainer.NeighborConnected -= OnNeighborConnected;
 
                        addNeighbor.Close();
                        maintainerClosed.Close(); 
                        welcomeReceived.Close(); 
                    }
                } 
            }
        }

        // This method exists to minimize code churn if PeerNodeAddress is refactored later to derive from EndpointAddress 
        static Uri GetEndpointUri(PeerNodeAddress address)
        { 
            return address.EndpointAddress.Uri; 
        }
 
        // Algorithm to prune connections
        // This implementation will reduce the number of connections to config.IdealNeighbors
        // by examining LinkUtility and selecting the neighbor with the lowest and then disconnecting it
        public void PruneConnections() 
        {
            while(maintainer.NonClosingNeighborCount > config.IdealNeighbors && maintainer.IsOpen) 
            { 
                IPeerNeighbor leastUseful = maintainer.GetLeastUsefulNeighbor();
                if(leastUseful == null) 
                    break;
                maintainer.CloseNeighbor(leastUseful, PeerCloseReason.NotUsefulNeighbor);
            }
        } 

        // Helper method for updating the end points list 
        public void UpdateEndpointsCollection(ICollection src) 
        {
            if( src != null) 
            {
                lock (ThisLock)
                {
                    foreach (PeerNodeAddress address in src) 
                    {
                        UpdateEndpointsCollection(address); 
                    } 
                }
            } 
        }

        public void UpdateEndpointsCollection(ICollection src)
        { 
            if( src != null)
            { 
                lock (ThisLock) 
                {
                    foreach (Referral referral in src) 
                    {
                        UpdateEndpointsCollection(referral.Address);
                    }
                } 
            }
        } 
 
        void UpdateEndpointsCollection(PeerNodeAddress address)
        { 
            // Don't accept invalid addresses
            if (PeerValidateHelper.ValidNodeAddress(address))
            {
                Uri key = GetEndpointUri(address); 
                if (!nodeAddresses.ContainsKey(key) && key != GetEndpointUri(maintainer.GetListenAddress()))
                { 
                    nodeAddresses[key] = address; 
                }
            } 
        }

        // When a connection occurs remove it from the list to look at
        void OnNeighborClosed(IPeerNeighbor neighbor) 
        {
            if (neighbor.ListenAddress != null) 
            { 
                Uri address = GetEndpointUri(neighbor.ListenAddress);
 
                if (!disposed)
                {
                    lock (ThisLock)
                    { 
                        if (!disposed)
                        { 
                            if (address != null && pendingConnectedNeighbor.ContainsKey(address)) 
                            {
                                pendingConnectedNeighbor.Remove(address); 
                                addNeighbor.Set();
                            }
                        }
                    } 
                }
            } 
        } 

        // When a connection occurs remove it from the list to look at 
        void OnNeighborConnected(IPeerNeighbor neighbor)
        {
            Uri address = GetEndpointUri(neighbor.ListenAddress);
 
            if (!disposed)
            { 
                lock (ThisLock) 
                {
                    if (!disposed) 
                    {
                        if (address != null && pendingConnectedNeighbor.ContainsKey(address))
                        {
                            pendingConnectedNeighbor.Remove(address); 
                        }
                        welcomeReceived.Set(); 
                    } 
                }
            } 
        }

        void OnMaintainerClosed()
        { 
            if (!disposed)
            { 
                lock (ThisLock) 
                {
                    if (!disposed) 
                    {
                        maintainerClosed.Set();
                    }
                } 
            }
        } 
 
        // When a connection occurs add those to the group I look at
        void OnReferralsAdded(IList referrals, IPeerNeighbor neighbor) 
        {
            bool added = false;

            // Do some stuff here 
            foreach (Referral referral in referrals)
            { 
                if (!disposed) 
                {
                    lock (ThisLock) 
                    {
                        if (!disposed)
                        {
                            if (!maintainer.IsOpen) 
                                return;
 
                            Uri key = GetEndpointUri(referral.Address); 
                            if (key != GetEndpointUri(maintainer.GetListenAddress()))   // make sure the referral is not mine
                            { 
                                if (!nodeAddresses.ContainsKey(key)
                                && !pendingConnectedNeighbor.ContainsKey(key)
                                && maintainer.FindDuplicateNeighbor(referral.Address) == null)
                                { 
                                    nodeAddresses[key] = referral.Address;
                                    added = true; 
                                } 
                            }
                        } 
                    }
                }
            }
 
            if(added)
            { 
                if(maintainer.ConnectedNeighborCount < wantedConnectionCount) 
                {
                    addNeighbor.Set(); 
                }
            }
        }
    } 
}

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