improve DHT routing table some, by replacing high RTT nodes within a node ID prefix

This commit is contained in:
Arvid Norberg 2013-09-14 21:49:08 +00:00
parent 2df72d276e
commit 40941608a9
2 changed files with 29 additions and 14 deletions

View File

@ -622,20 +622,32 @@ bool routing_table::add_node(node_entry e)
// in case bucket_size_limit is not an even power of 2 // in case bucket_size_limit is not an even power of 2
mask = (0xff << mask_shift) & 0xff; mask = (0xff << mask_shift) & 0xff;
// TODO: 2 we should really find the node with a matching prefix _and_ the highest
// RTT of those (if there are more than one)
node_id id = e.id; node_id id = e.id;
id <<= bucket_index + 1; id <<= bucket_index + 1;
j = std::find_if(b.begin(), b.end(), boost::bind(&matching_prefix, _1, mask, id[0] & mask, bucket_index));
if (j == b.end()) // pick out all nodes that have the same prefix as the new node
std::vector<bucket_t::iterator> nodes;
bool force_replace = false;
for (j = b.begin(); j != b.end(); ++j)
{ {
// there is no node in this prefix-slot, there must be some if (!matching_prefix(*j, mask, id[0] & mask, bucket_index)) continue;
// nodes sharing a prefix. Find all noes that do not nodes.push_back(j);
}
if (!nodes.empty())
{
j = *std::max_element(nodes.begin(), nodes.end()
, boost::bind(&node_entry::rtt, boost::bind(&bucket_t::iterator::operator*, _1))
< boost::bind(&node_entry::rtt, boost::bind(&bucket_t::iterator::operator*, _2)));
}
else
{
// there is no node in this prefix-slot, there may be some
// nodes sharing a prefix. Find all nodes that do not
// have a unique prefix // have a unique prefix
std::sort(b.begin(), b.end(), boost::bind(&node_entry::id, _1) < boost::bind(&node_entry::id, _2)); std::sort(b.begin(), b.end(), boost::bind(&node_entry::id, _1) < boost::bind(&node_entry::id, _2));
std::vector<bucket_t::iterator> nodes;
int last_prefix = -1; int last_prefix = -1;
nodes.reserve(b.size()); nodes.reserve(b.size());
for (j = b.begin(); j != b.end(); ++j) for (j = b.begin(); j != b.end(); ++j)
@ -664,8 +676,9 @@ bool routing_table::add_node(node_entry e)
< boost::bind(&node_entry::rtt, boost::bind(&bucket_t::iterator::operator*, _2))); < boost::bind(&node_entry::rtt, boost::bind(&bucket_t::iterator::operator*, _2)));
// in this case, we would really rather replace the node even if // in this case, we would really rather replace the node even if
// they have the same RTT. so, to emulate >= // the new node has higher RTT, becase it fills a new prefix that we otherwise
e.rtt = (std::max)(0, e.rtt - 1); // don't have.
force_replace = true;
j = *k; j = *k;
} }
else else
@ -676,12 +689,14 @@ bool routing_table::add_node(node_entry e)
} }
} }
if (j != b.end() && j->rtt > e.rtt) if (j != b.end() && (force_replace || j->rtt > e.rtt))
{ {
m_ips.erase(j->addr().to_v4().to_bytes()); m_ips.erase(j->addr().to_v4().to_bytes());
*j = e; *j = e;
m_ips.insert(e.addr().to_v4().to_bytes()); m_ips.insert(e.addr().to_v4().to_bytes());
// TORRENT_LOG(table) << "replacing node with higher RTT: " << e.id << " " << e.addr(); #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_LOG(table) << "replacing node with higher RTT: " << e.id << " " << e.addr();
#endif
return ret; return ret;
} }
// in order to keep lookup times small, prefer nodes with low RTTs // in order to keep lookup times small, prefer nodes with low RTTs

View File

@ -757,7 +757,7 @@ int test_main()
{ {
node_id id = random_id(); node_id id = random_id();
id[0] = i; id[0] = i;
tbl.node_seen(id, rand_ep(), 50); tbl.node_seen(id, rand_ep(), random() % 20 + 20);
} }
TEST_EQUAL(tbl.num_active_buckets(), 6); TEST_EQUAL(tbl.num_active_buckets(), 6);
@ -773,7 +773,7 @@ int test_main()
{ {
node_id id = random_id(); node_id id = random_id();
id[0] = i; id[0] = i;
tbl.node_seen(id, rand_ep(), 50); tbl.node_seen(id, rand_ep(), random() % 20 + 20);
} }
TEST_EQUAL(tbl.num_active_buckets(), 6); TEST_EQUAL(tbl.num_active_buckets(), 6);
@ -1002,7 +1002,7 @@ int test_main()
nodes.clear(); nodes.clear();
for (int i = 0; i < 7000; ++i) for (int i = 0; i < 7000; ++i)
{ {
table.node_seen(tmp, udp::endpoint(rand_v4(), rand()), 10); table.node_seen(tmp, udp::endpoint(rand_v4(), rand()), random() % 20 + 20);
add_and_replace(tmp, diff); add_and_replace(tmp, diff);
} }
TEST_EQUAL(table.num_active_buckets(), 11); TEST_EQUAL(table.num_active_buckets(), 11);