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(); } } }