Changeset 708

Show
Ignore:
Timestamp:
02/22/08 04:57:41 (8 months ago)
Author:
dormando
Message:

Implement 'noreply' option for update commands. (Tomash Brechko <tomash.brechko@gmail.com>)

Commands add, set, replace, append, prepend, cas, delete, incr, decr,
flush_all, verbosity can take last optional parameter, 'noreply',
which instructs the server to not send the reply.

Add benchmark script for noreply parameter.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/server/doc/protocol.txt

    r689 r708  
    127127First, the client sends a command line which looks like this: 
    128128 
    129 <command name> <key> <flags> <exptime> <bytes> [<cas unqiue>]\r\n 
    130  
    131 - <command name> is "set", "add", "replace", "append", "prepend", or "cas" 
     129<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n 
     130cas <key> <flags> <exptime> <bytes> <cas unqiue> [noreply]\r\n 
     131 
     132- <command name> is "set", "add", "replace", "append" or "prepend" 
    132133 
    133134  "set" means "store this data".   
     
    175176  when issuing "cas" updates. 
    176177 
     178- "noreply" optional parameter instructs the server to not send the 
     179  reply.  NOTE: if the request line is malformed, the server can't 
     180  parse "noreply" option reliably.  In this case it may send the error 
     181  to the client, and not reading it on the client side will break 
     182  things.  Client should construct only valid requests. 
     183 
    177184After this line, the client sends the data block: 
    178185 
     
    246253The command "delete" allows for explicit deletion of items: 
    247254 
    248 delete <key> <time>\r\n 
     255delete <key> [<time>] [noreply]\r\n 
    249256 
    250257- <key> is the key of the item the client wishes the server to delete 
     
    262269  storage commands with this key will succeed). 
    263270 
     271- "noreply" optional parameter instructs the server to not send the 
     272  reply.  See the note in Storage commands regarding malformed 
     273  requests. 
     274 
    264275The response line to this command can be one of: 
    265276 
     
    286297The client sends the command line: 
    287298 
    288 incr <key> <value>\r\n 
     299incr <key> <value> [noreply]\r\n 
    289300 
    290301or 
    291302 
    292 decr <key> <value>\r\n 
     303decr <key> <value> [noreply]\r\n 
    293304 
    294305- <key> is the key of the item the client wishes to change 
     
    296307- <value> is the amount by which the client wants to increase/decrease 
    297308the item. It is a decimal representation of a 64-bit unsigned integer. 
     309 
     310- "noreply" optional parameter instructs the server to not send the 
     311  reply.  See the note in Storage commands regarding malformed 
     312  requests. 
    298313 
    299314The response will be one of: 
     
    400415 
    401416"flush_all" is a command with an optional numeric argument. It always 
    402 succeeds, and the server sends "OK\r\n" in response. Its effect is to 
    403 invalidate all existing items immediately (by default) or after the 
    404 expiration specified.  After invalidation none of the items will be returned 
    405 in response to a retrieval command (unless it's stored again under the 
    406 same key *after* flush_all has invalidated the items). flush_all doesn't 
    407 actually free all the memory taken up by existing items; that will 
    408 happen gradually as new items are stored. The most precise definition 
    409 of what flush_all does is the following: it causes all items whose 
    410 update time is earlier than the time at which flush_all was set to be 
    411 executed to be ignored for retrieval purposes. 
     417succeeds, and the server sends "OK\r\n" in response (unless "noreply" 
     418is given as the last parameter). Its effect is to invalidate all 
     419existing items immediately (by default) or after the expiration 
     420specified.  After invalidation none of the items will be returned in 
     421response to a retrieval command (unless it's stored again under the 
     422same key *after* flush_all has invalidated the items). flush_all 
     423doesn't actually free all the memory taken up by existing items; that 
     424will happen gradually as new items are stored. The most precise 
     425definition of what flush_all does is the following: it causes all 
     426items whose update time is earlier than the time at which flush_all 
     427was set to be executed to be ignored for retrieval purposes. 
    412428 
    413429The intent of flush_all with a delay, was that in a setting where you 
     
    432448server. 
    433449 
    434 "verbosity" is a command with a numeric argument. It always                                                   
    435 succeeds, and the server sends "OK\r\n" in response. Its effect is to                                         
    436 set the verbosity level of the logging output.                                                                
     450"verbosity" is a command with a numeric argument. It always succeeds, 
     451and the server sends "OK\r\n" in response (unless "noreply" is given 
     452as the last parameter). Its effect is to set the verbosity level of 
     453the logging output. 
    437454 
    438455"quit" is a command with no arguments: 
  • trunk/server/memcached.c

    r707 r708  
    373373    c->gen = 0; 
    374374 
     375    c->noreply = false; 
     376 
    375377    event_set(&c->event, sfd, event_flags, event_handler, (void *)c); 
    376378    event_base_set(base, &c->event); 
     
    734736    assert(c != NULL); 
    735737 
     738    if (c->noreply) { 
     739        c->noreply = false; 
     740        conn_set_state(c, conn_read); 
     741        return; 
     742    } 
     743 
    736744    if (settings.verbose > 1) 
    737745        fprintf(stderr, ">%d %s\n", c->sfd, str); 
     
    899907#define KEY_MAX_LENGTH 250 
    900908 
    901 #define MAX_TOKENS 7 
     909#define MAX_TOKENS 8 
    902910 
    903911/* 
     
    966974    } else { 
    967975        out_string(c, "SERVER_ERROR out of memory"); 
     976    } 
     977} 
     978 
     979static inline void set_noreply_maybe(conn *c, token_t *tokens, size_t ntokens) 
     980{ 
     981    int noreply_index = ntokens - 2; 
     982 
     983    /* 
     984      NOTE: this function is not the first place where we are going to 
     985      send the reply.  We could send it instead from process_command() 
     986      if the request line has wrong number of tokens.  However parsing 
     987      malformed line for "noreply" option is not reliable anyway, so 
     988      it can't be helped. 
     989    */ 
     990    if (tokens[noreply_index].value 
     991        && strcmp(tokens[noreply_index].value, "noreply") == 0) { 
     992        c->noreply = true; 
    968993    } 
    969994} 
     
    13481373    assert(c != NULL); 
    13491374 
     1375    set_noreply_maybe(c, tokens, ntokens); 
     1376 
    13501377    if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { 
    13511378        out_string(c, "CLIENT_ERROR bad command line format"); 
     
    14181445 
    14191446    assert(c != NULL); 
     1447 
     1448    set_noreply_maybe(c, tokens, ntokens); 
    14201449 
    14211450    if(tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { 
     
    15151544    assert(c != NULL); 
    15161545 
     1546    set_noreply_maybe(c, tokens, ntokens); 
     1547 
    15171548    if (settings.managed) { 
    15181549        int bucket = c->bucket; 
     
    15361567    } 
    15371568 
    1538     if(ntokens == 4) { 
     1569    if(ntokens == (c->noreply ? 5 : 4)) { 
    15391570        exptime = strtol(tokens[2].value, NULL, 10); 
    15401571 
     
    15991630    assert(c != NULL); 
    16001631 
     1632    set_noreply_maybe(c, tokens, ntokens); 
     1633 
    16011634    level = strtoul(tokens[1].value, NULL, 10); 
    16021635    settings.verbose = level > MAX_VERBOSITY_LEVEL ? MAX_VERBOSITY_LEVEL : level; 
     
    16361669        process_get_command(c, tokens, ntokens, false); 
    16371670 
    1638     } else if (ntokens == 6 && 
     1671    } else if ((ntokens == 6 || ntokens == 7) && 
    16391672               ((strcmp(tokens[COMMAND_TOKEN].value, "add") == 0 && (comm = NREAD_ADD)) || 
    16401673                (strcmp(tokens[COMMAND_TOKEN].value, "set") == 0 && (comm = NREAD_SET)) || 
     
    16451678        process_update_command(c, tokens, ntokens, comm, false); 
    16461679 
    1647     } else if (ntokens == 7 && (strcmp(tokens[COMMAND_TOKEN].value, "cas") == 0 && (comm = NREAD_CAS))) { 
     1680    } else if ((ntokens == 7 || ntokens == 8) && (strcmp(tokens[COMMAND_TOKEN].value, "cas") == 0 && (comm = NREAD_CAS))) { 
    16481681 
    16491682        process_update_command(c, tokens, ntokens, comm, true); 
    16501683 
    1651     } else if (ntokens == 4 && (strcmp(tokens[COMMAND_TOKEN].value, "incr") == 0)) { 
     1684    } else if ((ntokens == 4 || ntokens == 5) && (strcmp(tokens[COMMAND_TOKEN].value, "incr") == 0)) { 
    16521685 
    16531686        process_arithmetic_command(c, tokens, ntokens, 1); 
     
    16571690        process_get_command(c, tokens, ntokens, true); 
    16581691 
    1659     } else if (ntokens == 4 && (strcmp(tokens[COMMAND_TOKEN].value, "decr") == 0)) { 
     1692    } else if ((ntokens == 4 || ntokens == 5) && (strcmp(tokens[COMMAND_TOKEN].value, "decr") == 0)) { 
    16601693 
    16611694        process_arithmetic_command(c, tokens, ntokens, 0); 
    16621695 
    1663     } else if (ntokens >= 3 && ntokens <= 4 && (strcmp(tokens[COMMAND_TOKEN].value, "delete") == 0)) { 
     1696    } else if (ntokens >= 3 && ntokens <= 5 && (strcmp(tokens[COMMAND_TOKEN].value, "delete") == 0)) { 
    16641697 
    16651698        process_delete_command(c, tokens, ntokens); 
     
    17301763        process_stat(c, tokens, ntokens); 
    17311764 
    1732     } else if (ntokens >= 2 && ntokens <= 3 && (strcmp(tokens[COMMAND_TOKEN].value, "flush_all") == 0)) { 
     1765    } else if (ntokens >= 2 && ntokens <= 4 && (strcmp(tokens[COMMAND_TOKEN].value, "flush_all") == 0)) { 
    17331766        time_t exptime = 0; 
    17341767        set_current_time(); 
    17351768 
    1736         if(ntokens == 2) { 
     1769        set_noreply_maybe(c, tokens, ntokens); 
     1770 
     1771        if(ntokens == (c->noreply ? 3 : 2)) { 
    17371772            settings.oldest_live = current_time - 1; 
    17381773            item_flush_expired(); 
     
    17991834        out_string(c, "CLIENT_ERROR Slab reassignment not supported"); 
    18001835#endif 
    1801     } else if (ntokens == 3 && (strcmp(tokens[COMMAND_TOKEN].value, "verbosity") == 0)) { 
     1836    } else if ((ntokens == 3 || ntokens == 4) && (strcmp(tokens[COMMAND_TOKEN].value, "verbosity") == 0)) { 
    18021837        process_verbosity_command(c, tokens, ntokens); 
    18031838    } else { 
  • trunk/server/memcached.h

    r701 r708  
    221221                         a managed instance. -1 (_not_ 0) means invalid. */ 
    222222    int    gen;       /* generation requested for the bucket */ 
     223    bool   noreply;   /* True if the reply should not be sent. */ 
    223224    conn   *next;     /* Used for generating a list of conn structures */ 
    224225};