protected void Leave()
{
if(ProtocolLog.NodeLog.Enabled) {
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"In StructuredNode.Leave: {0}", this.Address));
}
#if !BRUNET_SIMULATOR
_iphandler.Stop();
#endif
StopConnectionOverlords();
//Stop notifying neighbors of disconnection, we are the one leaving
_connection_table.DisconnectionEvent -= this.UpdateNeighborStatus;
//Gracefully close all the edges:
_connection_table.Close(); //This makes sure we can't add any new connections.
ArrayList edges_to_close = new ArrayList();
foreach(Edge e in _connection_table.GetUnconnectedEdges() ) {
edges_to_close.Add( e );
}
//There is no way unconnected edges could have become Connections,
//so we should put the connections in last.
foreach(Connection c in _connection_table) {
edges_to_close.Add( c.State.Edge );
}
//edges_to_close has all the connections and unconnected edges.
IList copy = edges_to_close.ToArray();
//Make sure multiple readers and writers won't have problems:
edges_to_close = ArrayList.Synchronized( edges_to_close );
EventHandler ch = delegate(object o, EventArgs a) {
if(ProtocolLog.NodeLog.Enabled)
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"{1} Handling Close of: {0}", o, this.Address));
edges_to_close.Remove(o);
if( edges_to_close.Count == 0 ) {
if(ProtocolLog.NodeLog.Enabled)
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"Node({0}) Stopping all EdgeListeners", Address));
StopAllEdgeListeners();
}
};
if(ProtocolLog.NodeLog.Enabled)
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"{0} About to gracefully close all edges", this.Address));
//Use just one of these for all the calls:
IDictionary carg = new ListDictionary();
carg["reason"] = "disconnecting";
for(int i = 0; i < copy.Count; i++) {
Edge e = (Edge)copy[i];
if(ProtocolLog.NodeLog.Enabled) {
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"{0} Closing: [{1} of {2}]: {3}", this.Address, i, copy.Count, e));
}
try {
e.CloseEvent += ch;
Channel res_q = new Channel(1);
DateTime start_time = DateTime.UtcNow;
res_q.CloseEvent += delegate(object o, EventArgs arg) {
if(ProtocolLog.NodeLog.Enabled)
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"Close on edge: {0} took: {1}", e, (DateTime.UtcNow - start_time)));
e.Close();
};
try {
_rpc.Invoke(e, res_q, "sys:link.Close", carg);
}
catch(EdgeException) {
/*
* It is not strange for the other side to have potentially
* closed, or some other error be in progress which is why
* we might have been shutting down in the first place
* No need to print a message
*/
e.Close();
}
catch(Exception x) {
if(ProtocolLog.Exceptions.Enabled)
ProtocolLog.Write(ProtocolLog.Exceptions, String.Format(
"sys:link.Close({0}) threw: {1}", e, x));
e.Close();
}
}
catch {
ch(e,null);
}
}
if( copy.Count == 0 ) {
//There were no edges, go ahead an Stop
if(ProtocolLog.NodeLog.Enabled)
ProtocolLog.Write(ProtocolLog.NodeLog, String.Format(
"Node({0}) Stopping all EdgeListeners", Address));
StopAllEdgeListeners();
}
}