public PeerNeighborCloseEventArgs(PeerCloseReason reason, PeerCloseInitiator closeInitiator, Exception exception) { this.reason = reason; this.closeInitiator = closeInitiator; this.exception = exception; }
// Close a neighbor gracefully public IAsyncResult BeginClose(PeerCloseReason reason, PeerCloseInitiator closeInit, Exception exception, AsyncCallback callback, object asyncState) { bool callClosing = false; lock (ThisLock) { // Set close reason etc. if they are not already set. if (!this.isClosing) { callClosing = true; this.isClosing = true; this.closeReason = reason; this.closeInitiator = closeInit; this.closeException = exception; } } // Initiate close, if another thread has not already done so.... // NOTE: NeighborClosing handlers should not throw any catchable exceptions. if (callClosing) { EventHandler<PeerNeighborCloseEventArgs> handler = this.Closing; if (handler != null) { try { PeerNeighborCloseEventArgs args = new PeerNeighborCloseEventArgs( reason, closeInitiator, exception); handler(this, args); } catch (Exception e) { if (Fx.IsFatal(e)) throw; Abort(); throw; } } } if (this.channelFactory != null) return this.channelFactory.BeginClose(callback, asyncState); else return this.proxyChannel.BeginClose(callback, asyncState); }
// NOTE: Closing handlers not invoked when a neighbor is aborted; but Closed handlers are. public void Abort(PeerCloseReason reason, PeerCloseInitiator closeInit) { lock (ThisLock) { // Set close reason etc. if they are not already set. if (!this.isClosing) { this.isClosing = true; this.closeReason = reason; this.closeInitiator = closeInit; } } Abort(); }
public PeerNeighbor(PeerNodeConfig config, IPeerNodeMessageHandling messageHandler) { this.closeReason = PeerCloseReason.None; this.closeInitiator = PeerCloseInitiator.LocalNode; this.config = config; this.state = PeerNeighborState.Created; this.extensions = new ExtensionCollection<IPeerNeighbor>(this, thisLock); this.messageHandler = messageHandler; }
// Calls neighbor.BeginClose or EndClose and catches appropriate exceptions for any cleanup. // We use a single method for both BeginClose and EndClose processing since exception handling // is very similar in both cases. void InvokeAsyncNeighborClose(PeerNeighbor neighbor, PeerCloseReason closeReason, PeerCloseInitiator closeInitiator, Exception closeException, IAsyncResult endResult) { // initiate invoking BeginClose or EndClose try { if (endResult == null) { IAsyncResult beginResult = neighbor.BeginClose(closeReason, closeInitiator, closeException, Fx.ThunkCallback(new AsyncCallback(OnNeighborClosedCallback)), neighbor); if (beginResult.CompletedSynchronously) neighbor.EndClose(beginResult); } else { neighbor.EndClose(endResult); } } catch (Exception e) { if (Fx.IsFatal(e)) throw; DiagnosticUtility.TraceHandledException(e, TraceEventType.Information); neighbor.TraceEventHelper(TraceEventType.Warning, TraceCode.PeerNeighborCloseFailed, SR.GetString(SR.TraceCodePeerNeighborCloseFailed), e); // May get InvalidOperationException or ObjectDisposedException due to simultaneous close from both sides (and autoclose is enabled) if (e is InvalidOperationException || e is CommunicationException || e is TimeoutException) { neighbor.Abort(); } else { throw; } } }
static void FireEvent(EventHandler<PeerNeighborCloseEventArgs> handler, PeerNeighbor neighbor, PeerCloseReason closeReason, PeerCloseInitiator closeInitiator, Exception closeException) { if (handler != null) { PeerNeighborCloseEventArgs args = new PeerNeighborCloseEventArgs( closeReason, closeInitiator, closeException); handler(neighbor, args); } }
public void CloseNeighbor(IPeerNeighbor neighbor, PeerCloseReason closeReason, PeerCloseInitiator closeInitiator, Exception closeException) { PeerNeighbor nbr = (PeerNeighbor)neighbor; lock (ThisLock) { if (!(this.state != State.Created)) { throw Fx.AssertAndThrow("Neighbor Manager is not expected to be in Created state"); } // Check that the neighbor is known to neighbor manager if (!this.neighborList.Contains(nbr)) return; } // initiate closing of the neighbor if (closeReason != PeerCloseReason.InvalidNeighbor) { if (!nbr.IsClosing) InvokeAsyncNeighborClose(nbr, closeReason, closeInitiator, closeException, null); } else // Call abort even if neighbor is already closing { nbr.Abort(closeReason, closeInitiator); } }
// // Close the specified neighbor. Ok to call multiple times, but NeighborClosing // and NeighborClosed events are fired just once. // If the closeReason specified is InvalidNeighbor, it will be closed ungracefully // public void CloseNeighbor(IPeerNeighbor neighbor, PeerCloseReason closeReason, PeerCloseInitiator closeInitiator) { CloseNeighbor(neighbor, closeReason, closeInitiator, null); }
// Does heavy-lifting of processing closed/faulted events void OnChannelClosedOrFaulted(PeerCloseReason reason) { PeerNeighborState oldState; lock (ThisLock) { // We don't call SetState here because it should not be called inside lock, // and to avoid race conditions, we need to set the state before the lock // can be released. oldState = this.state; this.state = PeerNeighborState.Closed; // Set close reason etc. if they are not already set (as a result of local // node initiating Close) if (!this.isClosing) { this.isClosing = true; this.closeReason = reason; this.closeInitiator = PeerCloseInitiator.RemoteNode; } TraceClosedEvent(oldState); } // Update traces and counters and notify interested parties OnStateChanged(PeerNeighborState.Closed); }
public PeerNeighborCloseEventArgs(PeerCloseReason reason, PeerCloseInitiator closeInitiator, System.Exception exception) { this.reason = reason; this.closeInitiator = closeInitiator; this.exception = exception; }