Skip to content
Snippets Groups Projects
Commit 9c4035dd authored by Simon Désaulniers's avatar Simon Désaulniers Committed by Adrien Béraud
Browse files

add inexact match lookup

This is meant to enable random lookup queries.
parent acc2b71c
Branches
Tags
No related merge requests found
...@@ -15,6 +15,15 @@ ...@@ -15,6 +15,15 @@
namespace dht { namespace dht {
namespace indexation { namespace indexation {
/*!
* @class Prefix
* @brief A blob structure which prefixes a Key in the PHT.
* @details
* Since the PHT structure is a "trie", every node in this structure have a
* label which is defined by the path from the root of the trie to the node. If
* the node in question is a leaf, *the label is a prefix of all the keys
* contained in the leaf*.
*/
struct Prefix { struct Prefix {
Prefix() {} Prefix() {}
Prefix(InfoHash h) : size_(h.size() * 8), content_(h.begin(), h.end()) {} Prefix(InfoHash h) : size_(h.size() * 8), content_(h.begin(), h.end()) {}
...@@ -32,6 +41,12 @@ struct Prefix { ...@@ -32,6 +41,12 @@ struct Prefix {
len += size_; len += size_;
return Prefix(*this, len); return Prefix(*this, len);
} }
/**
* This methods gets the prefix of its sibling in the PHT structure.
*
* @return The prefix of this sibling.
*/
Prefix getSibling() const { Prefix getSibling() const {
Prefix copy = *this; Prefix copy = *this;
if (size_) { if (size_) {
...@@ -59,6 +74,30 @@ struct Prefix { ...@@ -59,6 +74,30 @@ struct Prefix {
return ss.str(); return ss.str();
} }
static inline unsigned commonBits(const Prefix& p1, const Prefix& p2) {
unsigned i, j;
uint8_t x;
auto longest_prefix_size = std::min(p1.size_, p2.size_);
for (i = 0; i < longest_prefix_size; i++) {
if (p1.content_.data()[i] != p2.content_.data()[i])
break;
}
if (i == longest_prefix_size)
return 8*longest_prefix_size;
x = p1.content_.data()[i] ^ p2.content_.data()[i];
j = 0;
while ((x & 0x80) == 0) {
x <<= 1;
j++;
}
return 8 * i + j;
}
size_t size_ {0}; size_t size_ {0};
Blob content_ {}; Blob content_ {};
}; };
...@@ -111,7 +150,7 @@ public: ...@@ -111,7 +150,7 @@ public:
/** /**
* Lookup a key for a value. * Lookup a key for a value.
*/ */
void lookup(Key k, LookupCallback cb = {}, Dht::DoneCallbackSimple doneCb = {}); void lookup(Key k, LookupCallback cb = {}, Dht::DoneCallbackSimple doneCb = {}, bool exact_match = true);
/** /**
* Adds an entry into the index. * Adds an entry into the index.
*/ */
...@@ -135,10 +174,10 @@ private: ...@@ -135,10 +174,10 @@ private:
* Performs a step in the lookup operation. Each steps are performed * Performs a step in the lookup operation. Each steps are performed
* asynchronously. * asynchronously.
*/ */
void lookupStep(Prefix k, std::shared_ptr<int> lo, void lookupStep(Prefix k, std::shared_ptr<int> lo, std::shared_ptr<int> hi,
std::shared_ptr<int> hi,
std::shared_ptr<std::vector<std::shared_ptr<Value>>> vals, std::shared_ptr<std::vector<std::shared_ptr<Value>>> vals,
LookupCallback cb, Dht::DoneCallbackSimple done_cb); LookupCallback cb, Dht::DoneCallbackSimple done_cb,
std::shared_ptr<unsigned> max_common_prefix_len);
/** /**
* Updates the canary token on the node responsible for the specified * Updates the canary token on the node responsible for the specified
......
...@@ -4,10 +4,12 @@ ...@@ -4,10 +4,12 @@
namespace dht { namespace dht {
namespace indexation { namespace indexation {
void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, const ValueType IndexEntry::TYPE = ValueType::USER_DATA;
std::shared_ptr<int> hi,
void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, std::shared_ptr<int> hi,
std::shared_ptr<std::vector<std::shared_ptr<Value>>> vals, std::shared_ptr<std::vector<std::shared_ptr<Value>>> vals,
LookupCallback cb, Dht::DoneCallbackSimple done_cb) LookupCallback cb, Dht::DoneCallbackSimple done_cb,
std::shared_ptr<unsigned> max_common_prefix_len)
{ {
struct node_lookup_result { struct node_lookup_result {
bool done {false}; bool done {false};
...@@ -28,7 +30,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, ...@@ -28,7 +30,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
} else { } else {
// internal node // internal node
*lo = mid+1; *lo = mid+1;
lookupStep(p, lo, hi, vals, cb, done_cb); lookupStep(p, lo, hi, vals, cb, done_cb, max_common_prefix_len);
} }
}; };
if (*lo <= *hi) { if (*lo <= *hi) {
...@@ -42,8 +44,27 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, ...@@ -42,8 +44,27 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
else { else {
IndexEntry entry; IndexEntry entry;
entry.unpackValue(*value); entry.unpackValue(*value);
if (entry.prefix == p.content_)
auto add_value = [&](bool better = true) {
vals->emplace_back(std::make_shared<Value>(entry.value)); vals->emplace_back(std::make_shared<Value>(entry.value));
if (better and max_common_prefix_len)
*max_common_prefix_len = Prefix::commonBits(p, vals->front()->first);
};
if (max_common_prefix_len) {
if (vals->empty()) {
add_value();
} else {
auto common_bits = Prefix::commonBits(vals->front()->first, p.getPrefix(mid));
if (common_bits == *max_common_prefix_len)
add_value(false);
else if (common_bits > *max_common_prefix_len) {
vals->clear();
add_value();
}
}
}
else if (entry.prefix == p.content_)
add_value(false);
} }
return true; return true;
}; };
...@@ -59,7 +80,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, ...@@ -59,7 +80,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
if (not first_res->is_pht) { if (not first_res->is_pht) {
// Not a PHT node. // Not a PHT node.
*hi = mid-1; *hi = mid-1;
lookupStep(p, lo, hi, vals, cb, done_cb); lookupStep(p, lo, hi, vals, cb, done_cb, max_common_prefix_len);
} else { } else {
first_res->done = true; first_res->done = true;
if (second_res->done) if (second_res->done)
...@@ -88,12 +109,13 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo, ...@@ -88,12 +109,13 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
} }
} }
void Pht::lookup(Key k, Pht::LookupCallback cb, Dht::DoneCallbackSimple done_cb) { void Pht::lookup(Key k, Pht::LookupCallback cb, Dht::DoneCallbackSimple done_cb, bool exact_match) {
auto values = std::make_shared<std::vector<std::shared_ptr<Value>>>(); auto values = std::make_shared<std::vector<std::shared_ptr<Value>>>();
auto prefix = linearize(k); auto prefix = linearize(k);
auto lo = std::make_shared<int>(0); auto lo = std::make_shared<int>(0);
auto hi = std::make_shared<int>(prefix.size_); auto hi = std::make_shared<int>(prefix.size_);
lookupStep(prefix, lo, hi, values, cb, done_cb); std::shared_ptr<unsigned> max_common_prefix_len = not exact_match ? std::make_shared<unsigned>(0) : nullptr;
lookupStep(prefix, lo, hi, values, cb, done_cb, max_common_prefix_len);
} }
void Pht::updateCanary(Prefix p) { void Pht::updateCanary(Prefix p) {
...@@ -145,7 +167,7 @@ void Pht::insert(Key k, Value v, Dht::DoneCallbackSimple done_cb) { ...@@ -145,7 +167,7 @@ void Pht::insert(Key k, Value v, Dht::DoneCallbackSimple done_cb) {
updateCanary(*final_prefix); updateCanary(*final_prefix);
dht_->put(final_prefix->hash(), std::move(entry), done_cb); dht_->put(final_prefix->hash(), std::move(entry), done_cb);
} }
} }, nullptr
); );
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment