/////////////
///
/// Public methods
///
///////////
/**
* This tells the Linker to make its best effort to create
* a connection to another node
*/
override public void Start()
{
#if LINK_DEBUG
if (BU.ProtocolLog.LinkDebug.Enabled)
{
BU.ProtocolLog.Write(BU.ProtocolLog.LinkDebug, String.Format("{0}, Linker({1}).Start at: {2}", _local_n.Address, _lid, DateTime.UtcNow));
}
#endif
//Try to set _started to 1, if already set to one, throw an exception
if (Interlocked.Exchange(ref _started, 1) == 1)
{
throw new Exception("Linker already Started");
}
//Just move to the next (first) TA
//Get the set of addresses to try
int parallel_attempts = _MAX_PARALLEL_ATTEMPTS;
if (_target == null)
{
//Try more attempts in parallel to get leaf connections.
//This is a hack to make initial connection faster
parallel_attempts = 2 * parallel_attempts;
}
//This would be an ideal place for a list comprehension
ArrayList tasks_to_start = new ArrayList(parallel_attempts);
for (int i = 0; i < parallel_attempts; i++)
{
BC.TaskWorker t = StartAttempt(NextTA());
if (t != null)
{
tasks_to_start.Add(t);
}
}
foreach (BC.TaskWorker t in tasks_to_start)
{
_task_queue.Enqueue(t);
}
/*
* We have so far prevented ourselves from sending the
* FinishEvent. Now, we have laid all the ground work,
* if there are no active tasks, there won't ever be,
* so lets check to see if we need to fire the finish
* event
*/
Interlocked.Exchange(ref _hold_fire, 0);
if (_task_queue.WorkerCount == 0)
{
FinishCheckHandler(_task_queue, EventArgs.Empty);
}
}