diff --git a/items.c b/items.c --- a/items.c +++ b/items.c @@ -17,6 +17,7 @@ /* Forward Declarations */ static void item_link_q(item *it); static void item_unlink_q(item *it); +static uint64_t get_cas_id(); /* * We only reposition items in the LRU queue if they haven't been repositioned @@ -37,6 +38,15 @@ void item_init(void) { tails[i] = NULL; sizes[i] = 0; } +} + +/* Get the next CAS id for a new item. */ +uint64_t get_cas_id() { + static uint64_t cas_id; + if(cas_id >= MAX_CAS_ID) { + cas_id = 0; + } + return ++cas_id; } /* Enable this for reference-count debugging. */ @@ -129,6 +139,7 @@ item *do_item_alloc(char *key, const siz it->it_flags = 0; it->nkey = nkey; it->nbytes = nbytes; + it->cas_id = get_cas_id(); strcpy(ITEM_key(it), key); it->exptime = exptime; memcpy(ITEM_suffix(it), suffix, (size_t)nsuffix); diff --git a/memcached.c b/memcached.c --- a/memcached.c +++ b/memcached.c @@ -1079,7 +1079,6 @@ static inline void process_get_command(c item *it; token_t *key_token = &tokens[KEY_TOKEN]; char suffix[255]; - uint32_t in_memory_ptr; assert(c != NULL); if (settings.managed) { @@ -1132,8 +1131,8 @@ static inline void process_get_command(c if(return_key_ptr == true) { - in_memory_ptr = (uint32_t)item_get(key, nkey); - sprintf(suffix," %d %d %lu\r\n", atoi(ITEM_suffix(it) + 1), it->nbytes - 2, in_memory_ptr); + sprintf(suffix," %d %d %llu\r\n", atoi(ITEM_suffix(it) + 1), + it->nbytes - 2, it->cas_id); if (add_iov(c, "VALUE ", 6) != 0 || add_iov(c, ITEM_key(it), it->nkey) != 0 || add_iov(c, suffix, strlen(suffix)) != 0 || @@ -1207,7 +1206,7 @@ static void process_update_command(conn int flags; time_t exptime; int vlen, old_vlen; - uint32_t req_memory_ptr, in_memory_ptr; + uint32_t req_cas_id; item *it, *old_it; assert(c != NULL); @@ -1227,7 +1226,7 @@ static void process_update_command(conn // does cas value exist? if(tokens[5].value) { - req_memory_ptr = strtoull(tokens[5].value, NULL, 10); + req_cas_id = strtoull(tokens[5].value, NULL, 10); } if(errno == ERANGE || ((flags == 0 || exptime == 0) && errno == EINVAL)) { @@ -1255,35 +1254,30 @@ static void process_update_command(conn it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); /* HANDLE_CAS VALIDATION */ - if (handle_cas == true) - { - item *itmp=item_get(key, it->nkey); - /* Release the reference */ - if(itmp) { - item_remove(itmp); - } - in_memory_ptr = (uint32_t)itmp; - if(in_memory_ptr == req_memory_ptr) - { - // validates allow the set - } - else if(in_memory_ptr) - { - out_string(c, "EXISTS"); + if (handle_cas == true) { + item *itmp=item_get(key, it->nkey); + if(itmp && itmp->cas_id == req_cas_id) { + // validates allow the set + if(itmp) { + item_remove(itmp); + } + } else if(itmp) { + out_string(c, "EXISTS"); - /* swallow the data line */ - c->write_and_go = conn_swallow; - c->sbytes = vlen + 2; - return; - } - else - { - out_string(c, "NOT FOUND"); - /* swallow the data line */ - c->write_and_go = conn_swallow; - c->sbytes = vlen + 2; - return; - } + /* swallow the data line */ + c->write_and_go = conn_swallow; + c->sbytes = vlen + 2; + if(itmp) { + item_remove(itmp); + } + return; + } else { + out_string(c, "NOT FOUND"); + /* swallow the data line */ + c->write_and_go = conn_swallow; + c->sbytes = vlen + 2; + return; + } } if (it == 0) { diff --git a/memcached.h b/memcached.h --- a/memcached.h +++ b/memcached.h @@ -31,6 +31,8 @@ #define ITEM_LIST_HIGHWAT 400 #define IOV_LIST_HIGHWAT 600 #define MSG_LIST_HIGHWAT 100 + +#define MAX_CAS_ID 0x7ffffffffffffff0 /* Get a consistent bool type */ #if HAVE_STDBOOL_H @@ -111,6 +113,7 @@ typedef struct _stritem { uint8_t it_flags; /* ITEM_* above */ uint8_t slabs_clsid;/* which slab class we're in */ uint8_t nkey; /* key length, w/terminating null and padding */ + uint64_t cas_id; /* the CAS identifier */ void * end[]; /* then null-terminated key */ /* then " flags length\r\n" (no terminating null) */