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