Ejemplo n.º 1
0
        private ReadOnlyCollection <PeerNodeAddress> ResolveNewAddresses(TimeSpan timeLeft, bool retryResolve)
        {
            TimeoutHelper helper = new TimeoutHelper(timeLeft);
            Dictionary <string, PeerNodeAddress> dictionary = new Dictionary <string, PeerNodeAddress>();
            List <PeerNodeAddress> list          = new List <PeerNodeAddress>();
            PeerNodeAddress        listenAddress = this.config.GetListenAddress(true);

            dictionary.Add(listenAddress.ServicePath, listenAddress);
            int num = retryResolve ? 2 : 1;

            if (DiagnosticUtility.ShouldTraceInformation)
            {
                PeerMaintainerTraceRecord extendedData = new PeerMaintainerTraceRecord("Resolving");
                TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), extendedData, this, null);
            }
            for (int i = 0; ((i < num) && (list.Count < this.config.MaxResolveAddresses)) && (this.isOpen && (helper.RemainingTime() > TimeSpan.Zero)); i++)
            {
                ReadOnlyCollection <PeerNodeAddress> onlys;
                try
                {
                    onlys = this.config.Resolver.Resolve(this.config.MeshId, this.config.MaxResolveAddresses, helper.RemainingTime());
                }
                catch (Exception exception)
                {
                    if (Fx.IsFatal(exception))
                    {
                        throw;
                    }
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        PeerMaintainerTraceRecord record2 = new PeerMaintainerTraceRecord("Resolve exception " + exception.Message);
                        TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), record2, this, null);
                    }
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(System.ServiceModel.SR.GetString("ResolverException"), exception));
                }
                if (onlys != null)
                {
                    foreach (PeerNodeAddress address2 in onlys)
                    {
                        if (!dictionary.ContainsKey(address2.ServicePath))
                        {
                            dictionary.Add(address2.ServicePath, address2);
                            if (((IPeerMaintainer)this).FindDuplicateNeighbor(address2) == null)
                            {
                                list.Add(address2);
                            }
                        }
                    }
                }
            }
            return(new ReadOnlyCollection <PeerNodeAddress>(list));
        }
        public void Connect(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);

            addNeighbor.Set();              // We are trying to add a neighbor

            List <IAsyncResult> results = new List <IAsyncResult>();
            List <WaitHandle>   handles = new List <WaitHandle>();

            // 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 <Uri> keys = nodeAddresses.Keys;
                                    int i   = 0;
                                    Uri key = null;
                                    foreach (Uri uri in keys)
                                    {
                                        if (i++ == index2)
                                        {
                                            key = uri;
                                            break;
                                        }
                                    }
                                    Fx.Assert(key != null, "key cannot be null here");
                                    epr = nodeAddresses[key];
                                    Fx.Assert(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 ---- that will result in a throw to a miniscule level
                                    // We ---- 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, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                        record, this, null);
                                            }
                                            IAsyncResult iar = maintainer.BeginOpenNeighbor(epr, timeoutHelper.RemainingTime(), null, epr);
                                            results.Add(iar);
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        if (Fx.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, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                    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 ---- between PeerNode.Close()
                                        // and Connect trying to reconnect nodes.
                                        pendingConnectedNeighbor.Remove(GetEndpointUri(epr));
                                        if (!(e is ObjectDisposedException))
                                        {
                                            throw;
                                        }

                                        DiagnosticUtility.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 (Fx.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.TraceHandledException(e, TraceEventType.Information);
                    addNeighbor.Set();
                }
                catch (TimeoutException e)
                {
                    if (TD.OpenTimeoutIsEnabled())
                    {
                        TD.OpenTimeout(e.Message);
                    }
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                    addNeighbor.Set();
                }
            }
        }
        public void Connect(TimeSpan timeout)
        {
            TimeoutHelper helper = new TimeoutHelper(timeout);

            this.addNeighbor.Set();
            List <IAsyncResult> list  = new List <IAsyncResult>();
            List <WaitHandle>   list2 = new List <WaitHandle>();

            while ((list.Count != 0) || (((this.nodeAddresses.Count != 0) || (this.pendingConnectedNeighbor.Count != 0)) && (this.maintainer.IsOpen && (this.maintainer.ConnectedNeighborCount < this.wantedConnectionCount))))
            {
                try
                {
                    list2.Clear();
                    foreach (IAsyncResult result in list)
                    {
                        list2.Add(result.AsyncWaitHandle);
                    }
                    list2.Add(this.welcomeReceived);
                    list2.Add(this.maintainerClosed);
                    list2.Add(this.addNeighbor);
                    int index = WaitHandle.WaitAny(list2.ToArray(), this.config.ConnectTimeout, false);
                    if (index == list.Count)
                    {
                        this.welcomeReceived.Reset();
                        continue;
                    }
                    if (index == (list.Count + 1))
                    {
                        this.maintainerClosed.Reset();
                        lock (this.ThisLock)
                        {
                            this.nodeAddresses.Clear();
                            continue;
                        }
                    }
                    if (index == (list.Count + 2))
                    {
                        if ((this.nodeAddresses.Count > 0) && ((this.pendingConnectedNeighbor.Count + this.maintainer.ConnectedNeighborCount) < this.wantedConnectionCount))
                        {
                            PeerNodeAddress address = null;
                            lock (this.ThisLock)
                            {
                                if ((this.nodeAddresses.Count == 0) || !this.maintainer.IsOpen)
                                {
                                    this.addNeighbor.Reset();
                                    continue;
                                }
                                int num2 = random.Next() % this.nodeAddresses.Count;
                                ICollection <Uri> keys = this.nodeAddresses.Keys;
                                int num3 = 0;
                                Uri key  = null;
                                foreach (Uri uri2 in keys)
                                {
                                    if (num3++ == num2)
                                    {
                                        key = uri2;
                                        break;
                                    }
                                }
                                address = this.nodeAddresses[key];
                                this.nodeAddresses.Remove(key);
                            }
                            if ((this.maintainer.FindDuplicateNeighbor(address) == null) && !this.pendingConnectedNeighbor.ContainsKey(GetEndpointUri(address)))
                            {
                                lock (this.ThisLock)
                                {
                                    this.pendingConnectedNeighbor.Add(GetEndpointUri(address), address);
                                }
                                try
                                {
                                    if (this.maintainer.IsOpen)
                                    {
                                        if (DiagnosticUtility.ShouldTraceInformation)
                                        {
                                            PeerMaintainerTraceRecord extendedData = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerConnect", new object[] { address, this.config.MeshId }));
                                            TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), extendedData, this, null);
                                        }
                                        IAsyncResult item = this.maintainer.BeginOpenNeighbor(address, helper.RemainingTime(), null, address);
                                        list.Add(item);
                                    }
                                }
                                catch (Exception exception)
                                {
                                    if (Fx.IsFatal(exception))
                                    {
                                        throw;
                                    }
                                    if (DiagnosticUtility.ShouldTraceInformation)
                                    {
                                        PeerMaintainerTraceRecord record2 = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerConnectFailure", new object[] { address, this.config.MeshId, exception.Message }));
                                        TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), record2, this, null);
                                    }
                                    this.pendingConnectedNeighbor.Remove(GetEndpointUri(address));
                                    if (!(exception is ObjectDisposedException))
                                    {
                                        throw;
                                    }
                                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
                                }
                            }
                        }
                        if ((this.nodeAddresses.Count == 0) || ((this.pendingConnectedNeighbor.Count + this.maintainer.ConnectedNeighborCount) == this.wantedConnectionCount))
                        {
                            this.addNeighbor.Reset();
                        }
                        continue;
                    }
                    if (index != 0x102)
                    {
                        IAsyncResult result3 = list[index];
                        list.RemoveAt(index);
                        try
                        {
                            this.maintainer.EndOpenNeighbor(result3);
                            continue;
                        }
                        catch (Exception exception2)
                        {
                            if (Fx.IsFatal(exception2))
                            {
                                throw;
                            }
                            this.pendingConnectedNeighbor.Remove(GetEndpointUri((PeerNodeAddress)result3.AsyncState));
                            throw;
                        }
                    }
                    this.pendingConnectedNeighbor.Clear();
                    list.Clear();
                    this.addNeighbor.Set();
                }
                catch (CommunicationException exception3)
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception3, TraceEventType.Information);
                    this.addNeighbor.Set();
                }
                catch (TimeoutException exception4)
                {
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(exception4, TraceEventType.Information);
                    this.addNeighbor.Set();
                }
            }
        }
Ejemplo n.º 4
0
 private void MaintainConnections(object dummy)
 {
     if (this.isOpen)
     {
         bool flag = false;
         if (!this.isRunningMaintenance)
         {
             lock (this.ThisLock)
             {
                 if (!this.isRunningMaintenance)
                 {
                     this.isRunningMaintenance = true;
                     flag = true;
                 }
             }
         }
         if (flag)
         {
             if (DiagnosticUtility.ShouldTraceInformation)
             {
                 PeerMaintainerTraceRecord extendedData = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerStarting", new object[] { this.config.MeshId }));
                 TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), extendedData, this, null);
             }
             TimeoutHelper helper = new TimeoutHelper(this.config.MaintainerTimeout);
             try
             {
                 this.maintainerTimer.Cancel();
                 int connectedNeighborCount = this.neighborManager.ConnectedNeighborCount;
                 if (connectedNeighborCount != this.config.IdealNeighbors)
                 {
                     using (IConnectAlgorithms algorithms = (default(TConnectAlgorithms) == null) ? ((IConnectAlgorithms)Activator.CreateInstance <TConnectAlgorithms>()) : ((IConnectAlgorithms)default(TConnectAlgorithms)))
                     {
                         algorithms.Initialize(this, this.config, this.config.IdealNeighbors, this.referralCache);
                         if (connectedNeighborCount > this.config.IdealNeighbors)
                         {
                             if (DiagnosticUtility.ShouldTraceInformation)
                             {
                                 PeerMaintainerTraceRecord record2 = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerPruneMode", new object[] { this.config.MeshId }));
                                 TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), record2, this, null);
                             }
                             algorithms.PruneConnections();
                         }
                         if (this.neighborManager.ConnectedNeighborCount < this.config.IdealNeighbors)
                         {
                             if (this.referralCache.Count == 0)
                             {
                                 ReadOnlyCollection <PeerNodeAddress> src = this.ResolveNewAddresses(helper.RemainingTime(), true);
                                 algorithms.UpdateEndpointsCollection(src);
                             }
                             if (DiagnosticUtility.ShouldTraceInformation)
                             {
                                 PeerMaintainerTraceRecord record3 = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerConnectMode", new object[] { this.config.MeshId }));
                                 TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), record3, this, null);
                             }
                             algorithms.Connect(helper.RemainingTime());
                         }
                     }
                 }
             }
             catch (Exception exception)
             {
                 if (Fx.IsFatal(exception))
                 {
                     throw;
                 }
                 DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Information);
             }
             finally
             {
                 if (DiagnosticUtility.ShouldTraceInformation)
                 {
                     PeerMaintainerTraceRecord record4 = new PeerMaintainerTraceRecord("Maintainer cycle finish");
                     TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), record4, this, null);
                 }
             }
             this.ResetMaintenance();
         }
     }
 }
