diff --git a/include/opendht/node_cache.h b/include/opendht/node_cache.h index e5f90868..97e62cd1 100644 --- a/include/opendht/node_cache.h +++ b/include/opendht/node_cache.h @@ -26,9 +26,9 @@ namespace dht { struct NodeCache { - std::shared_ptr getNode(const InfoHash& id, sa_family_t family); - std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client=false); - std::vector> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count); + Sp getNode(const InfoHash& id, sa_family_t family); + Sp getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client=false); + std::vector> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) const; /** * Reset the connectivity state of every node, @@ -40,11 +40,12 @@ struct NodeCache { private: class NodeMap : public std::map> { public: - std::shared_ptr getNode(const InfoHash& id); - std::shared_ptr getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client); + Sp getNode(const InfoHash& id); + Sp getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client); void clearBadNodes(); }; + const NodeMap& cache(sa_family_t af) const { return af == AF_INET ? cache_4 : cache_6; } NodeMap& cache(sa_family_t af) { return af == AF_INET ? cache_4 : cache_6; } NodeMap cache_4; NodeMap cache_6; diff --git a/src/node_cache.cpp b/src/node_cache.cpp index 65a1cd07..f821b29b 100644 --- a/src/node_cache.cpp +++ b/src/node_cache.cpp @@ -20,41 +20,44 @@ namespace dht { -std::shared_ptr +Sp NodeCache::getNode(const InfoHash& id, sa_family_t family) { return cache(family).getNode(id); } -std::shared_ptr +Sp NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) { if (id == zeroes) return std::make_shared(id, addr); return cache(addr.getFamily()).getNode(id, addr, now, confirm, client); } -std::vector> -NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) { +std::vector> +NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) const +{ const auto& c = cache(sa_f); - auto it_p = c.lower_bound(id), - it_n = it_p; - std::vector> nodes; + std::vector> nodes; nodes.reserve(std::min(c.size(), count)); NodeMap::const_iterator it; + auto dec_it = [&c](NodeMap::const_iterator& it) { + auto ret = it; + it = (it == c.cbegin()) ? c.cend() : std::prev(it); + return ret; + }; - if (it_p != c.begin()) /* Create 2 separate iterator if we could */ - --it_p; + auto it_p = c.lower_bound(id), + it_n = it_p; + if (it_p != c.cend()) + dec_it(it_p); /* Create 2 separate iterator if we could */ - while (nodes.size() < count and (it_n != c.end() or it_p != c.end())) { + while (nodes.size() < count and (it_n != c.cend() or it_p != c.cend())) { /* If one of the iterator is at the end, then take the other one If they are both in middle of somewhere comapre both and take the closest to the id. */ - if (it_p == c.end()) it = it_n++; - else if (it_n == c.end()) it = it_p--; - else it = id.xorCmp(it_p->first, it_n->first) < 0 ? it_p-- : it_n++; - - if (it == c.begin()) - it_p = c.end(); + if (it_p == c.cend()) it = it_n++; + else if (it_n == c.cend()) it = dec_it(it_p); + else it = id.xorCmp(it_p->first, it_n->first) < 0 ? dec_it(it_p) : it_n++; if (auto n = it->second.lock()) if ( not n->isExpired() and not n->isClient() ) @@ -75,7 +78,7 @@ NodeCache::clearBadNodes(sa_family_t family) } } -std::shared_ptr +Sp NodeCache::NodeMap::getNode(const InfoHash& id) { auto wn = find(id); @@ -87,7 +90,7 @@ NodeCache::NodeMap::getNode(const InfoHash& id) return {}; } -std::shared_ptr +Sp NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) { auto it = emplace(id, std::weak_ptr{});