コード例 #1
0
ファイル: app_ramcloud.c プロジェクト: ctbrowser/wheatserver
static void ramcloudRead(void *item, void *data)
{
    wstr i = *(wstr*)item;
    struct ramcloudData *d = data;
    uint32_t actual_len;
    uint64_t version;
    uint64_t len = RAMCLOUD_DEFAULT_VALUE_LEN;

    wheatLog(WHEAT_DEBUG, "%s read key %s", __func__, i);
    wstr val = wstrNewLen(NULL, len);
    Status s = rc_read(global.client, d->table_id, i, wstrlen(i), NULL, &version, val, len, &actual_len);
    if (s != STATUS_OK) {
        if (s != STATUS_OBJECT_DOESNT_EXIST) {
            wheatLog(WHEAT_WARNING, " failed to read %s: %s", i, statusToString(s));
        }
        wstrFree(val);
        return ;
    }

    while (actual_len > len) {
        wstrFree(val);
        len = actual_len;
        val = wstrNewLen(NULL, actual_len);
        if (val == NULL) {
            wheatLog(WHEAT_WARNING, " failed to alloc memory");
            return ;
        }

        s = rc_read(global.client, d->table_id, i, wstrlen(i), NULL, &version, val, len, &actual_len);
        if (s != STATUS_OK) {
            if (s != STATUS_OBJECT_DOESNT_EXIST) {
                wheatLog(WHEAT_WARNING, " failed to read %s: %s", i, statusToString(s));
            }
            wstrFree(val);
            return ;
        }
    }

    d->retrieval_len += actual_len;
    arrayPush(d->retrievals, &val);
    struct slice ss = {(uint8_t*)(i), wstrlen(i)};
    arrayPush(d->retrievals_keys, &ss);
    ss.data = (uint8_t*)val;
    ss.len = actual_len - FLAG_SIZE;
    arrayPush(d->retrievals_vals, &ss);
    arrayPush(d->retrievals_flags, &val[actual_len-FLAG_SIZE]);
    arrayPush(d->retrievals_versions, &version);
}
コード例 #2
0
ファイル: worker.c プロジェクト: alemic/wheatserver
void registerConnFree(struct conn *conn, void (*clean)(void*), void *data)
{
    struct callback cleanup;
    cleanup.func = clean;
    cleanup.data = data;
    arrayPush(conn->cleanup, &cleanup);
}
コード例 #3
0
ファイル: hashkit.c プロジェクト: alemic/wheatserver
// 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;
}
コード例 #4
0
ファイル: proto_memcache.c プロジェクト: clareSun/wheatserver
static ssize_t memcacheParseReq(struct memcacheProcData *r, struct slice *s)
{
    char *m;
    char ch;
    size_t command_len;

    size_t pos = 0;
    uint64_t left = 0;
    struct slice val_s;
    enum reqStage state = r->stage;
    r->token_pos = 0;
    while (pos < s->len) {
        ch = s->data[pos];

        switch (state) {
        case SW_START:
            if (!islower(ch)) {
                goto error;
            }

            r->token_pos = pos;
            state = SW_REQ_TYPE;
            break;

        case SW_REQ_TYPE:
            if (ch == ' ' || ch == CR) {
                r->type = UNKNOWN;
                if (wstrlen(r->command)) {
                    r->command = wstrCatLen(r->command, (char *)&s->data[r->token_pos], pos);
                    command_len = wstrlen(r->command);
                    m = (char*)&r->command;
                } else {
                    command_len = pos - r->token_pos;
                    m = (char*)&s->data[r->token_pos];
                }

                switch (command_len) {

                case 3:
                    if (str4icmp(m, 'g', 'e', 't', ' ')) {
                        r->type = REQ_MC_GET;
                        break;
                    }

                    if (str4icmp(m, 's', 'e', 't', ' ')) {
                        r->type = REQ_MC_SET;
                        break;
                    }

                    if (str4icmp(m, 'a', 'd', 'd', ' ')) {
                        r->type = REQ_MC_ADD;
                        break;
                    }

                    if (str4icmp(m, 'c', 'a', 's', ' ')) {
                        r->type = REQ_MC_CAS;
                        break;
                    }

                    break;

                case 4:
                    if (str4icmp(m, 'g', 'e', 't', 's')) {
                        r->type = REQ_MC_GETS;
                        break;
                    }

                    if (str4icmp(m, 'i', 'n', 'c', 'r')) {
                        r->type = REQ_MC_INCR;
                        break;
                    }

                    if (str4icmp(m, 'd', 'e', 'c', 'r')) {
                        r->type = REQ_MC_DECR;
                        break;
                    }

                    if (str4icmp(m, 'q', 'u', 'i', 't')) {
                        r->type = REQ_MC_QUIT;
                        r->quit = 1;
                        break;
                    }

                    break;

                case 6:
                    if (str6icmp(m, 'a', 'p', 'p', 'e', 'n', 'd')) {
                        r->type = REQ_MC_APPEND;
                        break;
                    }

                    if (str6icmp(m, 'd', 'e', 'l', 'e', 't', 'e')) {
                        r->type = REQ_MC_DELETE;
                        break;
                    }

                    break;

                case 7:
                    if (str7icmp(m, 'p', 'r', 'e', 'p', 'e', 'n', 'd')) {
                        r->type = REQ_MC_PREPEND;
                        break;
                    }

                    if (str7icmp(m, 'r', 'e', 'p', 'l', 'a', 'c', 'e')) {
                        r->type = REQ_MC_REPLACE;
                        break;
                    }

                    break;
                }

                switch (r->type) {
                case REQ_MC_GET:
                case REQ_MC_GETS:
                case REQ_MC_DELETE:
                case REQ_MC_CAS:
                case REQ_MC_SET:
                case REQ_MC_ADD:
                case REQ_MC_REPLACE:
                case REQ_MC_APPEND:
                case REQ_MC_PREPEND:
                case REQ_MC_INCR:
                case REQ_MC_DECR:
                    if (ch == CR) {
                        goto error;
                    }
                    state = SW_SPACES_BEFORE_KEY;
                    break;

                case REQ_MC_QUIT:
                    pos--; /* go back by 1 byte */
                    state = SW_CRLF;
                    break;

                case UNKNOWN:
                    goto error;

                default:
                    ASSERT(0);
                }
            } else if (!islower(ch)) {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_KEY:
            if (ch != ' ') {
                pos--; /* go back by 1 byte */
                r->token_pos = -1;
                state = SW_KEY;
            }
            break;

        case SW_KEY:
            if (r->token_pos == -1) {
                r->token_pos = pos;
            }
            if (ch == ' ' || ch == CR) {
                if (wstrlen(r->key) + (pos - r->token_pos) > MEMCACHE_MAX_KEY_LENGTH) {
                    wheatLog(WHEAT_WARNING,
                             "parsed bad type %d with key prefix '%d' and length %d that exceeds "
                             "maximum key length", r->type, r->token_pos, pos);
                    goto error;
                }

                r->key = wstrCatLen(r->key, (char*)&s->data[r->token_pos], pos - r->token_pos);
                arrayPush(r->keys, &r->key);
                r->key = wstrNewLen(NULL, 64);

                r->token_pos = -1;

                /* get next state */
                if (memcache_storage(r)) {
                    state = SW_SPACES_BEFORE_FLAGS;
                } else if (memcache_arithmetic(r)) {
                    state = SW_SPACES_BEFORE_NUM;
                } else if (memcache_delete(r)) {
                    // whether exist delay time
                    if (ch == ' ')
                        state = SW_SPACES_BEFORE_NUM;
                    else
                        state = SW_RUNTO_CRLF;
                } else if (memcache_retrieval(r)) {
                    state = SW_SPACES_BEFORE_KEYS;
                } else {
                    state = SW_RUNTO_CRLF;
                }

                if (ch == CR) {
                    if (memcache_storage(r) || memcache_arithmetic(r)) {
                        goto error;
                    }
                    pos--; /* go back by 1 byte */
                }
            }

            break;

        case SW_SPACES_BEFORE_KEYS:
            ASSERT(memcache_retrieval(r));
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                r->token_pos = -1;
                pos--; /* go back by 1 byte */
                state = SW_KEY;
            }

            break;

        case SW_SPACES_BEFORE_FLAGS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                r->flag = ch - '0';
                state = SW_FLAGS;
            }

            break;

        case SW_FLAGS:
            if (isdigit(ch)) {
                r->flag = r->flag * 10 + (ch - '0');
            } else if (ch == ' ') {
                state = SW_SPACES_BEFORE_EXPIRY;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_EXPIRY:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* expiry_start <- p; expiry <- ch - '0' */
                r->expire = ch - '0';
                state = SW_EXPIRY;
            }

            break;

        case SW_EXPIRY:
            if (isdigit(ch)) {
                r->expire = r->expire * 10 + (ch - '0');
            } else if (ch == ' ') {
                state = SW_SPACES_BEFORE_VLEN;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_VLEN:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* vlen_start <- p */
                r->vlen = ch - '0';
                state = SW_VLEN;
            }

            break;

        case SW_VLEN:
            if (isdigit(ch)) {
                r->vlen = r->vlen * 10 + (uint32_t)(ch - '0');
            } else if (memcache_cas(r)) {
                if (ch != ' ') {
                    goto error;
                }
                pos--; /* go back by 1 byte */
                state = SW_SPACES_BEFORE_CAS;
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_CAS:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                /* cas_start <- p; cas <- ch - '0' */
                r->cas = ch - '0';
                state = SW_CAS;
            }

            break;

        case SW_CAS:
            if (isdigit(ch)) {
                r->cas = r->cas * 10 + (ch - '0');
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;


        case SW_RUNTO_VAL:
            switch (ch) {
            case LF:
                /* val_start <- p + 1 */
                state = SW_VAL;
                r->vlen_left = r->vlen;
                break;

            default:
                goto error;
            }

            break;

        case SW_VAL:
            if (r->vlen_left) {
                left = (s->len - pos) >= r->vlen ? (r->vlen) : (s->len-pos);
                val_s.len = left;
                val_s.data = &s->data[pos];
                arrayPush(r->vals, &val_s);
                r->vlen_left -= left;
                pos += left;
            }
            switch (s->data[pos]) {
            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_SPACES_BEFORE_NUM:
            if (ch != ' ') {
                if (!isdigit(ch)) {
                    goto error;
                }
                r->num = ch - '0';
                state = SW_NUM;
            }

            break;

        case SW_NUM:
            if (isdigit(ch)) {
                r->num = r->num * 10 + ch - '0';
            } else if (ch == ' ' || ch == CR) {
                pos--; /* go back by 1 byte */
                state = SW_RUNTO_CRLF;
            } else {
                goto error;
            }

            break;

        case SW_RUNTO_CRLF:
            switch (ch) {
            case ' ':
                break;

            case 'n':
                if (memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r)) {
                    state = SW_NOREPLY;
                    r->noreply_banner = wstrNewLen(NULL, 8);
                    r->token_pos = pos;
                } else {
                    goto error;
                }

                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }

                break;

            default:
                goto error;
            }

            break;

        case SW_NOREPLY:
            switch (ch) {
            case ' ':
            case CR:
                r->noreply_banner = wstrCatLen(r->noreply_banner, (char*)&s->data[r->token_pos], pos - r->token_pos);
                if (str7icmp(r->noreply_banner, 'n', 'o', 'r', 'e', 'p', 'l', 'y')) {
                    ASSERT(memcache_storage(r) || memcache_arithmetic(r) || memcache_delete(r));
                    /* noreply_end <- p - 1 */
                    r->noreply = 1;
                    state = SW_AFTER_NOREPLY;
                    pos--; /* go back by 1 byte */
                } else {
                    goto error;
                }
            }

            break;

        case SW_AFTER_NOREPLY:
            switch (ch) {
            case ' ':
                break;

            case CR:
                if (memcache_storage(r)) {
                    state = SW_RUNTO_VAL;
                } else {
                    state = SW_ALMOST_DONE;
                }
                break;

            default:
                goto error;
            }

            break;

        case SW_CRLF:
            switch (ch) {
            case ' ':
                break;

            case CR:
                state = SW_ALMOST_DONE;
                break;

            default:
                goto error;
            }

            break;

        case SW_ALMOST_DONE:
            switch (ch) {
            case LF:
                /* req_end <- p */
                pos++;
                goto done;

            default:
                goto error;
            }

            break;

        case SW_SENTINEL:
        default:
            ASSERT(0);
            break;

        }
        pos++;
    }

    if (state == SW_REQ_TYPE) {
        r->command = wstrCatLen(r->command, (char*)&s->data[r->token_pos], pos - r->token_pos);
    } else if (state == SW_KEY) {
        r->key = wstrCatLen(r->key, (char*)&s->data[r->token_pos], pos - r->token_pos);
    } else if (state == SW_NOREPLY) {
        r->noreply_banner = wstrCatLen(r->noreply_banner, (char*)&s->data[r->token_pos], pos - r->token_pos);
    }

done:
    r->stage = state;
    wheatLog(WHEAT_DEBUG, "parsed successfully type %d state %d", r->type, r->stage);
    return pos;

error:
    wheatLog(WHEAT_DEBUG, "parsed failed type %d state %d: %s", r->type, r->stage,
             s->data);
    return -1;
}