Changeset 493
- Timestamp:
- 04/10/07 11:54:23 (2 years ago)
- Files:
-
- branches/multithreaded/server/assoc.c (modified) (10 diffs)
- branches/multithreaded/server/configure.ac (modified) (1 diff)
- branches/multithreaded/server/devtools/clean-whitespace.pl (modified) (1 diff)
- branches/multithreaded/server/items.c (modified) (3 diffs)
- branches/multithreaded/server/memcached.c (modified) (33 diffs)
- branches/multithreaded/server/slabs.c (modified) (1 diff)
- branches/multithreaded/server/slabs.h (modified) (1 diff)
- branches/multithreaded/server/stats.c (modified) (3 diffs)
- branches/multithreaded/server/t/whitespace.t (copied) (copied from trunk/server/t/whitespace.t)
- branches/multithreaded/server/thread.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/multithreaded/server/assoc.c
r469 r493 65 65 is commonly produced by subtraction) look like a single 1-bit 66 66 difference. 67 * the base values were pseudorandom, all zero but one bit set, or 67 * the base values were pseudorandom, all zero but one bit set, or 68 68 all zero plus a counter that starts at zero. 69 69 … … 75 75 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing 76 76 for "differ" defined as + with a one-bit base and a two-bit delta. I 77 used http://burtleburtle.net/bob/hash/avalanche.html to choose 77 used http://burtleburtle.net/bob/hash/avalanche.html to choose 78 78 the operations, constants, and arrangements of the variables. 79 79 … … 114 114 is commonly produced by subtraction) look like a single 1-bit 115 115 difference. 116 * the base values were pseudorandom, all zero but one bit set, or 116 * the base values were pseudorandom, all zero but one bit set, or 117 117 all zero plus a counter that starts at zero. 118 118 … … 138 138 139 139 #if HASH_LITTLE_ENDIAN == 1 140 uint32_t hash( 140 uint32_t hash( 141 141 const void *key, /* the key to hash */ 142 142 size_t length, /* length of the key */ … … 146 146 union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ 147 147 148 /* Set up the internal state */ 148 /* Set up the internal state */ 149 149 a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; 150 150 … … 168 168 169 169 /*----------------------------- handle the last (probably partial) block */ 170 /* 170 /* 171 171 * "k[2]&0xffffff" actually reads beyond the end of the string, but 172 172 * then masks off the part it's not allowed to read. Because the … … 317 317 * This is the same as hashword() on big-endian machines. It is different 318 318 * from hashlittle() on all machines. hashbig() takes advantage of 319 * big-endian byte ordering. 319 * big-endian byte ordering. 320 320 */ 321 321 uint32_t hash( const void *key, size_t length, const uint32_t initval) … … 346 346 347 347 /*----------------------------- handle the last (probably partial) block */ 348 /* 348 /* 349 349 * "k[2]<<8" actually reads beyond the end of the string, but 350 350 * then shifts out the part it's not allowed to read. Because the … … 443 443 } 444 444 #else // HASH_XXX_ENDIAN == 1 445 #error Must define HASH_BIG_ENDIAN or HASH_LITTLE_ENDIAN 445 #error Must define HASH_BIG_ENDIAN or HASH_LITTLE_ENDIAN 446 446 #endif // hash_XXX_ENDIAN == 1 447 447 … … 611 611 return; 612 612 } 613 /* Note: we never actually get here. the callers don't delete things 613 /* Note: we never actually get here. the callers don't delete things 614 614 they can't find. */ 615 615 assert(*before != 0); branches/multithreaded/server/configure.ac
r469 r493 103 103 AC_CHECK_HEADER(malloc.h, AC_DEFINE(HAVE_MALLOC_H,,[do we have malloc.h?])) 104 104 AC_CHECK_MEMBER([struct mallinfo.arena], [ 105 AC_DEFINE(HAVE_STRUCT_MALLINFO,,[do we have stuct mallinfo?])106 ], ,[107 # include <malloc.h>108 ]105 AC_DEFINE(HAVE_STRUCT_MALLINFO,,[do we have stuct mallinfo?]) 106 ], ,[ 107 # include <malloc.h> 108 ] 109 109 ) 110 110 branches/multithreaded/server/devtools/clean-whitespace.pl
r332 r493 3 3 use FindBin qw($Bin); 4 4 chdir "$Bin/.." or die; 5 my @files = (glob("*.h"), glob("*.c") );5 my @files = (glob("*.h"), glob("*.c"), glob("*.ac")); 6 6 foreach my $f (@files) { 7 7 open(my $fh, $f) or die; branches/multithreaded/server/items.c
r490 r493 55 55 * Generates the variable-sized part of the header for an object. 56 56 * 57 * key - The key 57 * key - The key 58 58 * nkey - The length of the key 59 59 * flags - key flags … … 70 70 return sizeof(item) + nkey + *nsuffix + nbytes; 71 71 } 72 72 73 73 /*@null@*/ 74 74 item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes) { … … 93 93 if (settings.evict_to_free == 0) return NULL; 94 94 95 /* 96 * try to get one off the right LRU 95 /* 96 * try to get one off the right LRU 97 97 * don't necessariuly unlink the tail because it may be locked: refcount>0 98 98 * search up from tail an item with refcount==0 and unlink it; give up after 50 branches/multithreaded/server/memcached.c
r490 r493 62 62 63 63 /* 64 * forward declarations 64 * forward declarations 65 65 */ 66 66 static void drive_machine(conn *c); … … 485 485 c->isize = ITEM_LIST_INITIAL; 486 486 } 487 /* TODO check error condition? */487 /* TODO check error condition? */ 488 488 } 489 489 … … 494 494 c->msgsize = MSG_LIST_INITIAL; 495 495 } 496 /* TODO check error condition? */496 /* TODO check error condition? */ 497 497 } 498 498 … … 503 503 c->iovsize = IOV_LIST_INITIAL; 504 504 } 505 /* TODO check return value */505 /* TODO check return value */ 506 506 } 507 507 } … … 755 755 #define KEY_MAX_LENGTH 250 756 756 757 #define MAX_TOKENS 6 757 #define MAX_TOKENS 6 758 758 759 759 /* … … 762 762 * Returns total number of tokens. The last valid token is the terminal 763 763 * token (value points to the first unprocessed character of the string and 764 * length zero). 764 * length zero). 765 765 * 766 766 * Usage example: … … 780 780 size_t ntokens = 0; 781 781 782 assert(command != NULL && tokens != NULL && max_tokens > 1); 782 assert(command != NULL && tokens != NULL && max_tokens > 1); 783 783 784 784 cp = command; 785 785 while(*cp != '\0' && ntokens < max_tokens - 1) { 786 786 if(*cp == ' ') { 787 // If we've accumulated a token, this is the end of it. 787 // If we've accumulated a token, this is the end of it. 788 788 if(length > 0) { 789 789 tokens[ntokens].value = value; … … 943 943 return; 944 944 } 945 945 946 946 fd = open("/proc/self/maps", O_RDONLY); 947 947 if (fd == -1) { … … 965 965 c->write_and_free = wbuf; 966 966 c->wcurr = wbuf; 967 c->wbytes = res + 5; // Don't write the terminal '\0' 967 c->wbytes = res + 5; // Don't write the terminal '\0' 968 968 conn_set_state(c, conn_write); 969 969 c->write_and_go = conn_read; … … 1078 1078 do { 1079 1079 while(key_token->length != 0) { 1080 1080 1081 1081 key = key_token->value; 1082 1082 nkey = key_token->length; 1083 1083 1084 1084 if(nkey > KEY_MAX_LENGTH) { 1085 1085 out_string(c, "CLIENT_ERROR bad command line format"); 1086 1086 return; 1087 1087 } 1088 1088 1089 1089 STATS_LOCK(); 1090 1090 stats.get_cmds++; … … 1102 1102 } else break; 1103 1103 } 1104 1104 1105 1105 /* 1106 1106 * Construct the response. Each hit adds three elements to the … … 1132 1132 STATS_UNLOCK(); 1133 1133 } 1134 1134 1135 1135 key_token++; 1136 1136 } … … 1144 1144 key_token = tokens; 1145 1145 } 1146 1146 1147 1147 } while(key_token->value != NULL); 1148 1148 1149 1149 c->icurr = c->ilist; 1150 1150 c->ileft = i; 1151 1151 1152 1152 if (settings.verbose > 1) 1153 1153 fprintf(stderr, ">%d END\n", c->sfd); 1154 1154 add_iov(c, "END\r\n", 5); 1155 1155 1156 1156 if (c->udp && build_udp_headers(c) != 0) { 1157 1157 out_string(c, "SERVER_ERROR out of memory"); … … 1185 1185 exptime = strtol(tokens[3].value, NULL, 10); 1186 1186 vlen = strtol(tokens[4].value, NULL, 10); 1187 1187 1188 1188 if(errno == ERANGE || ((flags == 0 || exptime == 0) && errno == EINVAL)) { 1189 1189 out_string(c, "CLIENT_ERROR bad command line format"); … … 1220 1220 return; 1221 1221 } 1222 1222 1223 1223 c->item_comm = comm; 1224 1224 c->item = it; … … 1234 1234 char *key; 1235 1235 size_t nkey; 1236 1236 1237 1237 assert(c != NULL); 1238 1238 1239 if(tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { 1239 if(tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { 1240 1240 out_string(c, "CLIENT_ERROR bad command line format"); 1241 1241 return; … … 1244 1244 key = tokens[KEY_TOKEN].value; 1245 1245 nkey = tokens[KEY_TOKEN].length; 1246 1246 1247 1247 if (settings.managed) { 1248 1248 int bucket = c->bucket; … … 1259 1259 1260 1260 delta = strtoul(tokens[2].value, NULL, 10); 1261 1261 1262 1262 if(errno == ERANGE) { 1263 1263 out_string(c, "CLIENT_ERROR bad command line format"); … … 1282 1282 * delta amount to adjust value by 1283 1283 * buf buffer for response string 1284 * 1284 * 1285 1285 * returns a response string to send back to the client. 1286 1286 */ … … 1292 1292 ptr = ITEM_data(it); 1293 1293 while ((*ptr != '\0') && (*ptr < '0' && *ptr > '9')) ptr++; // BUG: can't be true 1294 1294 1295 1295 value = strtol(ptr, NULL, 10); 1296 1296 … … 1330 1330 item *it; 1331 1331 time_t exptime = 0; 1332 1332 1333 1333 assert(c != NULL); 1334 1334 … … 1345 1345 } 1346 1346 } 1347 1347 1348 1348 key = tokens[KEY_TOKEN].value; 1349 1349 nkey = tokens[KEY_TOKEN].length; … … 1356 1356 if(ntokens == 4) { 1357 1357 exptime = strtol(tokens[2].value, NULL, 10); 1358 1358 1359 1359 if(errno == ERANGE) { 1360 1360 out_string(c, "CLIENT_ERROR bad command line format"); … … 1394 1394 todelete = new_delete; 1395 1395 deltotal *= 2; 1396 } else { 1397 /* 1396 } else { 1397 /* 1398 1398 * can't delete it immediately, user wants a delay, 1399 1399 * but we ran out of memory for the delete queue … … 1403 1403 } 1404 1404 } 1405 1405 1406 1406 /* use its expiration time as its deletion time now */ 1407 1407 it->exptime = realtime(exptime); … … 1413 1413 1414 1414 static void process_command(conn *c, char *command) { 1415 1415 1416 1416 token_t tokens[MAX_TOKENS]; 1417 1417 size_t ntokens; … … 1423 1423 fprintf(stderr, "<%d %s\n", c->sfd, command); 1424 1424 1425 /* 1425 /* 1426 1426 * for commands set/add/replace, we build an item and read the data 1427 1427 * directly into it, then continue in nread_complete(). 1428 */ 1429 1428 */ 1429 1430 1430 c->msgcurr = 0; 1431 1431 c->msgused = 0; … … 1441 1441 ((strcmp(tokens[COMMAND_TOKEN].value, "get") == 0) || 1442 1442 (strcmp(tokens[COMMAND_TOKEN].value, "bget") == 0))) { 1443 1443 1444 1444 process_get_command(c, tokens, ntokens); 1445 1445 1446 } else if (ntokens == 6 && 1447 ((strcmp(tokens[COMMAND_TOKEN].value, "add") == 0 && (comm = NREAD_ADD)) || 1446 } else if (ntokens == 6 && 1447 ((strcmp(tokens[COMMAND_TOKEN].value, "add") == 0 && (comm = NREAD_ADD)) || 1448 1448 (strcmp(tokens[COMMAND_TOKEN].value, "set") == 0 && (comm = NREAD_SET)) || 1449 1449 (strcmp(tokens[COMMAND_TOKEN].value, "replace") == 0 && (comm = NREAD_REPLACE)))) { 1450 1450 1451 1451 process_update_command(c, tokens, ntokens, comm); 1452 1452 … … 1469 1469 return; 1470 1470 } 1471 1471 1472 1472 if (sscanf(tokens[1].value, "%u:%u", &bucket,&gen) == 2) { 1473 1473 if ((bucket < 0) || (bucket >= MAX_BUCKETS)) { … … 1525 1525 1526 1526 } else if (ntokens >= 2 && (strcmp(tokens[COMMAND_TOKEN].value, "stats") == 0)) { 1527 1527 1528 1528 process_stat(c, tokens, ntokens); 1529 1529 … … 1549 1549 out_string(c, "OK"); 1550 1550 return; 1551 1551 1552 1552 } else if (ntokens == 2 && (strcmp(tokens[COMMAND_TOKEN].value, "version") == 0)) { 1553 1553 … … 1557 1557 1558 1558 conn_set_state(c, conn_closing); 1559 1559 1560 1560 } else if (ntokens == 5 && (strcmp(tokens[COMMAND_TOKEN].value, "slabs") == 0 && 1561 1561 strcmp(tokens[COMMAND_TOKEN + 1].value, "reassign") == 0)) { … … 2707 2707 } 2708 2708 /* create the initial listening connection */ 2709 if (!(listen_conn = conn_new(l_socket, conn_listening, 2709 if (!(listen_conn = conn_new(l_socket, conn_listening, 2710 2710 EV_READ | EV_PERSIST, 1, false, main_base))) { 2711 2711 fprintf(stderr, "failed to create listening connection"); branches/multithreaded/server/slabs.c
r490 r493 74 74 * a given size. 75 75 * 76 * Given object size, return id to use when allocating/freeing memory for object 77 * 0 means error: can't store such a large object 76 * Given object size, return id to use when allocating/freeing memory for object 77 * 0 means error: can't store such a large object 78 78 */ 79 79 branches/multithreaded/server/slabs.h
r469 r493 7 7 8 8 9 /* 9 /* 10 10 * Given object size, return id to use when allocating/freeing memory for object 11 11 * 0 means error: can't store such a large object branches/multithreaded/server/stats.c
r462 r493 128 128 void stats_prefix_record_delete(char *key) { 129 129 PREFIX_STATS *pfs; 130 130 131 131 STATS_LOCK(); 132 132 pfs = stats_prefix_find(key); … … 142 142 void stats_prefix_record_set(char *key) { 143 143 PREFIX_STATS *pfs; 144 144 145 145 STATS_LOCK(); 146 146 pfs = stats_prefix_find(key); … … 182 182 for (i = 0; i < PREFIX_HASH_SIZE; i++) { 183 183 for (pfs = prefix_stats[i]; NULL != pfs; pfs = pfs->next) { 184 pos += sprintf(buf + pos, format, 184 pos += sprintf(buf + pos, format, 185 185 pfs->prefix, pfs->num_gets, pfs->num_hits, 186 186 pfs->num_sets, pfs->num_deletes); 187 187 } 188 188 } 189 189 190 190 STATS_UNLOCK(); 191 191 strcpy(buf + pos, "END\r\n"); branches/multithreaded/server/thread.c
r461 r493 302 302 303 303 if (item = cq_peek(&me->new_conn_queue)) { 304 conn *c = conn_new(item->sfd, item->init_state, item->event_flags,305 item->read_buffer_size, item->is_udp, me->base);306 if (!c) {307 if (item->is_udp) {308 fprintf(stderr, "Can't listen for events on UDP socket\n");309 exit(1);304 conn *c = conn_new(item->sfd, item->init_state, item->event_flags, 305 item->read_buffer_size, item->is_udp, me->base); 306 if (!c) { 307 if (item->is_udp) { 308 fprintf(stderr, "Can't listen for events on UDP socket\n"); 309 exit(1); 310 310 } 311 else {312 if (settings.verbose > 0) {313 fprintf(stderr, "Can't listen for events on fd %d\n",314 item->sfd);315 }316 close(item->sfd);317 }318 }311 else { 312 if (settings.verbose > 0) { 313 fprintf(stderr, "Can't listen for events on fd %d\n", 314 item->sfd); 315 } 316 close(item->sfd); 317 } 318 } 319 319 cqi_free(item); 320 320 } … … 595 595 threads[i].notify_send_fd = fds[1]; 596 596 597 setup_thread(&threads[i]);597 setup_thread(&threads[i]); 598 598 } 599 599
