/** * There are only four ways we can get here: * * 1) We got some exception in Start and never made the first request * 2) There was some problem in LinkCloseHandler * 3) We either got a response or had a problem in StatusCloseHandler * 4) The Edge closed, and the CloseHandler was called. * * The only possibility for a race is between the CloseHandler and * the others. * * When this state machine reaches an end point, it calls this method, * which fires the FinishEvent */ protected void Finish(Result res) { /* * No matter what, we are done here: */ if(ProtocolLog.LinkDebug.Enabled) { string message; Exception x; if (_x.TryGet(out x) ) { message = String.Format( "LPS: {0} finished: {2}, with exception: {1}", _node.Address, x, res); } else { message = String.Format("LPS: {0} finished: {1}", _node.Address, res); } ProtocolLog.Write(ProtocolLog.LinkDebug, message); } int already_finished = Interlocked.Exchange(ref _is_finished, 1); if(already_finished == 1) { //We already got here. //This is a barrier. Only one Finish call will make //it past this point. Only two could happen in a race: //Edge closing or some other failure/success. return; } //We don't care about close event's anymore _e.CloseEvent -= this.CloseHandler; //Set the result: _result = res; try { //Check to see if we need to close the edge if( _con.IsSet == false ) { /* * We didn't get a complete connection, * but we may have heard some response. If so * close the edge gracefully. */ if (LinkMessageReply != null) { //Let's be nice, send a Close message, but don't add this connection: Connection tmp_c = new Connection(_e, LinkMessageReply.Local.Address, _contype, null, LinkMessageReply); tmp_c.Close(_node.Rpc, "From LPS, did not complete a connection."); } else { /* * We never heard from the other side, so we will assume that further * packets will only waste bandwidth */ _e.Close(); } if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got no connection", _node.Address)); } } else { if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS: {0} got connection: {1}", _node.Address, _con.Value)); } } //This could throw an exception, but make sure we unlock if it does. FireFinished(); } finally { /** * We have to make sure the lock is eventually released: */ this.Unlock(); } }