コード例 #1
0
        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();
         }
     }
 }