Exemple #1
0
static struct item* _item_alloc(uint8_t id, char *key, uint16_t nkey, int exptime, char *value, uint32_t nbyte) {
    struct item *it;
    struct item *uit;
    assert(id >= SLABCLASS_MIN_ID && id <= SLABCLASS_MAX_ID);
    it = item_get_from_lruq(id);
    if (it != NULL && item_expired(it)) {
        item_reuse(it);
        goto done;
    }
    uit = (settings.evict_opt & EVICT_LRU)? it : NULL;
    it = slab_get_item(id);
    if (it != NULL) {
        goto done;
    }
    if (uit != NULL) {
        it = uit;
        item_reuse(it);
        goto done;
    }
    return NULL;
done:
    assert(it->id == id);
    assert(!item_is_linked(it));
    assert(!item_is_slabbed(it));
    assert(it->offset != 0);
    assert(it->refcount == 0);
    it->flags = 0;
    it->nbyte = nbyte;
    it->exptime = exptime + time_now();
    it->nkey = nkey;
    memcpy(item_key(it), key, nkey);
    memcpy(item_key(it) + nkey, value, nbyte);
    return it;
}
Exemple #2
0
static void
req_process_add(struct context *ctx, struct conn *conn, struct msg *msg)
{
    struct itemx *itx;
    struct item *it;

    /* add, adds only if the mapping is not present */
    itx = itemx_getx(msg->hash, msg->md);
    if (itx != NULL) {
        it = slab_read_item(itx->sid, itx->offset);
        /* if the item hasn't expired yet */
        if(!item_expired(it)) {
            rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_STORED);
            return;
        }
    }

    req_process_set(ctx, conn, msg);
}
Exemple #3
0
static struct item* item_get_from_lruq(uint8_t id) {
    struct item *it;
    struct item *uit;
    uint32_t tries;
    if (!settings.use_lruq) {
        return NULL;
    }
    for (tries = ITEM_LRUQ_MAX_TRIES, it = TAILQ_FIRST(&item_lruq[id]), uit = NULL;
	it != NULL && tries > 0; tries--, it = TAILQ_NEXT(it, i_tqe)) {
        if (it->refcount != 0) {
            continue;
        }
        if (item_expired(it)) {
            return it;
        } else if (uit == NULL) {
            uit = it;
        }
    }
    return uit;
}
Exemple #4
0
static void
req_process_get(struct context *ctx, struct conn *conn, struct msg *msg)
{
    struct itemx *itx;
    struct item *it;

    itx = itemx_getx(msg->hash, msg->md);
    if (itx == NULL) {
        msg_type_t type;

        /*
         * On a miss, we send a "END\r\n" response, unless the request
         * is an intermediate fragment in a fragmented request.
         */
        if (msg->frag_id == 0 || msg->last_fragment) {
            type = MSG_RSP_END;
        } else {
            type = MSG_EMPTY;
        }

        rsp_send_status(ctx, conn, msg, type);
        return;
    }

    /*
     * On a hit, we read the item with address [sid, offset] and respond
     * with item value if the item hasn't expired yet.
     */
    it = slab_read_item(itx->sid, itx->offset);
    if (it == NULL) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_SERVER_ERROR, errno);
        return;
    }
    if (item_expired(it)) {
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_FOUND);
        return;
    }

    rsp_send_value(ctx, conn, msg, it, itx->cas);
}
Exemple #5
0
static void
req_process_replace(struct context *ctx, struct conn *conn, struct msg *msg)
{
    struct itemx *itx;
    struct item *it;

    /*  replace, only replaces if the mapping is present */
    itx = itemx_getx(msg->hash, msg->md);
    if (itx == NULL) {
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_STORED);
        return;
    }

    /* if the item has expired */
    it = slab_read_item(itx->sid, itx->offset);
    if(item_expired(it)) {
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_STORED);
        return;
    }

    req_process_set(ctx, conn, msg);
}
Exemple #6
0
static void
req_process_num(struct context *ctx, struct conn *conn, struct msg *msg)
{
    rstatus_t status;
    uint8_t *key, nkey, cid;
    struct item *it;
    struct itemx *itx;
    uint64_t cnum, nnum;
    char numstr[FC_UINT64_MAXLEN];
    int n;

    key = msg->key_start;
    nkey = (uint8_t)(msg->key_end - msg->key_start);

    /* 1). look up existing itemx */
    itx = itemx_getx(msg->hash, msg->md);
    if (itx == NULL) {
        /* 2a). miss -> return NOT_FOUND */
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_FOUND);
        return;
    }

    /* 2b). hit -> read existing item into it */
    it = slab_read_item(itx->sid, itx->offset);
    if (it == NULL) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_SERVER_ERROR, errno);
        return;
    }
    if (item_expired(it)) {
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_FOUND);
        return;
    }

    /* 3). sanity check item data to be a number */
    status = fc_atou64(item_data(it), it->ndata, &cnum);
    if (status != FC_OK) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_CLIENT_ERROR, EINVAL);
        return;
    }

    /* 4). remove existing itemx of it */
    itemx_removex(msg->hash, msg->md);

    /* 5). compute the new incr/decr number nnum and numstr */
    if (msg->type == MSG_REQ_INCR) {
        nnum = cnum + msg->num;
    } else {
        if (cnum < msg->num) {
            nnum = 0;
        } else {
            nnum = cnum - msg->num;
        }
    }
    n = fc_scnprintf(numstr, sizeof(numstr), "%"PRIu64"", nnum);

    /* 6). alloc new item that can hold n worth of bytes */
    cid = item_slabcid(nkey, n);
    ASSERT(cid != SLABCLASS_INVALID_ID);

    it = item_get(key, nkey, cid, n, time_reltime(msg->expiry), msg->flags,
                   msg->md, msg->hash);
    if (it == NULL) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_SERVER_ERROR, ENOMEM);
        return;
    }

    /* 7). copy numstr to it */
    fc_memcpy(item_data(it), numstr, n);

    rsp_send_num(ctx, conn, msg, it);
}
Exemple #7
0
static void
req_process_concat(struct context *ctx, struct conn *conn, struct msg *msg)
{
    uint8_t *key, nkey, cid;
    struct item *oit, *it;
    uint32_t ndata;
    struct itemx *itx;

    key = msg->key_start;
    nkey = (uint8_t)(msg->key_end - msg->key_start);

    /* 1). look up existing itemx */
    itx = itemx_getx(msg->hash, msg->md);
    if (itx == NULL) {
        /* 2a). miss -> return NOT_STORED */
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_STORED);
        return;
    }

    /* 2b). hit -> read existing item into oit */
    oit = slab_read_item(itx->sid, itx->offset);
    if (oit == NULL) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_SERVER_ERROR, errno);
        return;
    }
    if (item_expired(oit)) {
        rsp_send_status(ctx, conn, msg, MSG_RSP_NOT_STORED);
        return;
    }

    ndata = msg->vlen + oit->ndata;
    cid = item_slabcid(nkey, ndata);
    if (cid == SLABCLASS_INVALID_ID) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_CLIENT_ERROR, EINVAL);
        return;
    }

    /* 3). remove existing itemx of oit */
    itemx_removex(msg->hash, msg->md);

    /* 4). alloc new item that can hold ndata worth of bytes */
    it = item_get(key, nkey, cid, ndata, time_reltime(msg->expiry),
                  msg->flags, msg->md, msg->hash);
    if (it == NULL) {
        rsp_send_error(ctx, conn, msg, MSG_RSP_SERVER_ERROR, ENOMEM);
        return;
    }

    /* 5). copy data from msg to head or tail of new item it */
    switch (msg->type) {

    case MSG_REQ_PREPEND:
        mbuf_copy_to(&msg->mhdr, msg->value, item_data(it), msg->vlen);
        fc_memcpy(item_data(it) + msg->vlen, item_data(oit), oit->ndata);
        break;

    case MSG_REQ_APPEND:
        fc_memcpy(item_data(it), item_data(oit), oit->ndata);
        mbuf_copy_to(&msg->mhdr, msg->value, item_data(it) + oit->ndata, msg->vlen);
        break;

    default:
        NOT_REACHED();
    }

    rsp_send_status(ctx, conn, msg, MSG_RSP_STORED);
}