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
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,15 @@
namespace dht {
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 {
Prefix() {}
Prefix(InfoHash h) : size_(h.size() * 8), content_(h.begin(), h.end()) {}
......@@ -32,6 +41,12 @@ struct Prefix {
len += size_;
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 copy = *this;
if (size_) {
......@@ -59,6 +74,30 @@ struct Prefix {
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};
Blob content_ {};
};
......@@ -111,7 +150,7 @@ public:
/**
* 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.
*/
......@@ -135,10 +174,10 @@ private:
* Performs a step in the lookup operation. Each steps are performed
* asynchronously.
*/
void lookupStep(Prefix k, std::shared_ptr<int> lo,
std::shared_ptr<int> hi,
void lookupStep(Prefix k, std::shared_ptr<int> lo, std::shared_ptr<int> hi,
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
......
......@@ -4,10 +4,12 @@
namespace dht {
namespace indexation {
void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
std::shared_ptr<int> hi,
const ValueType IndexEntry::TYPE = ValueType::USER_DATA;
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,
LookupCallback cb, Dht::DoneCallbackSimple done_cb)
LookupCallback cb, Dht::DoneCallbackSimple done_cb,
std::shared_ptr<unsigned> max_common_prefix_len)
{
struct node_lookup_result {
bool done {false};
......@@ -28,7 +30,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
} else {
// internal node
*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) {
......@@ -42,8 +44,27 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
else {
IndexEntry entry;
entry.unpackValue(*value);
if (entry.prefix == p.content_)
auto add_value = [&](bool better = true) {
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;
};
......@@ -59,7 +80,7 @@ void Pht::lookupStep(Prefix p, std::shared_ptr<int> lo,
if (not first_res->is_pht) {
// Not a PHT node.
*hi = mid-1;
lookupStep(p, lo, hi, vals, cb, done_cb);
lookupStep(p, lo, hi, vals, cb, done_cb, max_common_prefix_len);
} else {
first_res->done = true;
if (second_res->done)
......@@ -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 prefix = linearize(k);
auto lo = std::make_shared<int>(0);
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) {
......@@ -145,7 +167,7 @@ void Pht::insert(Key k, Value v, Dht::DoneCallbackSimple done_cb) {
updateCanary(*final_prefix);
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