Algorithm-ConsistentHash-CHash
view release on metacpan or search on metacpan
h ^= h >> 16;
b += 4;
len -= 4;
}
switch (len) {
case 3:
h += b[2] << 16;
case 2:
h += b[1] << 8;
case 1:
h += b[0];
h *= m;
h ^= h >> 24;
}
return h;
}
struct chash_t *chash_create(const char **node_names, size_t *name_lens,
size_t num_names, size_t replicas)
{
struct chash_t *chash;
struct bucket_t *blist;
char **nlist;
size_t *lens;
size_t i, n, r, len, len1, len2, bidx = 0;
char buffer[256];
blist = (struct bucket_t *) malloc(sizeof(bucket_t) * num_names * replicas);
if (blist == NULL) {
goto ERROR_BLIST;
}
nlist = (char **) malloc(sizeof(char *) * num_names);
if (nlist == NULL) {
goto ERROR_NLIST;
}
lens = (size_t *) malloc(sizeof(size_t) * num_names);
if (lens == NULL) {
goto ERROR_LENS;
}
for (n = 0; n < num_names; n++) {
nlist[n] = (char *) malloc(sizeof(char) * name_lens[n]);
if (nlist[n] == NULL) {
goto ERROR_NLIST_MEMBER;
}
lens[n] = name_lens[n];
memcpy(nlist[n], node_names[n], lens[n]);
for (r = 0; r < replicas; r++) {
blist[bidx].node_idx = n;
len1 = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long) r);
if ((sizeof(buffer) - len1) < name_lens[n]) {
len2 = sizeof(buffer) - len1;
} else {
len2 = name_lens[n];
}
memcpy(buffer + len1, node_names[n], len2);
len = len1 + len2;
buffer[len] = '\0';
if (len >= 255) {
fprintf(stderr, "Node name truncated to: %s\n", buffer);
}
blist[bidx].point =
leveldb_bloom_hash((const unsigned char *) buffer, len);
bidx++;
}
}
qsort(blist, bidx, sizeof(struct bucket_t), cmpbucket);
chash = malloc(sizeof(chash_t));
if (chash == NULL) {
goto ERROR_CHASH;
}
chash->blist = blist;
chash->nbuckets = bidx;
chash->node_names = nlist;
chash->name_lens = lens;
chash->num_names = num_names;
return chash;
ERROR_CHASH:
ERROR_NLIST_MEMBER:
/* We know that nlist[n] is the first member not allocated,
thus free every nlist[i] up to n. */
for (i = 0; i < n; i++) {
free(nlist[n]);
}
free(lens);
ERROR_LENS:
free(nlist);
ERROR_NLIST:
free(blist);
ERROR_BLIST:
return NULL;
}
void chash_lookup(struct chash_t *chash, const char *key, size_t len,
const char **node_name, size_t *name_len)
{
uint32_t point = leveldb_bloom_hash((const unsigned char *) key, len);
uint32_t low = 0, high = chash->nbuckets;
uint32_t node_idx;
/* binary search through blist */
while (low < high) {
uint32_t mid = low + (high - low) / 2;
if (chash->blist[mid].point > point) {
high = mid;
} else {
low = mid + 1;
}
}
if (low >= chash->nbuckets) {
low = 0;
}
node_idx = chash->blist[low].node_idx;
( run in 1.808 second using v1.01-cache-2.11-cpan-9581c071862 )