protected void CheckConnectionOptimality(object node, EventArgs eargs) {
DateTime now = DateTime.UtcNow;
lock(_sync) {
if ((now - _last_optimize_time).TotalSeconds < OPTIMIZE_DELAY) {
return;
}
_last_optimize_time = now;
}
#if TRACE
if (ProtocolLog.SCO.Enabled) {
ProtocolLog.Write(ProtocolLog.SCO,
String.Format("SCO local: {0}, Selcting a random shortcut to optimize.",
_node.Address));
}
#endif
double logk = Math.Log( (double)_node.NetworkSize, 2.0 );
//Get a random shortcut:
ArrayList shortcuts = new ArrayList();
foreach(Connection sc in _node.ConnectionTable.GetConnections(STRUC_SHORT) ) {
/**
* Only if we initiated it, we check if the connection is optimal.
* First half of the token is initiator address, while the other half
* is the start of the range.
*/
string token = sc.State.PeerLinkMessage.Token;
if (token == null || token == String.Empty) {
continue;
}
string initiator_addr = token.Substring(0, token.Length/2);
if (initiator_addr == _node.Address.ToString()) {
shortcuts.Add(sc);
}
}
if (shortcuts.Count > 0) {
// Pick a random shortcut and check for optimality.
Connection sc = (Connection)shortcuts[ _rand.Next(shortcuts.Count) ];
string token = sc.State.PeerLinkMessage.Token;
// Second half of the token is the random target for the shortcut.
Address random_target = AddressParser.Parse(token.Substring(token.Length/2));
#if TRACE
if (ProtocolLog.SCO.Enabled) {
ProtocolLog.Write(ProtocolLog.SCO,
String.Format("SCO local: {0}, Optimizing shortcut connection: {1}, random_target: {2}.",
_node.Address, sc.Address, random_target));
}
#endif
_target_selector.ComputeCandidates(random_target, (int) Math.Ceiling(logk),
CheckShortcutCallback, sc.Address);
} else {
#if TRACE
if (ProtocolLog.SCO.Enabled) {
ProtocolLog.Write(ProtocolLog.SCO,
String.Format("SCO local: {0}, Cannot find a shortcut to optimize.",
_node.Address));
}
#endif
}
//also optimize the bypass connections.
#if TRACE
if (ProtocolLog.SCO.Enabled) {
ProtocolLog.Write(ProtocolLog.SCO,
String.Format("SCO local: {0}, Selecting a bypass to optimize.",
_node.Address));
}
#endif
_target_selector.ComputeCandidates(_node.Address, (int) Math.Ceiling(logk), CheckBypassCallback, null);
}