📄 memcached.c
字号:
struct mallinfo info; char *pos = temp; info = mallinfo(); pos += sprintf(pos, "STAT arena_size %d\r\n", info.arena); pos += sprintf(pos, "STAT free_chunks %d\r\n", info.ordblks); pos += sprintf(pos, "STAT fastbin_blocks %d\r\n", info.smblks); pos += sprintf(pos, "STAT mmapped_regions %d\r\n", info.hblks); pos += sprintf(pos, "STAT mmapped_space %d\r\n", info.hblkhd); pos += sprintf(pos, "STAT max_total_alloc %d\r\n", info.usmblks); pos += sprintf(pos, "STAT fastbin_space %d\r\n", info.fsmblks); pos += sprintf(pos, "STAT total_alloc %d\r\n", info.uordblks); pos += sprintf(pos, "STAT total_free %d\r\n", info.fordblks); pos += sprintf(pos, "STAT releasable_space %d\r\nEND", info.keepcost); out_string(c, temp); return; }#endif /* HAVE_STRUCT_MALLINFO */#endif /* HAVE_MALLOC_H */ if (strcmp(subcommand, "maps") == 0) { char *wbuf; int wsize = 8192; /* should be enough */ int fd; int res; if (!(wbuf = (char *)malloc(wsize))) { out_string(c, "SERVER_ERROR out of memory"); return; } fd = open("/proc/self/maps", O_RDONLY); if (fd == -1) { out_string(c, "SERVER_ERROR cannot open the maps file"); free(wbuf); return; } res = read(fd, wbuf, wsize - 6); /* 6 = END\r\n\0 */ if (res == wsize - 6) { out_string(c, "SERVER_ERROR buffer overflow"); free(wbuf); close(fd); return; } if (res == 0 || res == -1) { out_string(c, "SERVER_ERROR can't read the maps file"); free(wbuf); close(fd); return; } memcpy(wbuf + res, "END\r\n", 6); c->write_and_free = wbuf; c->wcurr = wbuf; c->wbytes = res + 5; // Don't write the terminal '\0' conn_set_state(c, conn_write); c->write_and_go = conn_read; close(fd); return; } if (strcmp(subcommand, "cachedump") == 0) { char *buf; unsigned int bytes, id, limit = 0; if(ntokens < 5) { out_string(c, "CLIENT_ERROR bad command line"); return; } id = strtoul(tokens[2].value, NULL, 10); limit = strtoul(tokens[3].value, NULL, 10); if(errno == ERANGE) { out_string(c, "CLIENT_ERROR bad command line format"); return; } buf = item_cachedump(id, limit, &bytes); if (buf == 0) { out_string(c, "SERVER_ERROR out of memory"); return; } c->write_and_free = buf; c->wcurr = buf; c->wbytes = bytes; conn_set_state(c, conn_write); c->write_and_go = conn_read; return; } if (strcmp(subcommand, "slabs") == 0) { int bytes = 0; char *buf = slabs_stats(&bytes); if (!buf) { out_string(c, "SERVER_ERROR out of memory"); return; } c->write_and_free = buf; c->wcurr = buf; c->wbytes = bytes; conn_set_state(c, conn_write); c->write_and_go = conn_read; return; } if (strcmp(subcommand, "items") == 0) { char buffer[4096]; item_stats(buffer, 4096); out_string(c, buffer); return; } if (strcmp(subcommand, "detail") == 0) { if (ntokens < 4) process_stats_detail(c, ""); /* outputs the error message */ else process_stats_detail(c, tokens[2].value); return; } if (strcmp(subcommand, "sizes") == 0) { int bytes = 0; char *buf = item_stats_sizes(&bytes); if (! buf) { out_string(c, "SERVER_ERROR out of memory"); return; } c->write_and_free = buf; c->wcurr = buf; c->wbytes = bytes; conn_set_state(c, conn_write); c->write_and_go = conn_read; return; } out_string(c, "ERROR");}/* ntokens is overwritten here... shrug.. */static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens) { char *key; size_t nkey; int i = 0; item *it; token_t *key_token = &tokens[KEY_TOKEN]; assert(c != NULL); if (settings.managed) { int bucket = c->bucket; if (bucket == -1) { out_string(c, "CLIENT_ERROR no BG data in managed mode"); return; } c->bucket = -1; if (buckets[bucket] != c->gen) { out_string(c, "ERROR_NOT_OWNER"); return; } } do { while(key_token->length != 0) { key = key_token->value; nkey = key_token->length; if(nkey > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); return; } STATS_LOCK(); stats.get_cmds++; STATS_UNLOCK(); it = item_get(key, nkey); if (settings.detail_enabled) { stats_prefix_record_get(key, NULL != it); } if (it) { if (i >= c->isize) { item **new_list = realloc(c->ilist, sizeof(item *) * c->isize * 2); if (new_list) { c->isize *= 2; c->ilist = new_list; } else break; } /* * Construct the response. Each hit adds three elements to the * outgoing data list: * "VALUE " * key * " " + flags + " " + data length + "\r\n" + data (with \r\n) */ if (add_iov(c, "VALUE ", 6) != 0 || add_iov(c, ITEM_key(it), it->nkey) != 0 || add_iov(c, ITEM_suffix(it), it->nsuffix + it->nbytes) != 0) { break; } if (settings.verbose > 1) fprintf(stderr, ">%d sending key %s\n", c->sfd, ITEM_key(it)); /* item_get() has incremented it->refcount for us */ STATS_LOCK(); stats.get_hits++; STATS_UNLOCK(); item_update(it); *(c->ilist + i) = it; i++; } else { STATS_LOCK(); stats.get_misses++; STATS_UNLOCK(); } key_token++; } /* * If the command string hasn't been fully processed, get the next set * of tokens. */ if(key_token->value != NULL) { ntokens = tokenize_command(key_token->value, tokens, MAX_TOKENS); key_token = tokens; } } while(key_token->value != NULL); c->icurr = c->ilist; c->ileft = i; if (settings.verbose > 1) fprintf(stderr, ">%d END\n", c->sfd); add_iov(c, "END\r\n", 5); if (c->udp && build_udp_headers(c) != 0) { out_string(c, "SERVER_ERROR out of memory"); } else { conn_set_state(c, conn_mwrite); c->msgcurr = 0; } return;}static void process_update_command(conn *c, token_t *tokens, const size_t ntokens, int comm) { char *key; size_t nkey; int flags; time_t exptime; int vlen; item *it; assert(c != NULL); if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); return; } key = tokens[KEY_TOKEN].value; nkey = tokens[KEY_TOKEN].length; flags = strtoul(tokens[2].value, NULL, 10); exptime = strtol(tokens[3].value, NULL, 10); vlen = strtol(tokens[4].value, NULL, 10); if(errno == ERANGE || ((flags == 0 || exptime == 0) && errno == EINVAL)) { out_string(c, "CLIENT_ERROR bad command line format"); return; } if (settings.detail_enabled) { stats_prefix_record_set(key); } if (settings.managed) { int bucket = c->bucket; if (bucket == -1) { out_string(c, "CLIENT_ERROR no BG data in managed mode"); return; } c->bucket = -1; if (buckets[bucket] != c->gen) { out_string(c, "ERROR_NOT_OWNER"); return; } } it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); if (it == 0) { if (! item_size_ok(nkey, flags, vlen + 2)) out_string(c, "SERVER_ERROR object too large for cache"); else out_string(c, "SERVER_ERROR out of memory"); /* swallow the data line */ c->write_and_go = conn_swallow; c->sbytes = vlen + 2; return; } c->item_comm = comm; c->item = it; c->ritem = ITEM_data(it); c->rlbytes = it->nbytes; conn_set_state(c, conn_nread);}static void process_arithmetic_command(conn *c, token_t *tokens, const size_t ntokens, const int incr) { char temp[32]; item *it; unsigned int delta; char *key; size_t nkey; assert(c != NULL); if(tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); return; } key = tokens[KEY_TOKEN].value; nkey = tokens[KEY_TOKEN].length; if (settings.managed) { int bucket = c->bucket; if (bucket == -1) { out_string(c, "CLIENT_ERROR no BG data in managed mode"); return; } c->bucket = -1; if (buckets[bucket] != c->gen) { out_string(c, "ERROR_NOT_OWNER"); return; } } delta = strtoul(tokens[2].value, NULL, 10); if(errno == ERANGE) { out_string(c, "CLIENT_ERROR bad command line format"); return; } it = item_get(key, nkey); if (!it) { out_string(c, "NOT_FOUND"); return; } out_string(c, add_delta(it, incr, delta, temp)); item_remove(it); /* release our reference */}/* * adds a delta value to a numeric item. * * it item to adjust * incr true to increment value, false to decrement * delta amount to adjust value by * buf buffer for response string * * returns a response string to send back to the client. */char *do_add_delta(item *it, int incr, unsigned int delta, char *buf) { char *ptr; unsigned int value; int res; ptr = ITEM_data(it); while ((*ptr != '\0') && (*ptr < '0' && *ptr > '9')) ptr++; // BUG: can't be true value = strtol(ptr, NULL, 10); if(errno == ERANGE) { return "CLIENT_ERROR cannot increment or decrement non-numeric value"; } if (incr != 0) value += delta; else { if (delta >= value) value = 0; else value -= delta; } snprintf(buf, 32, "%u", value); res = strlen(buf); if (res + 2 > it->nbytes) { /* need to realloc */ item *new_it; new_it = do_item_alloc(ITEM_key(it), it->nkey, atoi(ITEM_suffix(it) + 1), it->exptime, res + 2 ); if (new_it == 0) { return "SERVER_ERROR out of memory"; } memcpy(ITEM_data(new_it), buf, res); memcpy(ITEM_data(new_it) + res, "\r\n", 3); do_item_replace(it, new_it); do_item_remove(new_it); /* release our reference */ } else { /* replace in-place */ memcpy(ITEM_data(it), buf, res); memset(ITEM_data(it) + res, ' ', it->nbytes - res - 2); } return buf;}static void process_delete_command(conn *c, token_t *tokens, const size_t ntokens) { char *key; size_t nkey; item *it; time_t exptime = 0; assert(c != NULL); if (settings.managed) { int bucket = c->bucket; if (bucket == -1) { out_string(c, "CLIENT_ERROR no BG data in managed mode"); return; } c->bucket = -1; if (buckets[bucket] != c->gen) { out_string(c, "ERROR_NOT_OWNER"); return; } } key = tokens[KEY_TOKEN].value; nkey = tokens[KEY_TOKEN].length; if(nkey > KEY_MAX_LENGTH) { out_string(c, "CLIENT_ERROR bad command line format"); return; } if(ntokens == 4) { exptime = strtol(tokens[2].value, NULL, 10); if(errno == ERANGE) { out_string(c, "CLIENT_ERROR bad command line format"); return; } } if (settings.detail_enabled) { stats_prefix_record_delete(key); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -