Jdesk / memcached

Automatically exported from code.google.com/p/memcached
0 stars 0 forks source link

stale data in cache with binary protocol #8

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
The textual protocol does not allow stale data to persist in the cache in
case of memory allocation errors. The binary protocol allows it.

e.g:

Textual protocol:
////////////////////////
static void process_update_command(conn *c, token_t *tokens, const size_t
ntokens, int comm, bool handle_cas) {
.
.
.
    it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2);

    if (it == 0) {
        if (! item_size_ok(nkey, flags, vlen + 2))
            out_string(c, "SERVER_ERROR object too large for cache");
        else
            out_string(c, "SERVER_ERROR out of memory storing object");
        /* swallow the data line */
        c->write_and_go = conn_swallow;
        c->sbytes = vlen + 2;

        /* Avoid stale data persisting in cache because we failed alloc.
         * Unacceptable for SET. Anywhere else too? */
        if (comm == NREAD_SET) {
            it = item_get(key, nkey);
            if (it) {
                item_unlink(it);
                item_remove(it);
            }
        }
        return;
    }
.
.
.
}

Textual protocol:
////////////////////////

int do_store_item(item *it, int comm, conn *c) {
.
.
.
        if (comm == NREAD_APPEND || comm == NREAD_PREPEND) {
.
.
                new_it = do_item_alloc(key, it->nkey, flags,
old_it->exptime, it->nbytes + old_it->nbytes - 2 /* CRLF */);

                if (new_it == NULL) {
                    /* SERVER_ERROR out of memory */
                    if (old_it != NULL)
                        do_item_remove(old_it);
                    return 0;
                }
.
.
.
}

Binary protocol:
////////////////////////
static void process_bin_update(conn *c) {
.
.
.
    it = item_alloc(key, nkey, req->message.body.flags,
            realtime(req->message.body.expiration), vlen+2);

    if (it == 0) {
        if (! item_size_ok(nkey, req->message.body.flags, vlen + 2)) {
            write_bin_error(c, PROTOCOL_BINARY_RESPONSE_E2BIG, vlen);
        } else {
            write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, vlen);
        }
        /* swallow the data line */
        c->write_and_go = conn_swallow;
        return;
    }
.
.
.
}

Binary protocol:
////////////////////////
static void process_bin_append_prepend(conn *c) {
.
.
.
    it = item_alloc(key, nkey, 0, 0, vlen+2);

    if (it == 0) {
        if (! item_size_ok(nkey, 0, vlen + 2)) {
            write_bin_error(c, PROTOCOL_BINARY_RESPONSE_E2BIG, vlen);
        } else {
            write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, vlen);
        }
        /* swallow the data line */
        c->write_and_go = conn_swallow;
        return;
    }
.
.
.
}

Original issue reported on code.google.com by Victor.K...@gmail.com on 17 Dec 2008 at 6:48

GoogleCodeExporter commented 9 years ago
Fixed (with test) in
http://github.com/dustin/memcached/commit/8ff14453be52fb43a1ba5d3fb372847db92753
0f

Original comment by dsalli...@gmail.com on 22 Jan 2009 at 12:58