Decide eviction group ties based on time.
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. (cherry picked from commit 8e09f914f8ec66301257358b250e9a61befadd95)
This commit is contained in:
parent
1e9613ac09
commit
1e05727072
1 changed files with 10 additions and 6 deletions
16
src/net.cpp
16
src/net.cpp
|
@ -929,15 +929,20 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
|
|
||||||
if (vEvictionCandidates.empty()) return false;
|
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;
|
std::vector<unsigned char> naMostConnections;
|
||||||
unsigned int nMostConnections = 0;
|
unsigned int nMostConnections = 0;
|
||||||
|
int64_t nMostConnectionsTime = 0;
|
||||||
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
|
std::map<std::vector<unsigned char>, std::vector<CNodeRef> > mapAddrCounts;
|
||||||
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
|
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
|
||||||
mapAddrCounts[node->addr.GetGroup()].push_back(node);
|
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) {
|
if (groupsize > nMostConnections || (groupsize == nMostConnections && grouptime > nMostConnectionsTime)) {
|
||||||
nMostConnections = mapAddrCounts[node->addr.GetGroup()].size();
|
nMostConnections = groupsize;
|
||||||
|
nMostConnectionsTime = grouptime;
|
||||||
naMostConnections = node->addr.GetGroup();
|
naMostConnections = node->addr.GetGroup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -945,14 +950,13 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
// Reduce to the network group with the most connections
|
// Reduce to the network group with the most connections
|
||||||
vEvictionCandidates = mapAddrCounts[naMostConnections];
|
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)
|
if (vEvictionCandidates.size() <= 1)
|
||||||
// unless we prefer the new connection (for whitelisted peers)
|
// unless we prefer the new connection (for whitelisted peers)
|
||||||
if (!fPreferNewConnection)
|
if (!fPreferNewConnection)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Disconnect the most recent connection from the network group with the most connections
|
// Disconnect from the network group with the most connections
|
||||||
std::sort(vEvictionCandidates.begin(), vEvictionCandidates.end(), ReverseCompareNodeTimeConnected);
|
|
||||||
vEvictionCandidates[0]->fDisconnect = true;
|
vEvictionCandidates[0]->fDisconnect = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue