-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbtrdb_mash.cpp
More file actions
95 lines (86 loc) · 2.67 KB
/
btrdb_mash.cpp
File metadata and controls
95 lines (86 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "btrdb_mash.h"
#include <sstream>
#include "btrdb_util.h"
/* Based on the implementation in https://en.wikipedia.org/wiki/MurmurHash */
std::uint32_t murmur3(const void* data, std::size_t len, std::uint32_t seed=1) {
using std::uint8_t;
using std::uint32_t;
using std::size_t;
const uint8_t* key = reinterpret_cast<const uint8_t*>(data);
uint32_t h = seed;
if (len > 3) {
for (size_t i = 0; i < len - 3; i++) {
uint32_t k = ((uint32_t) key[i]) |
(((uint32_t) key[i+1]) << 8) |
(((uint32_t) key[i+2]) << 16) |
(((uint32_t) key[i+3]) << 24);
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
k *= 0x1b873593;
h ^= k;
h = (h << 13) | (h >> 19);
h = (h * 5) + 0xe6546b64;
}
}
/*
* This should never happen when hashing a UUID, but I have it here for
* good measure.
*/
if ((len & 3) != 0) {
size_t i = (len & 3);
uint32_t k = 0;
const uint8_t* ptr = &key[len - 1];
do {
k <<= 8;
k |= *ptr;
ptr--;
} while (--i);
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17);
k *= 0x1b873593;
h ^= k;
}
h ^= len;
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
namespace btrdb {
MASH::MASH(const grpcinterface::Mash& mash) : m_(mash) {
this->precalculate();
}
void MASH::setProtoMash(const grpcinterface::Mash& mash) {
this->m_ = mash;
this->eps_.clear();
this->precalculate();
}
bool MASH::endpointFor(const void* uuid, std::vector<std::string>* addrs, uint32_t* hash) {
std::uint32_t hsh = murmur3(uuid, UUID_NUM_BYTES);
for (const struct endpoint& e : this->eps_) {
if (e.start <= hsh && e.end > hsh) {
*addrs = e.grpc;
*hash = e.hash;
return true;
}
}
return false;
}
void MASH::precalculate() {
const auto& members = this->m_.members();
int num_members = members.size();
this->eps_.resize(num_members);
for (int i = 0; i != num_members; i++) {
const grpcinterface::Member& mbr = members[i];
if (mbr.in() && mbr.up() && mbr.start() != mbr.end()) {
struct endpoint& ep = this->eps_[i];
ep.start = mbr.start();
ep.end = mbr.end();
ep.hash = mbr.hash();
ep.grpc = split_string(mbr.grpcendpoints(), ';');
}
}
}
}