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;
}
Exemple #3
0
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);
}