Skip to content

Commit

Permalink
Decide eviction group ties based on time.
Browse files Browse the repository at this point in the history
This corrects a bug the case of tying group size where the code may
 fail to select the group with the newest member. Since newest time
 is the final selection criteria, failing to break ties on it
 on the step before can undermine the final selection.

Tied netgroups are very common.
  • Loading branch information
gmaxwell committed Jan 28, 2016
1 parent 46dbcd4 commit 8e09f91
Showing 1 changed file with 10 additions and 6 deletions.
16 changes: 10 additions & 6 deletions src/net.cpp
Expand Up @@ -914,30 +914,34 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {

if (vEvictionCandidates.empty()) return false;

// Identify the network group with the most connections
// Identify the network group with the most connections and youngest member.
// (vEvictionCandidates is already sorted by reverse connect time)
std::vector<unsigned char> naMostConnections;
unsigned int nMostConnections = 0;
int64_t nMostConnectionsTime = 0;
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
mapAddrCounts[node->addr.GetGroup()].push_back(node);
int64_t grouptime = mapAddrCounts[node->addr.GetGroup()][0]->nTimeConnected;
size_t groupsize = mapAddrCounts[node->addr.GetGroup()].size();

if (mapAddrCounts[node->addr.GetGroup()].size() > nMostConnections) {
nMostConnections = mapAddrCounts[node->addr.GetGroup()].size();
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
nMostConnections = groupsize;
nMostConnectionsTime = grouptime;
naMostConnections = node->addr.GetGroup();
}
}

// Reduce to the network group with the most connections
vEvictionCandidates = mapAddrCounts[naMostConnections];

// Do not disconnect peers if there is only 1 connection from their network group
// Do not disconnect peers if there is only one unprotected connection from their network group.
if (vEvictionCandidates.size() <= 1)
// unless we prefer the new connection (for whitelisted peers)
if (!fPreferNewConnection)
return false;

// Disconnect the most recent connection from the network group with the most connections
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
// Disconnect from the network group with the most connections
vEvictionCandidates[0]->fDisconnect = true;

return true;
Expand Down

0 comments on commit 8e09f91

Please sign in to comment.