////////////////// /// /// Protected/Private methods /// ///////////////// /** * @param success if this is true, we have a new edge to try else, make a new edge * @param target_ta the transport address this edge was created with * @param e the new edge, if success * @param x the exception which may be present if sucess is false */ protected void EdgeWorkerHandler(object edgeworker, EventArgs args) { EdgeWorker ew = (EdgeWorker)edgeworker; bool close_edge = false; BC.TaskWorker next_task = null; try { Edge e = ew.NewEdge; //This can throw an exception SetTarget(); //This can also throw an exception //If we make it here, we did not have any problem. next_task = new LinkProtocolState(this, ew.TA, e); next_task.FinishEvent += this.LinkProtocolStateFinishHandler; } catch (LinkException) { //This happens if SetTarget sees that we are already connected //Our only choice here is to close the edge and give up. close_edge = true; } catch (EdgeException) { /* * If there is some problem creating the edge, * we wind up here. Just move on */ next_task = StartAttempt(NextTA()); } catch (Exception ex) { /* * The edge creation didn't work out so well */ BU.ProtocolLog.WriteIf(BU.ProtocolLog.LinkDebug, ex.ToString()); next_task = StartAttempt(NextTA()); } if (close_edge) { try { ew.NewEdge.Close(); } catch (Exception) { //Ignore any exception } } if (next_task != null) { /* * We should start a new task now */ _task_queue.Enqueue(next_task); } }
////////////////// /// /// Protected/Private methods /// ///////////////// /** * @param success if this is true, we have a new edge to try else, make a new edge * @param target_ta the transport address this edge was created with * @param e the new edge, if success * @param x the exception which may be present if sucess is false */ protected void EdgeWorkerHandler(object edgeworker, EventArgs args) { EdgeWorker ew = (EdgeWorker)edgeworker; bool close_edge = false; BC.TaskWorker next_task = null; try { Edge e = ew.NewEdge; //This can throw an exception SetTarget(); //This can also throw an exception //If we make it here, we did not have any problem. next_task = new LinkProtocolState(this, ew.TA, e); next_task.FinishEvent += this.LinkProtocolStateFinishHandler; //Keep a proper track of the active LinkProtocolStates: Interlocked.Increment(ref _active_lps_count); } catch(ConnectionExistsException) { //We already have a connection to the target close_edge = true; } catch(LinkException) { //This happens if SetTarget sees that we are already connected //Our only choice here is to close the edge and give up. close_edge = true; } catch(CTLockException) { /* * SetTarget could not get the lock on the address. * Try again later */ close_edge = true; next_task = GetRestartState( ew.TA ); if( next_task == null ) { //We've restarted too many times: next_task = StartAttempt( NextTA() ); } } catch(EdgeException) { /* * If there is some problem creating the edge, * we wind up here. Just move on */ next_task = StartAttempt( NextTA() ); } catch(Exception ex) { /* * The edge creation didn't work out so well */ BU.ProtocolLog.WriteIf(BU.ProtocolLog.LinkDebug, ex.ToString()); next_task = StartAttempt( NextTA() ); } if( close_edge ) { try { ew.NewEdge.Close(); } catch(Exception) { //Ignore any exception } } if( next_task != null ) { /* * We should start a new task now */ _task_queue.Enqueue(next_task); } }
protected void LinkProtocolStateFinishHandler(object olps, EventArgs args) { LinkProtocolState lps = (LinkProtocolState)olps; #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker({1}): {2} finished with result: {3} at: {4}", _local_n.Address, _lid, lps, lps.MyResult, DateTime.UtcNow)); } #endif BC.TaskWorker next_task = null; switch (lps.MyResult) { case LinkProtocolState.Result.Success: /* * Great, the Connection is up and in our table now * Just do nothing now and wait for the other tasks * to finish, at which point, the Linker will fire * its FinishEvent. */ Interlocked.Increment(ref _added_cons); #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker({1}) added {2} at: {3}", _local_n.Address, _lid, lps.Connection, DateTime.UtcNow)); } #endif break; case LinkProtocolState.Result.RetryThisTA: next_task = GetRestartState(lps.TA); if (next_task == null) { goto case LinkProtocolState.Result.MoveToNextTA; } break; case LinkProtocolState.Result.MoveToNextTA: //Hold the lock, it will be transferred: // old LPS -> Linker -> new LPS next_task = StartAttempt(NextTA()); break; case LinkProtocolState.Result.ProtocolError: break; case LinkProtocolState.Result.Exception: break; default: //This should not happen. Console.Error.WriteLine("unrecognized result: " + lps.MyResult.ToString()); break; } if (next_task != null) { //We have some new task to start _task_queue.Enqueue(next_task); } int current_active = Interlocked.Decrement(ref _active_lps_count); if (current_active == 0) { //We have finished handling this lps finishing, //if we have not started another yet, we are not //going to right away. In the mean time, release //the lock Unlock(); } }
////////////////// /// /// Protected/Private methods /// ///////////////// /** * @param success if this is true, we have a new edge to try else, make a new edge * @param target_ta the transport address this edge was created with * @param e the new edge, if success * @param x the exception which may be present if sucess is false */ protected void EdgeWorkerHandler(object edgeworker, EventArgs args) { EdgeWorker ew = (EdgeWorker)edgeworker; bool close_edge = false; BC.TaskWorker next_task = null; try { Edge e = ew.NewEdge; //This can throw an exception SetTarget(); //This can also throw an exception //If we make it here, we did not have any problem. next_task = new LinkProtocolState(this, ew.TA, e); next_task.FinishEvent += this.LinkProtocolStateFinishHandler; //Keep a proper track of the active LinkProtocolStates: Interlocked.Increment(ref _active_lps_count); } catch (ConnectionExistsException) { //We already have a connection to the target close_edge = true; } catch (LinkException) { //This happens if SetTarget sees that we are already connected //Our only choice here is to close the edge and give up. close_edge = true; } catch (CTLockException) { /* * SetTarget could not get the lock on the address. * Try again later */ close_edge = true; next_task = GetRestartState(ew.TA); if (next_task == null) { //We've restarted too many times: next_task = StartAttempt(NextTA()); } } catch (EdgeException) { /* * If there is some problem creating the edge, * we wind up here. Just move on */ next_task = StartAttempt(NextTA()); } catch (Exception ex) { /* * The edge creation didn't work out so well */ BU.ProtocolLog.WriteIf(BU.ProtocolLog.LinkDebug, ex.ToString()); next_task = StartAttempt(NextTA()); } if (close_edge) { try { ew.NewEdge.Close(); } catch (Exception) { //Ignore any exception } } if (next_task != null) { /* * We should start a new task now */ _task_queue.Enqueue(next_task); } }
/** * Allow if we are transfering to a LinkProtocolState or ConnectionPacketHandler * Note this method does not change anything, if the transfer is done, it * is done by the ConnectionTable while it holds its lock. */ public bool AllowLockTransfer(Address a, string contype, ILinkLocker l) { bool allow = false; bool hold_lock = (a.Equals(_target_lock) && contype == _contype); if (false == hold_lock) { //We don't even hold this lock! throw new Exception( String.Format("{2} asked to transfer a lock({0}) we don't hold: ({1})", a, _target_lock, this)); } if (l is Linker) { //Never transfer to another linker: } else if (l is ConnectionPacketHandler.CphState) { /** * The ConnectionPacketHandler only locks when it * has actually received a packet. This is a "bird in the * hand" situation, however, if both sides in the double * link case transfer the lock, then we have accomplished * nothing. * * There is a specific case to worry about: the case of * a firewall, where only one node can contact the other. * In this case, it may be very difficult to connect if * we don't eventually transfer the lock to the * ConnectionPacketHandler. In the case of bi-directional * connectivity, we only transfer the lock if the * address we are locking is greater than our own (which * clearly cannot be true for both sides). * * To handle the firewall case, we keep count of how * many times we have been asked to transfer the lock. On * the third time we are asked, we assume we are in the firewall * case and we allow the transfer, this is just a hueristic. */ int reqs = Interlocked.Increment(ref _cph_transfer_requests); if ((reqs >= 3) || (a.CompareTo(LocalNode.Address) > 0)) { allow = true; } } else if (l is LinkProtocolState) { LinkProtocolState lps = (LinkProtocolState)l; /** * Or Transfer the lock to a LinkProtocolState if: * 1) We created this LinkProtocolState * 2) The LinkProtocolState has received a packet */ if ((lps.Linker == this) && (lps.LinkMessageReply != null)) { allow = true; } } #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker({1}) {2}: transfering lock on {3} to {4}", _local_n.Address, _lid, (_target_lock == null), a, l)); } #endif return(allow); }
////////////////// /// /// Protected/Private methods /// ///////////////// /** * @param success if this is true, we have a new edge to try else, make a new edge * @param target_ta the transport address this edge was created with * @param e the new edge, if success * @param x the exception which may be present if sucess is false */ protected void EdgeWorkerHandler(object edgeworker, EventArgs args) { EdgeWorker ew = (EdgeWorker)edgeworker; bool close_edge = false; BC.TaskWorker next_task = null; try { Edge e = ew.NewEdge; //This can throw an exception SetTarget(); //This can also throw an exception //If we make it here, we did not have any problem. next_task = new LinkProtocolState(this, ew.TA, e); next_task.FinishEvent += this.LinkProtocolStateFinishHandler; } catch(LinkException) { //This happens if SetTarget sees that we are already connected //Our only choice here is to close the edge and give up. close_edge = true; } catch(EdgeException) { /* * If there is some problem creating the edge, * we wind up here. Just move on */ next_task = StartAttempt( NextTA() ); } catch(Exception ex) { /* * The edge creation didn't work out so well */ BU.ProtocolLog.WriteIf(BU.ProtocolLog.LinkDebug, ex.ToString()); next_task = StartAttempt( NextTA() ); } if( close_edge ) { try { ew.NewEdge.Close(); } catch(Exception) { //Ignore any exception } } if( next_task != null ) { /* * We should start a new task now */ _task_queue.Enqueue(next_task); } }