protected void Trim() {
DateTime now = DateTime.UtcNow;
bool do_trim = false;
lock (_sync ) {
if( now - _last_trim > TRIM_INTERVAL ) {
_last_trim = now;
do_trim = true;
}
}
if( do_trim ) {
Edge to_close = null;
/*
* There is no need to lock the table, this IEnumerable
* won't have problems because it never changes
*/
IEnumerable lenum = _local.ConnectionTable.GetConnections(ConnectionType.Leaf);
ArrayList all_leafs = new ArrayList();
foreach(Connection c in lenum) {
all_leafs.Add(c.Edge);
}
int leafs = all_leafs.Count;
int surplus = leafs - DesiredConnections;
if( surplus > 0 ) {
/*
* Since only public nodes can accept leaf connections (to a good
* approximation), there could be insufficient public nodes to fit
* all the connections. Thus, we make the maximum we accept
* "soft" by only deleting with some probability. This makes the
* system tend toward balance but allows nodes to have more than
* a fixed number of leafs.
*/
double d_s = (double)(surplus);
double prob = 0.0;
if( surplus > 1 ) {
prob = 1.0 - 1.0/d_s;
}
else {
//surplus == 1
//With 25% chance trim the excess connection
prob = 0.25;
}
if( _rnd.NextDouble() < prob ) {
//as surplus -> infinity, prob -> 1, and we always close.
//Now sort them, and get the oldest:
all_leafs.Sort(new EdgeDateComparer());
//Here is the oldest:
to_close = (Edge)all_leafs[0];
}
else {
//We just add the new edge without closing
}
}
if( to_close != null ) {
_local.GracefullyClose( to_close, "From LeafCO, too many leaf connections." );
}
}
}
}