Test-before-evict in addrman

From BTC Core https://github.com/bitcoin/bitcoin/pull/9037/ with modifications to support our asmap.

This has a small part of code commented out that depends feeler connection code.
This commit is contained in:
Duke Leto
2021-03-01 17:30:46 -05:00
parent dbef6b34c8
commit 8339b55df4
4 changed files with 315 additions and 21 deletions

View File

@@ -215,8 +215,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId)
info.fInTried = true;
}
void CAddrMan::Good_(const CService& addr, int64_t nTime)
{
void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime) {
int nId;
CAddrInfo* pinfo = Find(addr, &nId);
@@ -258,12 +257,101 @@ void CAddrMan::Good_(const CService& addr, int64_t nTime)
if (nUBucket == -1)
return;
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
// which tried bucket to move the entry to
int tried_bucket = info.GetTriedBucket(nKey,m_asmap);
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
// move nId to the tried tables
MakeTried(info, nId);
// Will moving this address into tried evict another entry?
if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
LogPrint("addrman", "Collision inserting element into tried table, moving %s to m_tried_collisions=%d\n", addr.ToString(), m_tried_collisions.size());
if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) {
m_tried_collisions.insert(nId);
}
} else {
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
printf("%s: Moving %s to tried\n", __func__, addr.ToString().c_str() );
// move nId to the tried tables
MakeTried(info, nId);
}
}
void CAddrMan::ResolveCollisions_() {
for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
int id_new = *it;
bool erase_collision = false;
// If id_new not found in mapInfo remove it from m_tried_collisions
if (mapInfo.count(id_new) != 1) {
erase_collision = true;
} else {
CAddrInfo& info_new = mapInfo[id_new];
// Which tried bucket to move the entry to.
int tried_bucket = info_new.GetTriedBucket(nKey,m_asmap);
int tried_bucket_pos = info_new.GetBucketPosition(nKey, false, tried_bucket);
if (!info_new.IsValid()) { // id_new may no longer map to a valid address
erase_collision = true;
} else if (vvTried[tried_bucket][tried_bucket_pos] != -1) { // The position in the tried bucket is not empty
// Get the to-be-evicted address that is being tested
int id_old = vvTried[tried_bucket][tried_bucket_pos];
CAddrInfo& info_old = mapInfo[id_old];
// Has successfully connected in last X hours
if (GetTime() - info_old.nLastSuccess < ADDRMAN_REPLACEMENT_HOURS*(60*60)) {
erase_collision = true;
} else if (GetTime() - info_old.nLastTry < ADDRMAN_REPLACEMENT_HOURS*(60*60)) { // attempted to connect and failed in last X hours
// Give address at least 60 seconds to successfully connect
if (GetTime() - info_old.nLastTry > 60) {
LogPrint("addrman", "Swapping %s for %s in tried table\n", info_new.ToString(), info_old.ToString());
// Replaces an existing address already in the tried table with the new address
Good_(info_new, false, GetTime());
erase_collision = true;
}
}
} else { // Collision is not actually a collision anymore
Good_(info_new, false, GetTime());
erase_collision = true;
}
}
if (erase_collision) {
m_tried_collisions.erase(it++);
} else {
it++;
}
}
}
CAddrInfo CAddrMan::SelectTriedCollision_() {
if (m_tried_collisions.size() == 0) return CAddrInfo();
std::set<int>::iterator it = m_tried_collisions.begin();
// Selects a random element from m_tried_collisions
std::advance(it, GetRandInt(m_tried_collisions.size()));
int id_new = *it;
// If id_new not found in mapInfo remove it from m_tried_collisions
if (mapInfo.count(id_new) != 1) {
m_tried_collisions.erase(it);
return CAddrInfo();
}
CAddrInfo& newInfo = mapInfo[id_new];
// which tried bucket to move the entry to
int tried_bucket = newInfo.GetTriedBucket(nKey,m_asmap);
int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
int id_old = vvTried[tried_bucket][tried_bucket_pos];
return mapInfo[id_old];
}
bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
{
if (!addr.IsRoutable())