Changeset 627
- Timestamp:
- 10/03/07 23:45:44 (1 year ago)
- Files:
-
- trunk/server/ChangeLog (modified) (1 diff)
- trunk/server/doc/protocol.txt (modified) (4 diffs)
- trunk/server/memcached.c (modified) (5 diffs)
- trunk/server/memcached.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/server/ChangeLog
r624 r627 15 15 16 16 * Add append command support written by Filipe Laborde. 17 Tests/protocol doc updates by Paul Lindner. 17 Thread safe version plus prepend command from Maxim Dounin 18 <mdounin@mdounin.ru> 18 19 19 20 * The memcached-tool script can now display stats. Patch trunk/server/doc/protocol.txt
r620 r627 54 54 There are three types of commands. 55 55 56 Storage commands (there are five: "set", "add", "replace", "append"57 and "cas") ask the server to store some data identified by a key. The56 Storage commands (there are six: "set", "add", "replace", "append" 57 "prepend" and "cas") ask the server to store some data identified by a key. The 58 58 client sends a command line, and then a data block; after that the 59 59 client expects one line of response, which will indicate success or … … 127 127 First, the client sends a command line which looks like this: 128 128 129 <command name> <key> <flags> <exptime> <bytes> [< unqiue>]\r\n130 131 - <command name> is "set", "add", "replace", "append", or "cas"129 <command name> <key> <flags> <exptime> <bytes> [<cas unqiue>]\r\n 130 131 - <command name> is "set", "add", "replace", "append", "prepend", or "cas" 132 132 133 133 "set" means "store this data". … … 139 139 already hold data for this key". 140 140 141 "append" means "add this data to an existing key". 141 "append" means "add this data to an existing key after existing data". 142 143 "prepend" means "add this data to an existing key before existing data". 142 144 143 145 "cas" is a check and set operation which means "store this data but … … 166 168 167 169 - <cas unique> is a unique 64-bit value of an existing entry. 170 Clients should use the value returned from the "gets" command 171 when issuing "cas" updates. 168 172 169 173 After this line, the client sends the data block: trunk/server/memcached.c
r624 r627 720 720 int stored = 0; 721 721 722 item *new_it = NULL; 723 int flags; 724 722 725 if (old_it != NULL && comm == NREAD_ADD) { 723 726 /* add only adds a nonexistent item, but promote to head of LRU */ 724 727 do_item_update(old_it); 725 } else if (!old_it && comm == NREAD_REPLACE) { 728 } else if (!old_it && (comm == NREAD_REPLACE 729 || comm == NREAD_APPEND || comm == NREAD_PREPEND)) 730 { 726 731 /* replace only replaces an existing value; don't store */ 727 } else if (delete_locked && (comm == NREAD_REPLACE || comm == NREAD_ADD)) { 732 } else if (delete_locked && (comm == NREAD_REPLACE || comm == NREAD_ADD 733 || comm == NREAD_APPEND || comm == NREAD_PREPEND)) 734 { 728 735 /* replace and add can't override delete locks; don't store */ 729 736 } else { 737 738 /* 739 * Append - combine new and old record into single one. Here it's 740 * atomic and thread-safe. 741 */ 742 743 if (comm == NREAD_APPEND || comm == NREAD_PREPEND) { 744 745 /* we have it and old_it here - alloc memory to hold both */ 746 /* flags was already lost - so recover them from ITEM_suffix(it) */ 747 748 flags = (int) strtol(ITEM_suffix(it), (char **) NULL, 10); 749 750 new_it = do_item_alloc(key, it->nkey, flags, it->exptime, it->nbytes + old_it->nbytes - 2 /* CRLF */); 751 752 if (new_it == NULL) { 753 /* SERVER_ERROR out of memory */ 754 return 0; 755 } 756 757 /* copy data from it and old_it to new_it */ 758 759 if (comm == NREAD_APPEND) { 760 memcpy(ITEM_data(new_it), ITEM_data(old_it), old_it->nbytes); 761 memcpy(ITEM_data(new_it) + old_it->nbytes - 2 /* CRLF */, ITEM_data(it), it->nbytes); 762 } else { 763 /* NREAD_PREPEND */ 764 memcpy(ITEM_data(new_it), ITEM_data(it), it->nbytes); 765 memcpy(ITEM_data(new_it) + it->nbytes - 2 /* CRLF */, ITEM_data(old_it), old_it->nbytes); 766 } 767 768 it = new_it; 769 } 770 730 771 /* "set" commands can override the delete lock 731 772 window... in which case we have to find the old hidden item … … 743 784 } 744 785 745 if (old_it )786 if (old_it != NULL) 746 787 do_item_remove(old_it); /* release our reference */ 788 if (new_it != NULL) 789 do_item_remove(new_it); 790 747 791 return stored; 748 792 } … … 1209 1253 } 1210 1254 1211 /* Check if append -- if yes, search for previous entry, and allocate memory for both */1212 if( comm == NREAD_APPEND ){1213 old_it = assoc_find(key,nkey);1214 1215 if( old_it && (old_it->nbytes)>2 ){ // previous must be more than \r\n1216 old_vlen = old_it->nbytes - 2;1217 vlen += old_vlen; // append the length of old data1218 } else {1219 comm = NREAD_REPLACE; // no old entry: treat as replace1220 }1221 }1222 1223 1255 it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); 1224 1256 … … 1269 1301 c->ritem = ITEM_data(it); 1270 1302 c->rlbytes = it->nbytes; 1271 1272 1273 /* If append, prepend old data before new - adjust item, rlbytes variables too1274 * Now that data has been merged, treat simply as a replace command1275 */1276 if (comm == NREAD_APPEND ){1277 memcpy( c->ritem, ITEM_data(old_it), old_vlen );1278 c->ritem += old_vlen;1279 c->rlbytes -= old_vlen;1280 comm = NREAD_REPLACE;1281 }1282 1283 1303 c->item_comm = comm; 1284 1304 conn_set_state(c, conn_nread); … … 1515 1535 (strcmp(tokens[COMMAND_TOKEN].value, "set") == 0 && (comm = NREAD_SET)) || 1516 1536 (strcmp(tokens[COMMAND_TOKEN].value, "replace") == 0 && (comm = NREAD_REPLACE)) || 1537 (strcmp(tokens[COMMAND_TOKEN].value, "prepend") == 0 && (comm = NREAD_PREPEND)) || 1517 1538 (strcmp(tokens[COMMAND_TOKEN].value, "append") == 0 && (comm = NREAD_APPEND)) )) { 1518 1539 trunk/server/memcached.h
r620 r627 139 139 #define NREAD_REPLACE 3 140 140 #define NREAD_APPEND 4 141 #define NREAD_PREPEND 5 141 142 142 143 typedef struct {
