/** * This creates a TaskWorker that represents the next step that should * be taken for the ta. It can only be two tasks: create the edge * (EdgeWorker) or wait and try again (RestartState). * * We return null if: * - the TA is null * - Linker is finished * - a Connection was already created * - this TA has been restarted too many times * * If we cannot get a ConnectionTable.Lock with SetTarget, we return a * RestartState to wait a little while to try to get the lock again. * * @returns the next TaskWorker that should be enqueued, does not start or * Enqueue it. */ protected BC.TaskWorker StartAttempt(TransportAddress next_ta) { BC.TaskWorker next_task = null; if ((next_ta == null) || (_added_cons != 0) || IsFinished || ConnectionInTable) { //Looks like we are already connected... return(null); } try { #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) attempting to lock {2}", _local_n.Address, _lid, _target)); } #endif /* * If we cannot set this address as our target, we * stop before we even try to make an edge. * * Locks flow around in complex ways, but we * (or one of our LinkProtocolState) * will hold the lock */ SetTarget(); #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) acquired lock on {2}", _local_n.Address, _lid, _target)); BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker: ({1}) Trying TA: {2}", _local_n.Address, _lid, next_ta)); } #endif next_task = new EdgeWorker(_local_n, next_ta); next_task.FinishEvent += this.EdgeWorkerHandler; } catch (CTLockException) { /* * If we cannot get a lock on the address in SetTarget() * we wait and and try again */ #if LINK_DEBUG if (BU.ProtocolLog.LinkDebug.Enabled) { BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) failed to lock {2}", _local_n.Address, _lid, _target)); } #endif next_task = GetRestartState(next_ta); } catch (ConnectionExistsException) { //We already have a connection to the target } catch (Exception) { } return(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; } 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); } }
/** * This creates a TaskWorker that represents the next step that should * be taken for the ta. It can only be two tasks: create the edge * (EdgeWorker) or wait and try again (RestartState). * * We return null if: * - the TA is null * - Linker is finished * - a Connection was already created * - this TA has been restarted too many times * * If we cannot get a ConnectionTable.Lock with SetTarget, we return a * RestartState to wait a little while to try to get the lock again. * * @returns the next TaskWorker that should be enqueued, does not start or * Enqueue it. */ protected TaskWorker StartAttempt(TransportAddress next_ta) { TaskWorker next_task = null; if ( (next_ta == null) || (_added_cons != 0) || IsFinished || ConnectionInTable ) { //Looks like we are already connected... return null; } try { #if LINK_DEBUG if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) attempting to lock {2}", _local_n.Address, _lid, _target)); } #endif /* * If we cannot set this address as our target, we * stop before we even try to make an edge. * * Locks flow around in complex ways, but we * (or one of our LinkProtocolState) * will hold the lock */ SetTarget(); #if LINK_DEBUG if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) acquired lock on {2}", _local_n.Address, _lid, _target)); ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("{0}: Linker: ({1}) Trying TA: {2}", _local_n.Address, _lid, next_ta)); } #endif next_task = new EdgeWorker(_local_n, next_ta); next_task.FinishEvent += this.EdgeWorkerHandler; } catch(CTLockException) { /* * If we cannot get a lock on the address in SetTarget() * we wait and and try again */ #if LINK_DEBUG if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("{0}: Linker ({1}) failed to lock {2}", _local_n.Address, _lid, _target)); } #endif next_task = GetRestartState(next_ta); } catch(ConnectionExistsException) { //We already have a connection to the target } catch(Exception) { } return 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); } }