Changeset 646
- Timestamp:
- 11/20/07 07:01:27 (1 year ago)
- Files:
-
- trunk/server/memcached.c (modified) (15 diffs)
- trunk/server/memcached.h (modified) (7 diffs)
- trunk/server/thread.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/server/memcached.c
r645 r646 304 304 c->rbuf = c->wbuf = 0; 305 305 c->ilist = 0; 306 c->suffixlist = 0; 306 307 c->iov = 0; 307 308 c->msglist = 0; … … 311 312 c->wsize = DATA_BUFFER_SIZE; 312 313 c->isize = ITEM_LIST_INITIAL; 314 c->suffixsize = SUFFIX_LIST_INITIAL; 313 315 c->iovsize = IOV_LIST_INITIAL; 314 316 c->msgsize = MSG_LIST_INITIAL; … … 318 320 c->wbuf = (char *)malloc((size_t)c->wsize); 319 321 c->ilist = (item **)malloc(sizeof(item *) * c->isize); 322 c->suffixlist = (char **)malloc(sizeof(char *) * c->suffixsize); 320 323 c->iov = (struct iovec *)malloc(sizeof(struct iovec) * c->iovsize); 321 324 c->msglist = (struct msghdr *)malloc(sizeof(struct msghdr) * c->msgsize); 322 325 323 326 if (c->rbuf == 0 || c->wbuf == 0 || c->ilist == 0 || c->iov == 0 || 324 c->msglist == 0 ) {327 c->msglist == 0 || c->suffixlist == 0) { 325 328 if (c->rbuf != 0) free(c->rbuf); 326 329 if (c->wbuf != 0) free(c->wbuf); 327 330 if (c->ilist !=0) free(c->ilist); 331 if (c->suffixlist != 0) free(c->suffixlist); 328 332 if (c->iov != 0) free(c->iov); 329 333 if (c->msglist != 0) free(c->msglist); … … 356 360 c->ritem = 0; 357 361 c->icurr = c->ilist; 362 c->suffixcurr = c->suffixlist; 358 363 c->ileft = 0; 364 c->suffixleft = 0; 359 365 c->iovused = 0; 360 366 c->msgcurr = 0; … … 397 403 for (; c->ileft > 0; c->ileft--,c->icurr++) { 398 404 item_remove(*(c->icurr)); 405 } 406 } 407 408 if (c->suffixleft != 0) { 409 for (; c->suffixleft > 0; c->suffixleft--, c->suffixcurr++) { 410 suffix_add_to_freelist(*(c->suffixcurr)); 399 411 } 400 412 } … … 421 433 if (c->ilist) 422 434 free(c->ilist); 435 if (c->suffixlist) 436 free(c->suffixlist); 423 437 if (c->iov) 424 438 free(c->iov); … … 528 542 } 529 543 544 /* 545 * Free list management for suffix buffers. 546 */ 547 548 static char **freesuffix; 549 static int freesuffixtotal; 550 static int freesuffixcurr; 551 552 static void suffix_init(void) { 553 freesuffixtotal = 500; 554 freesuffixcurr = 0; 555 556 freesuffix = (char **)malloc( sizeof(char *) * 557 21 * freesuffixtotal ); 558 if (freesuffix == NULL) { 559 perror("malloc()"); 560 } 561 return; 562 } 563 564 /* 565 * Returns a suffix buffer from the freelist, if any. Should call this using 566 * suffix_from_freelist() for thread safety. 567 */ 568 char *do_suffix_from_freelist() { 569 char *s; 570 571 if (freesuffixcurr > 0) { 572 s = freesuffix[--freesuffixcurr]; 573 } else { 574 /* FIXME: global define? */ 575 /* If malloc fails, let the logic fall through without spamming 576 * STDERR on the server. */ 577 s = malloc( sizeof(char *) * SUFFIX_SIZE ); 578 } 579 580 return s; 581 } 582 583 /* 584 * Adds a connection to the freelist. 0 = success. Should call this using 585 * conn_add_to_freelist() for thread safety. 586 */ 587 bool do_suffix_add_to_freelist(char *s) { 588 if (freesuffixcurr < freesuffixtotal) { 589 freesuffix[freesuffixcurr++] = s; 590 return false; 591 } else { 592 /* try to enlarge free connections array */ 593 char **new_freesuffix = realloc(freesuffix, 594 SUFFIX_SIZE * freesuffixtotal * 2); 595 if (new_freesuffix) { 596 freesuffixtotal *= 2; 597 freesuffix = new_freesuffix; 598 freesuffix[freesuffixcurr++] = s; 599 return false; 600 } 601 } 602 return true; 603 } 530 604 531 605 /* … … 1096 1170 1097 1171 /* ntokens is overwritten here... shrug.. */ 1098 static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_ key_ptr) {1172 static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas) { 1099 1173 char *key; 1100 1174 size_t nkey; … … 1102 1176 item *it; 1103 1177 token_t *key_token = &tokens[KEY_TOKEN]; 1104 char suffix[255];1178 char *suffix; 1105 1179 int stats_get_cmds = 0; 1106 1180 int stats_get_hits = 0; … … 1159 1233 */ 1160 1234 1161 if(return_ key_ptr== true)1235 if(return_cas == true) 1162 1236 { 1163 sprintf(suffix," %d %d %llu\r\n", atoi(ITEM_suffix(it) + 1), 1164 it->nbytes - 2, it->cas_id); 1237 /* Goofy mid-flight realloc. */ 1238 if (i >= c->suffixsize) { 1239 char **new_suffix_list = realloc(c->suffixlist, 1240 sizeof(char *) * c->suffixsize * 2); 1241 if (new_suffix_list) { 1242 c->suffixsize *= 2; 1243 c->suffixlist = new_suffix_list; 1244 } 1245 } 1246 1247 suffix = suffix_from_freelist(); 1248 if (suffix == NULL) { 1249 STATS_LOCK(); 1250 stats.get_cmds += stats_get_cmds; 1251 stats.get_hits += stats_get_hits; 1252 stats.get_misses += stats_get_misses; 1253 STATS_UNLOCK(); 1254 out_string(c, "SERVER_ERROR out of memory"); 1255 return; 1256 } 1257 *(c->suffixlist + i) = suffix; 1258 sprintf(suffix, " %llu\r\n", it->cas_id); 1165 1259 if (add_iov(c, "VALUE ", 6) != 0 || 1166 1260 add_iov(c, ITEM_key(it), it->nkey) != 0 || 1261 add_iov(c, ITEM_suffix(it), it->nsuffix - 2) != 0 || 1167 1262 add_iov(c, suffix, strlen(suffix)) != 0 || 1168 1263 add_iov(c, ITEM_data(it), it->nbytes) != 0) … … 1211 1306 c->icurr = c->ilist; 1212 1307 c->ileft = i; 1308 if (return_cas) { 1309 c->suffixcurr = c->suffixlist; 1310 c->suffixleft = i; 1311 } 1213 1312 1214 1313 if (settings.verbose > 1) … … 1223 1322 || (c->udp && build_udp_headers(c) != 0)) { 1224 1323 out_string(c, "SERVER_ERROR out of memory"); 1324 } 1325 else if (return_cas) { 1326 conn_set_state(c, conn_caswrite); 1327 c->msgcurr = 0; 1225 1328 } 1226 1329 else { … … 2103 2206 2104 2207 case conn_mwrite: 2208 case conn_caswrite: 2105 2209 switch (transmit(c)) { 2106 2210 case TRANSMIT_COMPLETE: 2107 if (c->state == conn_mwrite ) {2211 if (c->state == conn_mwrite || c->state == conn_caswrite) { 2108 2212 while (c->ileft > 0) { 2109 2213 item *it = *(c->icurr); … … 2112 2216 c->icurr++; 2113 2217 c->ileft--; 2218 } 2219 if (c->state == conn_caswrite) { 2220 while (c->suffixleft > 0) { 2221 char *suffix = *(c->suffixcurr); 2222 suffix_add_to_freelist(suffix); 2223 c->suffixcurr++; 2224 c->suffixleft--; 2225 } 2114 2226 } 2115 2227 conn_set_state(c, conn_read); … … 2789 2901 assoc_init(); 2790 2902 conn_init(); 2903 /* Hacky suffix buffers. */ 2904 suffix_init(); 2791 2905 slabs_init(settings.maxbytes, settings.factor); 2792 2906 trunk/server/memcached.h
r636 r646 17 17 #define UDP_HEADER_SIZE 8 18 18 #define MAX_SENDBUF_SIZE (256 * 1024 * 1024) 19 /* I'm told the max legnth of a 64-bit num converted to string is 20 bytes. 20 * Plus one for good luck. */ 21 #define SUFFIX_SIZE 21 19 22 20 23 /** Initial size of list of items being returned by "get". */ 21 24 #define ITEM_LIST_INITIAL 200 25 26 /** Initial size of list of CAS suffixes appended to "gets" lines. */ 27 #define SUFFIX_LIST_INITIAL 20 22 28 23 29 /** Initial size of the sendmsg() scatter/gather array. */ … … 134 140 conn_swallow, /** swallowing unnecessary bytes w/o storing */ 135 141 conn_closing, /** closing this connection */ 136 conn_mwrite /** writing out many items sequentially */ 142 conn_mwrite, /** writing out many items sequentially */ 143 conn_caswrite, /** writing out many items sequentially with cas value */ 137 144 }; 138 145 … … 195 202 item **icurr; 196 203 int ileft; 204 205 char **suffixlist; 206 int suffixsize; 207 char **suffixcurr; 208 int suffixleft; 197 209 198 210 /* data for UDP clients */ … … 226 238 conn *do_conn_from_freelist(); 227 239 bool do_conn_add_to_freelist(conn *c); 240 char *do_suffix_from_freelist(); 241 bool do_suffix_add_to_freelist(char *s); 228 242 char *do_defer_delete(item *item, time_t exptime); 229 243 void do_run_deferred_deletes(void); … … 263 277 conn *mt_conn_from_freelist(void); 264 278 bool mt_conn_add_to_freelist(conn *c); 279 char *mt_suffix_from_freelist(void); 280 bool mt_suffix_add_to_freelist(char *s); 265 281 char *mt_defer_delete(item *it, time_t exptime); 266 282 int mt_is_listen_thread(void); … … 290 306 # define conn_from_freelist() mt_conn_from_freelist() 291 307 # define conn_add_to_freelist(x) mt_conn_add_to_freelist(x) 308 # define suffix_from_freelist() mt_suffix_from_freelist() 309 # define suffix_add_to_freelist(x) mt_suffix_add_to_freelist(x) 292 310 # define defer_delete(x,y) mt_defer_delete(x,y) 293 311 # define is_listen_thread() mt_is_listen_thread() … … 319 337 # define conn_from_freelist() do_conn_from_freelist() 320 338 # define conn_add_to_freelist(x) do_conn_add_to_freelist(x) 339 # define suffix_from_freelist() do_suffix_from_freelist() 340 # define suffix_add_to_freelist(x) do_suffix_add_to_freelist(x) 321 341 # define defer_delete(x,y) do_defer_delete(x,y) 322 342 # define dispatch_conn_new(x,y,z,a,b) conn_new(x,y,z,a,b,main_base) trunk/server/thread.c
r619 r646 48 48 static pthread_mutex_t conn_lock; 49 49 50 /* Lock for alternative item suffix freelist */ 51 static pthread_mutex_t suffix_lock; 52 50 53 /* Lock for cache operations (item_*, assoc_*) */ 51 54 static pthread_mutex_t cache_lock; … … 245 248 return result; 246 249 } 250 251 /* 252 * Pulls a suffix buffer from the freelist, if one is available. 253 */ 254 char *mt_suffix_from_freelist() { 255 char *s; 256 257 pthread_mutex_lock(&suffix_lock); 258 s = do_suffix_from_freelist(); 259 pthread_mutex_unlock(&suffix_lock); 260 261 return s; 262 } 263 264 265 /* 266 * Adds a suffix buffer to the freelist. 267 * 268 * Returns 0 on success, 1 if the buffer couldn't be added. 269 */ 270 bool mt_suffix_add_to_freelist(char *s) { 271 bool result; 272 273 pthread_mutex_lock(&conn_lock); 274 result = do_conn_add_to_freelist(s); 275 pthread_mutex_unlock(&conn_lock); 276 277 return result; 278 } 279 247 280 248 281 /****************************** LIBEVENT THREADS *****************************/
