changed Search::refill to progressive approach

In order to optimize the refill of a search with good SearchNode, the refill is
now done at each call of searchStep(). A "refill" will try to add more good
nodes to the search until the search has reached SEARCH_NODES good nodes.
This commit is contained in:
Simon Désaulniers authored and Simon Désaulniers committed 2016-04-08 23:10:05 -04:00
1 parent e9bda23ae4
commit 9e7babc707
1 file changed
+31 -33
+31 -33
View File
@@ -948,6 +948,12 @@ Dht::searchStep(Search& sr)
/* Check if the first TARGET_NODES (8) live nodes have replied. */
if (sr.isSynced(now)) {
if (sr.nodes.size()-sr.getNumberOfCandidates(now) < SEARCH_NODES and not sr.refilled) {
auto added = sr.refill(sr.af == AF_INET ? buckets : buckets6, now);
DHT_WARN("[search %s IPv%c] refilled with %u nodes", sr.id.toString().c_str(), (sr.af == AF_INET) ? '4' : '6', added);
}
if (not sr.callbacks.empty()) {
// search is synced but some (newer) get operations are not complete
// Call callbacks when done
@@ -1057,40 +1063,31 @@ Dht::searchStep(Search& sr)
return sn.candidate or sn.node->isExpired(now);
}) == sr.nodes.size())
{
unsigned added = 0;
if (not sr.refilled) {
added = sr.refill(sr.af == AF_INET ? buckets : buckets6, now);
sr.refilled = true;
DHT_ERROR("[search %s IPv%c] expired", sr.id.toString().c_str(), sr.af == AF_INET ? '4' : '6');
// no nodes or all expired nodes
sr.expired = true;
// reset refilled since the search is now expired.
sr.refilled = false;
if (sr.announce.empty() && sr.listeners.empty()) {
// Listening or announcing requires keeping the cluster up to date.
sr.done = true;
}
if (added) {
DHT_WARN("[search %s IPv%c] refilled with %u nodes", sr.id.toString().c_str(), (sr.af == AF_INET) ? '4' : '6', added);
} else {
DHT_ERROR("[search %s IPv%c] expired", sr.id.toString().c_str(), sr.af == AF_INET ? '4' : '6');
// no nodes or all expired nodes
sr.expired = true;
// reset refilled since the search is now expired.
sr.refilled = false;
if (sr.announce.empty() && sr.listeners.empty()) {
// Listening or announcing requires keeping the cluster up to date.
sr.done = true;
}
{
auto get_cbs = std::move(sr.callbacks);
for (const auto& g : get_cbs) {
if (g.done_cb)
g.done_cb(false, {});
}
}
{
std::vector<DoneCallback> a_cbs;
a_cbs.reserve(sr.announce.size());
for (const auto& a : sr.announce)
if (a.callback)
a_cbs.emplace_back(std::move(a.callback));
for (const auto& a : a_cbs)
a(false, {});
{
auto get_cbs = std::move(sr.callbacks);
for (const auto& g : get_cbs) {
if (g.done_cb)
g.done_cb(false, {});
}
}
{
std::vector<DoneCallback> a_cbs;
a_cbs.reserve(sr.announce.size());
for (const auto& a : sr.announce)
if (a.callback)
a_cbs.emplace_back(std::move(a.callback));
for (const auto& a : a_cbs)
a(false, {});
}
}
}
@@ -1359,7 +1356,7 @@ Dht::Search::refill(const RoutingTable& r, time_point now) {
auto num_bad_nodes = getNumberOfBadNodes(now);
auto b = r.findBucket(id);
auto n = b;
while (added < SEARCH_NODES && (std::next(n) != r.end() || b != r.begin())) {
while (nodes.size()-num_bad_nodes < SEARCH_NODES && (std::next(n) != r.end() || b != r.begin())) {
if (std::next(n) != r.end()) {
added += insertBucket(*std::next(n), now);
n = std::next(n);
@@ -1369,7 +1366,8 @@ Dht::Search::refill(const RoutingTable& r, time_point now) {
b = std::prev(b);
}
}
//DHT_WARN("[search %s IPv%c] refilled with %u nodes", id.toString().c_str(), (af == AF_INET) ? '4' : '6', added);
refilled = true;
return added;
}