Ejemplo n.º 5
0
 private void InitialConnection(object dummy)
 {
     if (this.isOpen)
     {
         bool flag = false;
         if (!this.isRunningMaintenance)
         {
             lock (this.ThisLock)
             {
                 if (!this.isRunningMaintenance)
                 {
                     this.isRunningMaintenance = true;
                     flag = true;
                 }
             }
         }
         if (flag)
         {
             if (DiagnosticUtility.ShouldTraceInformation)
             {
                 PeerMaintainerTraceRecord extendedData = new PeerMaintainerTraceRecord(System.ServiceModel.SR.GetString("PeerMaintainerInitialConnect", new object[] { this.config.MeshId }));
                 TraceUtility.TraceEvent(TraceEventType.Information, 0x40051, System.ServiceModel.SR.GetString("TraceCodePeerMaintainerActivity"), extendedData, this, null);
             }
             TimeoutHelper helper = new TimeoutHelper(this.config.MaintainerTimeout);
             Exception     e      = null;
             try
             {
                 this.maintainerTimer.Cancel();
                 using (IConnectAlgorithms algorithms = (default(TConnectAlgorithms) == null) ? ((IConnectAlgorithms)Activator.CreateInstance <TConnectAlgorithms>()) : ((IConnectAlgorithms)default(TConnectAlgorithms)))
                 {
                     algorithms.Initialize(this, this.config, this.config.MinNeighbors, this.referralCache);
                     if (this.referralCache.Count == 0)
                     {
                         ReadOnlyCollection <PeerNodeAddress> src = this.ResolveNewAddresses(helper.RemainingTime(), false);
                         algorithms.UpdateEndpointsCollection(src);
                     }
                     if (this.isOpen)
                     {
                         algorithms.Connect(helper.RemainingTime());
                     }
                 }
             }
             catch (Exception exception2)
             {
                 if (Fx.IsFatal(exception2))
                 {
                     throw;
                 }
                 DiagnosticUtility.ExceptionUtility.TraceHandledException(exception2, TraceEventType.Information);
                 e = exception2;
             }
             if (this.isOpen)
             {
                 try
                 {
                     lock (this.ThisLock)
                     {
                         if (this.isOpen)
                         {
                             if (this.neighborManager.ConnectedNeighborCount < 1)
                             {
                                 this.maintainerTimer.Set(this.config.MaintainerRetryInterval);
                             }
                             else
                             {
                                 this.maintainerTimer.Set(this.config.MaintainerInterval);
                             }
                         }
                     }
                 }
                 catch (Exception exception3)
                 {
                     if (Fx.IsFatal(exception3))
                     {
                         throw;
                     }
                     DiagnosticUtility.ExceptionUtility.TraceHandledException(exception3, TraceEventType.Information);
                     if (e == null)
                     {
                         e = exception3;
                     }
                 }
             }
             lock (this.ThisLock)
             {
                 this.isRunningMaintenance = false;
             }
             if (this.connectCallback != null)
             {
                 this.connectCallback(e);
             }
         }
     }
 }
        // Get some addresses and make sure they are not in my neighborlist
        ReadOnlyCollection <PeerNodeAddress> ResolveNewAddresses(TimeSpan timeLeft, bool retryResolve)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeLeft);
            Dictionary <string, PeerNodeAddress> alreadySeen = new Dictionary <string, PeerNodeAddress>();
            List <PeerNodeAddress> reply = new List <PeerNodeAddress>();

            // Is this address me
            PeerNodeAddress lclNodeAddress = config.GetListenAddress(true);

            alreadySeen.Add(lclNodeAddress.ServicePath, lclNodeAddress);

            // Maximum of 2 resolves to get new addresses - if the resolver doesn't return us good addresses in 2 goes (8 randomly returned addresses)
            // it is probably messing with us
            int nresolves = (retryResolve) ? 2 : 1;

            if (DiagnosticUtility.ShouldTraceInformation)
            {
                PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord("Resolving");
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                        record, this, null);
            }

            for (int i = 0; i < nresolves && reply.Count < config.MaxResolveAddresses && isOpen && timeoutHelper.RemainingTime() > TimeSpan.Zero; i++)
            {
                ReadOnlyCollection <PeerNodeAddress> addresses;
                try
                {
                    addresses = config.Resolver.Resolve(config.MeshId, config.MaxResolveAddresses, timeoutHelper.RemainingTime());
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord("Resolve exception " + e.Message);
                        TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                record, this, null);
                    }

                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.ResolverException), e));
                }

                if (addresses != null)
                {
                    foreach (PeerNodeAddress address in addresses)
                    {
                        if (!alreadySeen.ContainsKey(address.ServicePath))
                        {
                            alreadySeen.Add(address.ServicePath, address);
                            if (((IPeerMaintainer)this).FindDuplicateNeighbor(address) == null)
                            {
                                reply.Add(address);
                            }
                        }
                    }
                }
            }
            return(new ReadOnlyCollection <PeerNodeAddress>(reply));
        }
        // This activity maintains the connected nodes
        void MaintainConnections(object dummy)
        {
            // Are we open and is any maintenance activity occuring
            if (isOpen)
            {
                bool continueMaintenance = false;
                if (!isRunningMaintenance)
                {
                    lock (ThisLock)
                    {
                        if (!isRunningMaintenance)
                        {
                            isRunningMaintenance = true;
                            continueMaintenance  = true;
                        }
                    }
                }
                if (continueMaintenance)
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerStarting, this.config.MeshId));
                        TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                record, this, null);
                    }

                    TimeoutHelper timeoutHelper = new TimeoutHelper(config.MaintainerTimeout);
                    try
                    {
                        maintainerTimer.Cancel();                               // No reconnect until after connect has succeeded

                        int currentlyConnected = neighborManager.ConnectedNeighborCount;
                        if (currentlyConnected != config.IdealNeighbors)        // Already at ideal no work to do
                        {
                            using (IConnectAlgorithms connectAlgorithm = (IConnectAlgorithms) new TConnectAlgorithms())
                            {
                                connectAlgorithm.Initialize(this, config, config.IdealNeighbors, referralCache);
                                if (currentlyConnected > config.IdealNeighbors)
                                {
                                    if (DiagnosticUtility.ShouldTraceInformation)
                                    {
                                        PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerPruneMode, this.config.MeshId));
                                        TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                record, this, null);
                                    }
                                    connectAlgorithm.PruneConnections();
                                }

                                // During Prune some other neighbor may have gone away which leaves us below Ideal
                                // So try to reconnect
                                currentlyConnected = neighborManager.ConnectedNeighborCount;
                                if (currentlyConnected < config.IdealNeighbors)
                                {
                                    if (referralCache.Count == 0)
                                    {
                                        ReadOnlyCollection <PeerNodeAddress> addresses = ResolveNewAddresses(timeoutHelper.RemainingTime(), true);
                                        connectAlgorithm.UpdateEndpointsCollection(addresses);
                                    }
                                    if (DiagnosticUtility.ShouldTraceInformation)
                                    {
                                        PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerConnectMode, this.config.MeshId));
                                        TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                                record, this, null);
                                    }
                                    connectAlgorithm.Connect(timeoutHelper.RemainingTime());
                                }
                            }
                        }
                    }
