///<summary> /// Sets the channel named in the SoftProtocolException into /// "quiescing mode", where we issue a channel.close and /// ignore everything up to the channel.close-ok reply that /// should eventually arrive. ///</summary> ///<remarks> ///<para> /// Since a well-behaved peer will not wait indefinitely before /// issuing the close-ok, we don't bother with a timeout here; /// compare this to the case of a connection.close-ok, where a /// timeout is necessary. ///</para> ///<para> /// We need to send the close method and politely wait for a /// reply before marking the channel as available for reuse. ///</para> ///<para> /// As soon as SoftProtocolException is detected, we should stop /// servicing ordinary application work, and should concentrate /// on bringing down the channel as quickly and gracefully as /// possible. The way this is done, as per the close-protocol, /// is to signal closure up the stack *before* sending the /// channel.close, by invoking ISession.Close. Once the upper /// layers have been signalled, we are free to do what we need /// to do to clean up and shut down the channel. ///</para> ///</remarks> public void QuiesceChannel(SoftProtocolException pe) { // First, construct the close request and QuiescingSession // that we'll use during the quiesce process. Command request; int replyClassId; int replyMethodId; Protocol.CreateChannelClose(pe.ReplyCode, pe.Message, out request, out replyClassId, out replyMethodId); ISession newSession = new QuiescingSession(this, pe.Channel, pe.ShutdownReason, replyClassId, replyMethodId); // Here we detach the session from the connection. It's // still alive: it just won't receive any further frames // from the mainloop (once we return to the mainloop, of // course). Instead, those frames will be directed at the // new QuiescingSession. ISession oldSession = m_sessionManager.Swap(pe.Channel, newSession); // Now we have all the information we need, and the event // flow of the *lower* layers is set up properly for // shutdown. Signal channel closure *up* the stack, toward // the model and application. oldSession.Close(pe.ShutdownReason); // The upper layers have been signalled. Now we can tell // our peer. The peer will respond through the lower // layers - specifically, through the QuiescingSession we // installed above. newSession.Transmit(request); }
///<summary> /// Sets the channel named in the SoftProtocolException into /// "quiescing mode", where we issue a channel.close and /// ignore everything except for subsequent channel.close /// messages and the channel.close-ok reply that should /// eventually arrive. ///</summary> ///<remarks> ///<para> /// Since a well-behaved peer will not wait indefinitely before /// issuing the close-ok, we don't bother with a timeout here; /// compare this to the case of a connection.close-ok, where a /// timeout is necessary. ///</para> ///<para> /// We need to send the close method and politely wait for a /// reply before marking the channel as available for reuse. ///</para> ///<para> /// As soon as SoftProtocolException is detected, we should stop /// servicing ordinary application work, and should concentrate /// on bringing down the channel as quickly and gracefully as /// possible. The way this is done, as per the close-protocol, /// is to signal closure up the stack *before* sending the /// channel.close, by invoking ISession.Close. Once the upper /// layers have been signalled, we are free to do what we need /// to do to clean up and shut down the channel. ///</para> ///</remarks> public void QuiesceChannel(SoftProtocolException pe) { // Construct the QuiescingSession that we'll use during // the quiesce process. ISession newSession = new QuiescingSession(this, pe.Channel, pe.ShutdownReason); // Here we detach the session from the connection. It's // still alive: it just won't receive any further frames // from the mainloop (once we return to the mainloop, of // course). Instead, those frames will be directed at the // new QuiescingSession. ISession oldSession = m_sessionManager.Swap(pe.Channel, newSession); // Now we have all the information we need, and the event // flow of the *lower* layers is set up properly for // shutdown. Signal channel closure *up* the stack, toward // the model and application. oldSession.Close(pe.ShutdownReason); // The upper layers have been signalled. Now we can tell // our peer. The peer will respond through the lower // layers - specifically, through the QuiescingSession we // installed above. newSession.Transmit(ChannelCloseWrapper(pe.ReplyCode, pe.Message)); }