int cluster_config_key_is_mine(struct cluster_config *config, const char *key, size_t nkey, bool *mine, uint32_t *key_id, uint32_t *self_id) { uint32_t server, self; uint32_t digest; int ret = 0; assert(config); assert(config->continuum); pthread_mutex_lock(&config->lock); if (config->is_valid) { /* cluster is valid */ self = config->self_id; digest = hash_ketama(key, nkey); server = find_continuum(config->continuum, config->num_continuum, digest); *mine = (server == self ? true : false); if ( key_id) *key_id = server; if (self_id) *self_id = self; } else { /* this case should not be happened. */ ret = -1; /* unknown cluster */ } pthread_mutex_unlock(&config->lock); return ret; }
bool cluster_config_key_is_mine(struct cluster_config *config, const char *key, size_t nkey, uint32_t *key_id, uint32_t *self_id) { uint32_t server, self; uint32_t digest, mid, prev; struct continuum_item *beginp, *endp, *midp, *highp, *lowp; assert(config); assert(config->continuum); pthread_mutex_lock(&config->lock); // this should not be happened if (config->is_valid == false) { pthread_mutex_unlock(&config->lock); return true; } self = config->self_id; digest = hash_ketama(key, nkey); beginp = lowp = config->continuum; endp = highp = config->continuum + config->num_continuum; while (1) { // pick the middle point midp = lowp + (highp - lowp) / 2; if (midp == endp) { // if at the end, rollback to 0th server = beginp->index; break; } mid = midp->point; prev = (midp == beginp) ? 0 : (midp-1)->point; if (digest <= mid && digest > prev) { // found the nearest server server = midp->index; break; } // adjust the limits if (mid < digest) lowp = midp + 1; else highp = midp - 1; if (lowp > highp) { server = beginp->index; break; } } if ( key_id) *key_id = server; if (self_id) *self_id = self; pthread_mutex_unlock(&config->lock); return server == self; }
int vbucket_map(VBUCKET_CONFIG_HANDLE vb, const void *key, size_t nkey, int *vbucket_id, int *server_idx) { uint32_t digest, mid, prev; struct continuum_item_st *beginp, *endp, *midp, *highp, *lowp; if (vb->distribution == VBUCKET_DISTRIBUTION_KETAMA) { assert(vb->continuum); if (vbucket_id) { *vbucket_id = 0; } digest = hash_ketama(key, nkey); beginp = lowp = vb->continuum; endp = highp = vb->continuum + vb->num_continuum; /* divide and conquer array search to find server with next biggest * point after what this key hashes to */ while (1) { /* pick the middle point */ midp = lowp + (highp - lowp) / 2; if (midp == endp) { /* if at the end, roll back to zeroth */ *server_idx = beginp->index; break; } mid = midp->point; prev = (midp == beginp) ? 0 : (midp-1)->point; if (digest <= mid && digest > prev) { /* we found nearest server */ *server_idx = midp->index; break; } /* adjust the limits */ if (mid < digest) { lowp = midp + 1; } else { highp = midp - 1; } if (lowp > highp) { *server_idx = beginp->index; break; } } } else { *vbucket_id = vbucket_get_vbucket_by_key(vb, key, nkey); *server_idx = vbucket_get_master(vb, *vbucket_id); } return 0; }
uint32_t cluster_config_ketama_hash(struct cluster_config *config, const char *key, size_t nkey) { assert(config); return hash_ketama(key, nkey); }