#pragma warning suppress 56500 // covered by FxCOP
                    catch (Exception e)
                    {
                        if (Fx.IsFatal(e))
                        {
                            throw;
                        }
                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                        // We ---- all non Fatal exceptions because this is a worker thread, with no user code waiting
                    }
                    finally
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord("Maintainer cycle finish");
                            TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                    record, this, null);
                        }
                    }
                    ResetMaintenance();
                }
            }
        }
        void InitialConnection(object dummy)
        {
            // Are we open and is any maintenance activity occuring
            if (isOpen)
            {
                bool continueMaintenance = false;
                if (!isRunningMaintenance)
                {
                    lock (ThisLock)
                    {
                        if (!isRunningMaintenance)
                        {
                            isRunningMaintenance = true;
                            continueMaintenance  = true;
                        }
                    }
                }
                if (continueMaintenance)
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        PeerMaintainerTraceRecord record = new PeerMaintainerTraceRecord(SR.GetString(SR.PeerMaintainerInitialConnect, this.config.MeshId));
                        TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.PeerMaintainerActivity, SR.GetString(SR.TraceCodePeerMaintainerActivity),
                                                record, this, null);
                    }

                    TimeoutHelper timeoutHelper = new TimeoutHelper(config.MaintainerTimeout);
                    Exception     exception     = null;
                    // The connection algorithm may be pluggable if we provide an api or metadata to enable it.
                    // I am sure that research would be interested in doing such a thing.
                    try
                    {
                        maintainerTimer.Cancel();                   // No reconnect until after connect has succeeded

                        using (IConnectAlgorithms connectAlgorithm = (IConnectAlgorithms) new TConnectAlgorithms())
                        {
                            connectAlgorithm.Initialize(this, config, config.MinNeighbors, referralCache);
                            if (referralCache.Count == 0)
                            {
                                ReadOnlyCollection <PeerNodeAddress> addresses = ResolveNewAddresses(timeoutHelper.RemainingTime(), false);
                                connectAlgorithm.UpdateEndpointsCollection(addresses);
                            }
                            if (isOpen)
                            {
                                connectAlgorithm.Connect(timeoutHelper.RemainingTime());
                            }
                        }
                    }
#pragma warning suppress 56500 // covered by FxCOP
                    catch (Exception e)
                    {
                        if (Fx.IsFatal(e))
                        {
                            throw;
                        }
                        DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                        exception = e;                              // Exeption is saved and transferred
                    }
                    if (isOpen)
                    {
                        try
                        {
                            lock (ThisLock)
                            {
                                if (isOpen)
                                {
                                    // No reconnect until after connect has succeeded
                                    if (neighborManager.ConnectedNeighborCount < 1)
                                    {
                                        maintainerTimer.Set(config.MaintainerRetryInterval);
                                    }
                                    else
                                    {
                                        maintainerTimer.Set(config.MaintainerInterval);
                                    }
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            if (Fx.IsFatal(e))
                            {
                                throw;
                            }
                            DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
                            if (exception == null)
                            {
                                exception = e;                                   // Exeption is saved and transferred via callback
                            }
                        }
                    }
                    lock (ThisLock)
                    {
                        isRunningMaintenance = false;
                    }
                    if (connectCallback != null)
                    {
                        connectCallback(exception);
                    }
                }
            }
        }