Esempio n. 1
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);
    }
}
Esempio n. 2
0
static void ramcloudDelete(struct ramcloudData* d, wstr key, struct RejectRules *rule)
{
    wheatLog(WHEAT_DEBUG, "%s delete key %s", __func__, key);
    uint64_t version;
    Status s = rc_remove(global.client, d->table_id, key, wstrlen(key), rule, &version);
    if (s != STATUS_OK) {
        if (s == STATUS_OBJECT_DOESNT_EXIST) {
            sliceTo(&d->storage_response, (uint8_t*)NOT_FOUND, sizeof(NOT_FOUND)-1);
        } else {
            wheatLog(WHEAT_WARNING, "%s failed to remove %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*)DELETED, sizeof(DELETED)-1);
    }
}
Esempio n. 3
0
static void appendSliceToSendQueue(struct conn *conn, struct slice *s)
{
    struct sendPacket *packet = wmalloc(sizeof(*packet));
    if (!packet)
        setClientUnvalid(conn->client);
    packet->type = SLICE;
    sliceTo(&packet->target.slice, s->data, s->len);
    appendToListTail(conn->send_queue, packet);
}
Esempio n. 4
0
int callRamcloud(struct conn *c, void *arg)
{
    enum memcacheCommand command = getMemcacheCommand(c->protocol_data);
    struct RejectRules rule;
    struct ramcloudData *d = c->app_private_data;
    int owner = c->client->owner;
    uint64_t table_id;
    ASSERT(owner);
    if (getTableId(owner, &table_id) < 0) {
        sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
        sendMemcacheResponse(c, &d->storage_response);
        return WHEAT_OK;
    }
    d->table_id = table_id;
    memset(&rule, 0, sizeof(rule));
    switch (command) {
        case REQ_MC_GET:
        case REQ_MC_GETS:
            d->retrievals = arrayCreate(sizeof(wstr), 1);
            d->retrievals_keys = arrayCreate(sizeof(struct slice), 1);
            d->retrievals_vals = arrayCreate(sizeof(struct slice), 1);
            d->retrievals_flags = arrayCreate(FLAG_SIZE, 1);
            d->retrievals_versions = arrayCreate(sizeof(uint64_t), 1);
            arrayEach2(getMemcacheKeys(c->protocol_data), ramcloudRead, d);
            buildRetrievalResponse(d, command == REQ_MC_GETS ? 1 : 0);
            sliceTo(&d->storage_response, (uint8_t*)d->retrieval_response, wstrlen(d->retrieval_response));
            break;

        case REQ_MC_DELETE:
            rule.doesntExist = 1;
            ramcloudDelete(d, getMemcacheKey(c->protocol_data), &rule);
            break;

        case REQ_MC_ADD:
            rule.exists = 1;
            ramcloudSet(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                        getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), &rule);
            break;

        case REQ_MC_REPLACE:
            rule.doesntExist = 1;
            ramcloudSet(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                        getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), &rule);
            break;

        case REQ_MC_CAS:
            rule.givenVersion = getMemcacheCas(c->protocol_data);
            rule.versionNeGiven = 1;
            rule.doesntExist = 1;
            ramcloudSet(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                        getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), &rule);
            break;

        case REQ_MC_SET:
            ramcloudSet(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                        getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), &rule);
            break;

        case REQ_MC_INCR:
            ramcloudIncr(d, getMemcacheKey(c->protocol_data), getMemcacheNum(c->protocol_data), 1);
            break;

        case REQ_MC_DECR:
            ramcloudIncr(d, getMemcacheKey(c->protocol_data), getMemcacheNum(c->protocol_data), 0);
            break;

        case REQ_MC_APPEND:
            ramcloudAppend(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                           getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), 1);
            break;

        case REQ_MC_PREPEND:
            ramcloudAppend(d, getMemcacheKey(c->protocol_data), getMemcacheVal(c->protocol_data),
                           getMemcacheValLen(c->protocol_data), getMemcacheFlag(c->protocol_data), 0);
            break;

        default:
            ASSERT(0);
    }

    sendMemcacheResponse(c, &d->storage_response);

    return WHEAT_OK;
}
Esempio n. 5
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);
}
Esempio n. 6
0
static void ramcloudIncr(struct ramcloudData *d, wstr key, uint64_t num, int positive)
{
    if (num > INT64_MAX) {
        wheatLog(WHEAT_WARNING, "%s num %ld can't larger than %ld", __func__, num, INT64_MAX);
        sliceTo(&d->storage_response, (uint8_t*)CLIENT_ERROR, sizeof(CLIENT_ERROR)-1);
        return ;
    }

    static int max_len = 100;
    char value[max_len];
    uint32_t actual_len;
    uint64_t version;
    uint16_t flag;

again:
    wheatLog(WHEAT_DEBUG, "%s incr key %s %ld", __func__, key, num);
    Status s = rc_read(global.client, d->table_id, key, wstrlen(key), NULL, &version, value, max_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_FOUND, sizeof(NOT_FOUND)-1);
        }
        return ;
    }

    if (actual_len > max_len) {
        sliceTo(&d->storage_response, (uint8_t*)CLIENT_ERROR, sizeof(CLIENT_ERROR)-1);
        return ;
    }

    flag = *(uint16_t*)&value[actual_len-FLAG_SIZE];
    value[actual_len-FLAG_SIZE] = '\0';
    long long n = atoll(value);
    if (n == 0) {
        if (value[0] != '0') {
            sliceTo(&d->storage_response, (uint8_t*)CLIENT_ERROR, sizeof(CLIENT_ERROR)-1);
            return ;
        }
    }
    if (positive) {
        n += num;
    } else {
        if (num > n)
            n = 0;
        else
            n -= num;
    }
    int l = sprintf(value, "%llu", n);
    memcpy(&value[l], &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), value, l+FLAG_SIZE,
                 &rule, &version);
    if (s != STATUS_OK) {
        if (s == STATUS_WRONG_VERSION) {
            goto again;
        }

        if (s == STATUS_OBJECT_DOESNT_EXIST) {
            sliceTo(&d->storage_response, (uint8_t*)NOT_FOUND, sizeof(NOT_FOUND)-1);
            return ;
        }
        sliceTo(&d->storage_response, (uint8_t*)SERVER_ERROR, sizeof(SERVER_ERROR)-1);
        wheatLog(WHEAT_WARNING, "%s failed to incr %s: %s", __func__, key, statusToString(s));
        return ;
    } else {
        l = sprintf(value, "%llu\r\n", n);
        d->retrieval_response = wstrNewLen(value, l);
        sliceTo(&d->storage_response, (uint8_t*)d->retrieval_response, wstrlen(d->retrieval_response));
    }
}