Skip to content
Snippets Groups Projects
Commit d26a34f4 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

node_cache: use std::map

parent 6652f27a
Branches
Tags
No related merge requests found
...@@ -38,21 +38,15 @@ struct NodeCache { ...@@ -38,21 +38,15 @@ struct NodeCache {
void clearBadNodes(sa_family_t family = 0); void clearBadNodes(sa_family_t family = 0);
private: private:
struct NodeTree { class NodeMap : public std::map<InfoHash, std::weak_ptr<Node>> {
std::shared_ptr<Node> get(const InfoHash& id); public:
std::shared_ptr<Node> get(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed); std::shared_ptr<Node> getNode(const InfoHash& id);
std::shared_ptr<Node> getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed);
void clearBadNodes(); void clearBadNodes();
private:
std::shared_ptr<Node> getLocal(const InfoHash& id);
std::vector<NodeTree> childs;
std::vector<std::weak_ptr<Node>> nodes;
}; };
NodeTree cache_4; NodeMap cache_4;
NodeTree cache_6; NodeMap cache_6;
}; };
} }
...@@ -23,12 +23,12 @@ namespace dht { ...@@ -23,12 +23,12 @@ namespace dht {
std::shared_ptr<Node> std::shared_ptr<Node>
NodeCache::getNode(const InfoHash& id, sa_family_t family) { NodeCache::getNode(const InfoHash& id, sa_family_t family) {
return (family == AF_INET ? cache_4 : cache_6).get(id); return (family == AF_INET ? cache_4 : cache_6).getNode(id);
} }
std::shared_ptr<Node> std::shared_ptr<Node>
NodeCache::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm) { NodeCache::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm) {
return (sa->sa_family == AF_INET ? cache_4 : cache_6).get(id, sa, sa_len, now, confirm); return (sa->sa_family == AF_INET ? cache_4 : cache_6).getNode(id, sa, sa_len, now, confirm);
} }
void void
...@@ -43,82 +43,40 @@ NodeCache::clearBadNodes(sa_family_t family) ...@@ -43,82 +43,40 @@ NodeCache::clearBadNodes(sa_family_t family)
} }
std::shared_ptr<Node> std::shared_ptr<Node>
NodeCache::NodeTree::getLocal(const InfoHash& id) NodeCache::NodeMap::getNode(const InfoHash& id)
{ {
for (auto it = nodes.begin(); it != nodes.end();) { auto wn = find(id);
if (auto n = it->lock()) { if (wn == end())
if (n->id == id) return n; return {};
++it; if (auto n = wn->second.lock())
} else { return n;
it = nodes.erase(it); erase(wn);
}
}
return {}; return {};
} }
std::shared_ptr<Node> std::shared_ptr<Node>
NodeCache::NodeTree::get(const InfoHash& id) NodeCache::NodeMap::getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm)
{ {
NodeTree* t = this; auto it = emplace(id, std::weak_ptr<Node>{});
for (auto b : id) { auto node = it.first->second.lock();
if (t->childs.empty())
return t->getLocal(id);
else
t = &t->childs[b];
}
return {};
}
std::shared_ptr<Node>
NodeCache::NodeTree::get(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirm)
{
// find the bucket
NodeTree* t = this;
size_t offset = 0;
while (not t->childs.empty() and offset < 4)
t = &t->childs[id[offset++]];
// find node in bucket
auto node = t->getLocal(id);
if (not node) { if (not node) {
node = std::make_shared<Node>(id, sa, sa_len); node = std::make_shared<Node>(id, sa, sa_len);
it.first->second = node;
// insert node in bucket
if (t->nodes.size() >= 8 && offset < 4) {
offset++;
t->childs.resize(256);
for (auto& w : t->nodes) {
if (auto tn = w.lock()) {
t->childs[tn->id[offset]].nodes.emplace_back(std::move(w));
}
}
t->nodes = {};
t->childs[id[offset]].nodes.emplace_back(node);
} else {
t->nodes.emplace_back(node);
}
} else if (confirm || node->time < now - Node::NODE_EXPIRE_TIME) { } else if (confirm || node->time < now - Node::NODE_EXPIRE_TIME) {
node->update(sa, sa_len); node->update(sa, sa_len);
} }
/*if (confirm)
node->received(now, confirm >= 2);*/
return node; return node;
} }
void void
NodeCache::NodeTree::clearBadNodes() { NodeCache::NodeMap::clearBadNodes() {
if (childs.empty()) { for (auto it = cbegin(); it != cend();) {
for (auto it = nodes.begin(); it != nodes.end();) { if (auto n = it->second.lock()) {
if (auto n = it->lock()) { n->reset();
n->reset(); ++it;
++it; } else {
} else { erase(it++);
it = nodes.erase(it);
}
} }
} else {
for (auto& c : childs)
c.clearBadNodes();
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment