Changeset 635

Show
Ignore:
Timestamp:
11/15/07 08:13:45 (1 year ago)
Author:
dormando
Message:

CAS fix from Christ Goffinet and Dustin Sallings. Use a global incremental
counter in a thread safe place.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/server/items.c

    r618 r635  
    1818static void item_link_q(item *it); 
    1919static void item_unlink_q(item *it); 
     20static uint64_t get_cas_id(); 
    2021 
    2122/* 
     
    3839        sizes[i] = 0; 
    3940    } 
     41} 
     42 
     43/* Get the next CAS id for a new item. */ 
     44uint64_t get_cas_id() { 
     45    static uint64_t cas_id; 
     46    if(cas_id >= MAX_CAS_ID) { 
     47        cas_id = 0; 
     48    } 
     49    return ++cas_id; 
    4050} 
    4151 
     
    130140    it->nkey = nkey; 
    131141    it->nbytes = nbytes; 
     142    it->cas_id = get_cas_id(); 
    132143    strcpy(ITEM_key(it), key); 
    133144    it->exptime = exptime; 
  • trunk/server/memcached.c

    r633 r635  
    690690    item *it = c->item; 
    691691    int comm = c->item_comm; 
     692    int ret; 
    692693 
    693694    STATS_LOCK(); 
     
    698699        out_string(c, "CLIENT_ERROR bad data chunk"); 
    699700    } else { 
    700         if (store_item(it, comm)) { 
    701             out_string(c, "STORED"); 
    702         } else { 
    703             out_string(c, "NOT_STORED"); 
    704         } 
     701      ret = store_item(it, comm); 
     702      if (ret == 1) 
     703          out_string(c, "STORED"); 
     704      else if(ret == 2) 
     705          out_string(c, "EXISTS"); 
     706      else if(ret == 3) 
     707          out_string(c, "NOT FOUND"); 
     708      else 
     709          out_string(c, "NOT_STORED"); 
    705710    } 
    706711 
     
    735740    { 
    736741        /* replace and add can't override delete locks; don't store */ 
     742    } else if (comm == NREAD_CAS) { 
     743        /* validate cas operation */ 
     744        if (delete_locked) 
     745            old_it = do_item_get_nocheck(key, it->nkey); 
     746 
     747        if(old_it == NULL) { 
     748          // LRU expired 
     749          stored = 3; 
     750        } 
     751        else if(it->cas_id == old_it->cas_id) { 
     752          // cas validates 
     753          do_item_replace(old_it, it); 
     754          stored = 1; 
     755        } 
     756        else 
     757        { 
     758          stored = 2; 
     759        } 
    737760    } else { 
    738  
    739761        /* 
    740762         * Append - combine new and old record into single one. Here it's 
     
    10811103    token_t *key_token = &tokens[KEY_TOKEN]; 
    10821104    char suffix[255]; 
    1083     uint32_t in_memory_ptr; 
    10841105    assert(c != NULL); 
    10851106 
     
    11341155                if(return_key_ptr == true) 
    11351156                { 
    1136                   in_memory_ptr = (uint32_t)item_get(key, nkey); 
    1137                   sprintf(suffix," %d %d %lu\r\n", atoi(ITEM_suffix(it) + 1), it->nbytes - 2, in_memory_ptr); 
     1157                  sprintf(suffix," %d %d %llu\r\n", atoi(ITEM_suffix(it) + 1), 
     1158                      it->nbytes - 2, it->cas_id); 
    11381159                  if (add_iov(c, "VALUE ", 6) != 0 || 
    11391160                      add_iov(c, ITEM_key(it), it->nkey) != 0 || 
     
    12141235    time_t exptime; 
    12151236    int vlen, old_vlen; 
    1216     uint32_t req_memory_ptr, in_memory_ptr
     1237    uint64_t req_cas_id
    12171238    item *it, *old_it; 
    12181239 
     
    12321253 
    12331254    // does cas value exist? 
    1234     if(tokens[5].value
     1255    if(handle_cas
    12351256    { 
    1236       req_memory_ptr = strtoull(tokens[5].value, NULL, 10); 
     1257      req_cas_id = strtoull(tokens[5].value, NULL, 10); 
    12371258    } 
    12381259 
     
    12601281 
    12611282    it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); 
    1262  
    1263     /* HANDLE_CAS VALIDATION */ 
    1264     if (handle_cas == true) 
    1265     { 
    1266       item *itmp=item_get(key, it->nkey); 
    1267       /* Release the reference */ 
    1268       if(itmp) { 
    1269         item_remove(itmp); 
    1270       } 
    1271       in_memory_ptr = (uint32_t)itmp; 
    1272       if(in_memory_ptr == req_memory_ptr) 
    1273       { 
    1274         // validates allow the set 
    1275       } 
    1276       else if(in_memory_ptr) 
    1277       { 
    1278         out_string(c, "EXISTS"); 
    1279  
    1280         /* swallow the data line */ 
    1281         c->write_and_go = conn_swallow; 
    1282         c->sbytes = vlen + 2; 
    1283         return; 
    1284       } 
    1285       else 
    1286       { 
    1287         out_string(c, "NOT FOUND"); 
    1288         /* swallow the data line */ 
    1289         c->write_and_go = conn_swallow; 
    1290         c->sbytes = vlen + 2; 
    1291         return; 
    1292       } 
    1293     } 
    12941283 
    12951284    if (it == 0) { 
     
    13031292        return; 
    13041293    } 
     1294    if(handle_cas) 
     1295      it->cas_id = req_cas_id; 
    13051296 
    13061297    c->item = it; 
     
    15461537        process_update_command(c, tokens, ntokens, comm, false); 
    15471538 
    1548     } else if (ntokens == 6 && (strcmp(tokens[COMMAND_TOKEN].value, "cas") == 0)) { 
     1539    } else if (ntokens == 6 && (strcmp(tokens[COMMAND_TOKEN].value, "cas") == 0 && (comm = NREAD_CAS))) { 
    15491540 
    15501541        process_update_command(c, tokens, ntokens, comm, true); 
  • trunk/server/memcached.h

    r629 r635  
    3232#define IOV_LIST_HIGHWAT 600 
    3333#define MSG_LIST_HIGHWAT 100 
     34 
     35#define MAX_CAS_ID 0x7ffffffffffffff0 
    3436 
    3537/* Get a consistent bool type */ 
     
    113115    uint8_t         slabs_clsid;/* which slab class we're in */ 
    114116    uint8_t         nkey;       /* key length, w/terminating null and padding */ 
     117    uint64_t        cas_id;     /* the CAS identifier */ 
    115118    void * end[]; 
    116119    /* then null-terminated key */ 
     
    141144#define NREAD_APPEND 4 
    142145#define NREAD_PREPEND 5 
     146#define NREAD_CAS 6 
    143147 
    144148typedef struct {