Exemple #1
0
static void buildRetrievalResponse(struct ramcloudData *d, int cas)
{
    int i = 0;
    char buf[64];
    ASSERT(!d->retrieval_response);
    // Estimate value avoid realloc
    d->retrieval_response = wstrNewLen(NULL, d->retrieval_len+narray(d->retrievals_vals)*64);
    for (; i < narray(d->retrievals_vals); ++i) {
        struct slice *val = arrayIndex(d->retrievals_vals, i);
        struct slice *key = arrayIndex(d->retrievals_keys, i);
        uint16_t *flag = arrayIndex(d->retrievals_flags, i);
        uint64_t *v = arrayIndex(d->retrievals_versions, i);
        d->retrieval_response = wstrCatLen(d->retrieval_response, VALUE, 5);
        d->retrieval_response = wstrCatLen(d->retrieval_response, " ", 1);
        d->retrieval_response = wstrCatLen(d->retrieval_response, (char*)key->data, key->len);
        d->retrieval_response = wstrCatLen(d->retrieval_response, " ", 1);
        int l = sprintf(buf, "%d", *flag);
        d->retrieval_response = wstrCatLen(d->retrieval_response, buf, l);
        d->retrieval_response = wstrCatLen(d->retrieval_response, " ", 1);
        l = sprintf(buf, "%ld", val->len);
        d->retrieval_response = wstrCatLen(d->retrieval_response, buf, l);
        if (cas) {
            d->retrieval_response = wstrCatLen(d->retrieval_response, " ", 1);
            l = sprintf(buf, "%llu", *v);
            d->retrieval_response = wstrCatLen(d->retrieval_response, buf, l);
        }
        d->retrieval_response = wstrCatLen(d->retrieval_response, CRLF, 2);
        d->retrieval_response = wstrCatLen(d->retrieval_response, (char*)val->data, val->len);
        d->retrieval_response = wstrCatLen(d->retrieval_response, CRLF, 2);
    }

    d->retrieval_response = wstrCatLen(d->retrieval_response, END, 3);
    d->retrieval_response = wstrCatLen(d->retrieval_response, CRLF, 2);
}
Exemple #2
0
static void ramcloudSet(struct ramcloudData *d, wstr key, struct array *vals, uint32_t vlen, uint16_t flag, struct RejectRules *rule)
{
    wheatLog(WHEAT_DEBUG, "%s set key %s", __func__, key);
    uint64_t version;
    int i = 0;
    struct slice *slice;
    wstr val = wstrNewLen(NULL, vlen+sizeof(flag));
    while (i < narray(vals)) {
        slice = arrayIndex(vals, i);
        val = wstrCatLen(val, (char*)slice->data, slice->len);
        ++i;
    }
    val = wstrCatLen(val, (char*)&flag, FLAG_SIZE);

    Status s = rc_write(global.client, d->table_id, key, wstrlen(key), val, wstrlen(val),
                        rule, &version);
    wstrFree(val);
    if (s != STATUS_OK) {
        // cas command
        if (rule->versionNeGiven) {
            if (s == STATUS_WRONG_VERSION)
                sliceTo(&d->storage_response, (uint8_t*)EXISTS, sizeof(EXISTS)-1);
            else if (s == STATUS_OBJECT_DOESNT_EXIST)
                sliceTo(&d->storage_response, (uint8_t*)NOT_FOUND, sizeof(NOT_FOUND)-1);
        } else if ((rule->doesntExist && s == STATUS_OBJECT_DOESNT_EXIST) ||
                   (rule->exists && s == STATUS_OBJECT_EXISTS)) {
            sliceTo(&d->storage_response, (uint8_t*)NOT_STORED, sizeof(NOT_STORED)-1);
        } else {
            wheatLog(WHEAT_WARNING, "%s failed to set %s: %s", __func__, key, statusToString(s));
            sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
        }
    } else {
        sliceTo(&d->storage_response, (uint8_t*)STORED, sizeof(STORED)-1);
    }
}
Exemple #3
0
// Only called when config-server is not specifyed. Means that WheatRedis is
// firstly running on your system.
int hashInit(struct redisServer *server)
{
    ASSERT(narray(server->instances) >= server->nbackup);
    struct redisInstance *instance;
    size_t ntoken, ninstance, swap;
    int i, prev_idx;
    struct token *tokens = server->tokens, *last_token = NULL;

    ntoken = WHEAT_KEYSPACE;
    tokens = wmalloc(sizeof(struct token)*ntoken);
    if (!tokens)
        return WHEAT_WRONG;
    server->tokens = tokens;

    ninstance = narray(server->instances);
    for (i = 0; i < ntoken; ++i) {
        instance = arrayIndex(server->instances, i%ninstance);
        tokens[i].next_instance = UINT32_MAX; // An impossible value
        tokens[i].pos = i;
        tokens[i].instance_id = i%ninstance;
        instance->ntoken++;
    }

    // shuffle
    for (i = 0; i < ntoken; i++)
    {
        size_t j = i + rand() / (RAND_MAX / (ntoken - i) + 1);
        swap = tokens[j].instance_id;
        tokens[j].instance_id = tokens[i].instance_id;
        tokens[i].instance_id = swap;
    }

    // Populate each token.next_instance to quicker search node process
    prev_idx = 0;
    i = 1;
    last_token = &tokens[ntoken-1];
    while (last_token->next_instance == UINT32_MAX) {
        if (tokens[i%ntoken].instance_id != tokens[prev_idx].instance_id) {
            for (; prev_idx < i && prev_idx < ntoken; ++prev_idx)
                tokens[prev_idx].next_instance = i%ntoken;
        }
        ++i;
    }
    server->ntoken = ntoken;
    return WHEAT_OK;
}
wstr getMemcacheKey(void *data)
{
    struct memcacheProcData *d = data;
    if (narray(d->keys))
        return *(wstr*)arrayTop(d->keys);
    else
        return d->key;
}
Exemple #5
0
// hashAdd is used when a new redis server add to rebalance tokens
int hashAdd(struct redisServer *server, wstr ip, int port, int id)
{
    size_t ninstance, ntoken_per_instance, extra_ntoken, target_idx, ntoken;
    struct token *token, *tokens;
    struct redisInstance *instance, *target_instance;
    struct redisInstance add_instance;
    size_t *sub_ntoken;
    int i;

    if (initInstance(&add_instance, id, ip, port, DIRTY) == WHEAT_WRONG)
        return WHEAT_WRONG;
    arrayPush(server->instances, &add_instance);

    // `sub_ntoken`'s element is the amount of tokens every instance should
    // take out
    ninstance = narray(server->instances);
    sub_ntoken = wmalloc(sizeof(int)*ninstance);
    ntoken_per_instance = WHEAT_KEYSPACE / ninstance;
    extra_ntoken = WHEAT_KEYSPACE % ninstance;
    for (i = 0; i < ninstance; i++) {
        instance = arrayIndex(server->instances,i);
        sub_ntoken[i] = instance->ntoken - ntoken_per_instance;
    }
    if (!extra_ntoken) {
        for (i = 0; i < extra_ntoken; i++) {
            sub_ntoken[i]--;
        }
    }

    target_idx = ninstance-1;
    extra_ntoken = sub_ntoken[target_idx];
    target_instance = arrayIndex(server->instances, target_idx);
    token = tokens = &server->tokens[0];
    while (extra_ntoken) {
        size_t skip = random() % ntoken_per_instance + 1;
        while (skip--) {
            token = &tokens[token->next_instance];
        }
        if (token->instance_id != target_idx &&
                sub_ntoken[token->instance_id]) {
            wheatLog(WHEAT_DEBUG, "token: %d", token->pos);
            instance = arrayIndex(server->instances, token->instance_id);
            token->instance_id = target_idx;
            instance->ntoken--;
            target_instance->ntoken++;
        }
    }

    ntoken = 0;
    for (i = 0; i < ninstance; i++) {
        instance = arrayIndex(server->instances,i);
        ntoken += instance->ntoken;
    }
    ASSERT(ntoken == WHEAT_KEYSPACE);

    wfree(sub_ntoken);
    return WHEAT_OK;
}
Exemple #6
0
void initWorkerProcess(struct workerProcess *worker, char *worker_name)
{
    struct configuration *conf;
    int i;
    struct app *app;
    struct moduleAttr *module;

    if (Server.stat_fd != 0)
        close(Server.stat_fd);
    setProctitle(worker_name);
    worker->pid = getpid();
    worker->ppid = getppid();
    worker->alive = 1;
    worker->start_time = Server.cron_time;
    worker->worker = spotWorker(worker_name);
    worker->master_stat_fd = 0;
    ASSERT(worker->worker);
    worker->stats = NULL;
    initWorkerSignals();
    worker->center = eventcenterInit(WHEAT_CLIENT_MAX);
    if (!worker->center) {
        wheatLog(WHEAT_WARNING, "eventcenter_init failed");
        halt(1);
    }
    if (createEvent(worker->center, Server.ipfd, EVENT_READABLE, acceptClient,  NULL) == WHEAT_WRONG)
    {
        wheatLog(WHEAT_WARNING, "createEvent failed");
        halt(1);
    }

    // It may nonblock after fork???
    if (wheatNonBlock(Server.neterr, Server.ipfd) == NET_WRONG) {
        wheatLog(WHEAT_WARNING, "Set nonblock %d failed: %s", Server.ipfd, Server.neterr);
        halt(1);
    }

    module = NULL;
    conf = getConfiguration("protocol");
    if (conf->target.ptr) {
        module = getModule(PROTOCOL, conf->target.ptr);
        if (module && getProtocol(module)->initProtocol() == WHEAT_WRONG) {
            wheatLog(WHEAT_WARNING, "init protocol failed");
            halt(1);
        }
    }
    if (!module) {
        wheatLog(WHEAT_WARNING, "find protocol %s failed", conf->target.ptr);
        halt(1);
    }
    worker->protocol = getProtocol(module);

    StatTotalClient = getStatItemByName("Total client");
    gettimeofday(&Server.cron_time, NULL);
    if (worker->worker->setup)
        worker->worker->setup();
    WorkerProcess->refresh_time = Server.cron_time.tv_sec;

    FreeClients = createAndFillPool();
    Clients = createList();
    StatBufferSize = getStatItemByName("Max buffer size");
    StatTotalRequest = getStatItemByName("Total request");
    StatFailedRequest = getStatItemByName("Total failed request");
    StatRunTime = getStatItemByName("Worker run time");

    worker->apps = arrayCreate(sizeof(struct app*), 3);
    if (!worker->apps) {
        wheatLog(WHEAT_WARNING, "array create failed");
        halt(1);
    }

    getAppsByProtocol(worker->apps, worker->protocol);
    for (i = 0; i < narray(worker->apps); i++) {
        app = *(struct app**)arrayIndex(worker->apps, i);
        if (app->initApp(worker->protocol) == WHEAT_WRONG) {
            wheatLog(WHEAT_WARNING, "init app failed %s", getModuleName(APP, app));
            halt(1);
        }
    }

    sendStatPacket(WorkerProcess);
}
Exemple #7
0
static void ramcloudAppend(struct ramcloudData *d, wstr key, struct array *vals, uint32_t vlen, uint16_t flag, int append)
{
    uint32_t actual_len;
    uint64_t version;
    uint64_t len = RAMCLOUD_DEFAULT_VALUE_LEN;

again:
    wheatLog(WHEAT_DEBUG, "%s read key %s", __func__, key);

    wstr origin_val = wstrNewLen(NULL, len);
    wstr val;
    Status s = rc_read(global.client, d->table_id, key, wstrlen(key), NULL, &version, origin_val, len, &actual_len);
    if (s != STATUS_OK) {
        if (s != STATUS_OBJECT_DOESNT_EXIST) {
            wheatLog(WHEAT_WARNING, " failed to read %s: %s", key, statusToString(s));
            sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
        } else {
            sliceTo(&d->storage_response, (uint8_t*)NOT_STORED, sizeof(NOT_STORED)-1);
        }
        wstrFree(origin_val);
        return ;
    }

    while (actual_len > len) {
        wstrFree(origin_val);
        len = actual_len;
        origin_val = wstrNewLen(NULL, actual_len);
        if (origin_val == NULL) {
            sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
            wheatLog(WHEAT_WARNING, " failed to alloc memory");
            return ;
        }

        s = rc_read(global.client, d->table_id, key, wstrlen(key), NULL, &version, origin_val, len, &actual_len);
        if (s != STATUS_OK) {
            if (s != STATUS_OBJECT_DOESNT_EXIST) {
                wheatLog(WHEAT_WARNING, " failed to read %s: %s", key, statusToString(s));
                sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
            } else {
                sliceTo(&d->storage_response, (uint8_t*)NOT_STORED, sizeof(NOT_STORED)-1);
            }
            wstrFree(origin_val);
            return ;
        }
    }

    wstrupdatelen(origin_val, actual_len-FLAG_SIZE);
    if (append) {
        val = origin_val;
        // reduce flag size
    } else {
        val = wstrNewLen(NULL, vlen);
    }

    int i = 0;
    while (i < narray(vals)) {
        struct slice *slice;
        slice = arrayIndex(vals, i);
        val = wstrCatLen(val, (char*)slice->data, slice->len);
        len += slice->len;
        ++i;
    }

    if (!append) {
        val = wstrCatLen(val, origin_val, wstrlen(origin_val));
        wstrFree(origin_val);
    }
    val = wstrCatLen(val, (char*)&flag, FLAG_SIZE);

    struct RejectRules rule;
    memset(&rule, 0, sizeof(rule));
    rule.doesntExist = 1;
    rule.versionNeGiven = 1;
    rule.givenVersion = version;
    s = rc_write(global.client, d->table_id, key, wstrlen(key), val, wstrlen(val),
                        &rule, NULL);
    wstrFree(val);
    if (s != STATUS_OK) {
        if (s == STATUS_OBJECT_DOESNT_EXIST) {
            sliceTo(&d->storage_response, (uint8_t*)NOT_STORED, sizeof(NOT_STORED)-1);
            return ;
        } else if (s == STATUS_WRONG_VERSION) {
            goto again;
        }

        wheatLog(WHEAT_WARNING, " failed to write %s: %s", key, statusToString(s));
        sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
        return ;
    }
    sliceTo(&d->storage_response, (uint8_t*)STORED, sizeof(STORED)-1);
}