protected void TrimConnections() {
if(_shortcuts <= 2 * DesiredShortcuts) {
return;
}
lock( _sync ) {
TimeSpan elapsed = DateTime.UtcNow - _last_connection_time;
if( elapsed.TotalSeconds < TRIM_DELAY ) {
return;
}
}
ArrayList trim_candidates = new ArrayList();
ConnectionTable tab = _node.ConnectionTable;
ConnectionList structs = tab.GetConnections(ConnectionType.Structured);
foreach(Connection c in structs) {
if(!c.ConType.Equals(STRUC_SHORT)) {
continue;
}
int left_pos = structs.LeftInclusiveCount(_node.Address, c.Address);
int right_pos = structs.RightInclusiveCount(_node.Address, c.Address);
// Verify that this shortcut is not close
if( left_pos >= DESIRED_NEIGHBORS && right_pos >= DESIRED_NEIGHBORS ) {
trim_candidates.Add(c);
}
}
/*
* The maximum number of shortcuts we allow is log N,
* but we only want 1. This gives some flexibility to
* prevent too much edge churning
*/
if(trim_candidates.Count <= 2 * DesiredShortcuts) {
return;
}
/**
* @todo use a better algorithm here, such as Nima's
* algorithm for biasing towards more distant nodes:
*/
//Delete a random trim candidate:
int idx = _rand.Next( trim_candidates.Count );
Connection to_trim = (Connection)trim_candidates[idx];
#if POB_DEBUG
Console.Error.WriteLine("Attempt to trim Shortcut: {0}", to_trim);
#endif
to_trim.Close(_node.Rpc, "SCO, shortcut connection trim" );
}
}