0
@@ -67,7 +67,10 @@ static void conn_set_state(conn *c, enum conn_states state);
0
static void stats_reset(void);
0
static void stats_init(void);
0
-static char *server_stats(bool binprot, int *size);
0
+static char *server_stats(uint32_t (*add_stats)(char *buf, const char *key,
0
+ const uint16_t klen, const char *val,
0
+ const uint32_t vlen, void *cookie), conn *c,
0
static void settings_init(void);
0
@@ -1227,11 +1230,12 @@ static void process_bin_get(conn *c) {
0
uint32_t append_bin_stats(char *buf, const char *key, const uint16_t klen,
0
- const char *val, const uint32_t vlen
) {
0
+ const char *val, const uint32_t vlen
, void *cookie) {
0
protocol_binary_response_header *header;
0
uint32_t bodylen = klen + vlen;
0
header = (protocol_binary_response_header *)ptr;
0
+ conn *c = (conn *)cookie;
0
header->response.magic = (uint8_t)PROTOCOL_BINARY_RES;
0
header->response.opcode = PROTOCOL_BINARY_CMD_STAT;
0
@@ -1240,8 +1244,8 @@ uint32_t append_bin_stats(char *buf, const char *key, const uint16_t klen,
0
header->response.datatype = (uint8_t)PROTOCOL_BINARY_RAW_BYTES;
0
header->response.status = (uint16_t)htons(0);
0
header->response.bodylen = htonl(bodylen);
0
- header->response.opaque = htonl(0);
0
- header->response.cas = swap64(0); /* this can be anything... */
0
+ header->response.opaque = c->opaque;
0
+ header->response.cas = swap64(0);
0
ptr += sizeof(header->response);
0
@@ -1276,12 +1280,13 @@ static void process_bin_stat(conn *c) {
0
int server_statlen, engine_statlen;
0
char *ptr, *server_statbuf, *engine_statbuf;
0
- if ((server_statbuf = server_stats(true, &server_statlen)) == NULL) {
0
+ if ((server_statbuf = server_stats(&append_bin_stats, (void *)c,
0
+ &server_statlen)) == NULL) {
0
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0);
0
- if ((engine_statbuf = get_stats(NULL, &append_bin_stats,
0
+ if ((engine_statbuf = get_stats(NULL, &append_bin_stats,
(void *)c,0
&engine_statlen)) == NULL) {
0
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0);
0
@@ -1304,7 +1309,8 @@ static void process_bin_stat(conn *c) {
0
memcpy(ptr, engine_statbuf, engine_statlen);
0
- append_bin_stats(ptr, NULL, 0, NULL, 0); /* append termination packet */
0
+ /* append termination packet */
0
+ append_bin_stats(ptr, NULL, 0, NULL, 0, (void *)c);
0
@@ -1319,7 +1325,7 @@ static void process_bin_stat(conn *c) {
0
- append_bin_stats(buf, NULL, 0, NULL, 0
);
0
+ append_bin_stats(buf, NULL, 0, NULL, 0
, (void *)c);
0
write_and_free(c, buf, sizeof(header->response));
0
} else if (strncmp(subcommand, "detail", 6) == 0) {
0
char *subcmd_pos = subcommand + 6;
0
@@ -1346,9 +1352,9 @@ static void process_bin_stat(conn *c) {
0
nbytes = append_bin_stats(bufpos, "detailed", strlen("detailed"),
0
+ dump_buf, len
, (void *)c);
0
- nbytes += append_bin_stats(bufpos, NULL, 0, NULL, 0
);
0
+ nbytes += append_bin_stats(bufpos, NULL, 0, NULL, 0
, (void *)c);
0
write_and_free(c, buf, nbytes);
0
@@ -1372,12 +1378,12 @@ static void process_bin_stat(conn *c) {
0
- len = append_bin_stats(bufpos, NULL, 0, NULL, 0
);
0
+ len = append_bin_stats(bufpos, NULL, 0, NULL, 0
, (void *)c);
0
write_and_free(c, buf, len);
0
- buf = get_stats(subcommand, &append_bin_stats,
&len);
0
+ buf = get_stats(subcommand, &append_bin_stats,
(void *)c, &len);
0
memset(subcommand, 0, strlen(subcommand));
0
/* len is set to -1 in get_stats if memory couldn't be allocated */
0
@@ -1971,11 +1977,17 @@ inline static void process_stats_detail(conn *c, const char *command) {
0
/* return server specific stats only */
0
-static char *server_stats(bool binprot, int *buflen) {
0
+static char *server_stats(uint32_t (*add_stats)(char *buf, const char *key,
0
+ const uint16_t klen, const char *val,
0
+ const uint32_t vlen, void *cookie), conn *c,
0
rel_time_t now = current_time;
0
@@ -1985,84 +1997,126 @@ static char *server_stats(bool binprot, int *buflen) {
0
- pos += sprintf(pos, "STAT pid %lu\r\n", (long)pid);
0
- pos += sprintf(pos, "STAT uptime %u\r\n", now);
0
- pos += sprintf(pos, "STAT time %ld\r\n", now + stats.started);
0
- pos += sprintf(pos, "STAT version " VERSION "\r\n");
0
- pos += sprintf(pos, "STAT pointer_size %d\r\n", (int)(8 * sizeof(void *)));
0
+ vlen = sprintf(val, "%lu", (long)pid);
0
+ nbytes = add_stats(pos, "pid", strlen("pid"), val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%u", now);
0
+ nbytes = add_stats(pos, "uptime", strlen("uptime"), val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%ld", now + stats.started);
0
+ nbytes = add_stats(pos, "time", strlen("time"), val, vlen, (void *)c);
0
+ nbytes = add_stats(pos, "version", strlen("version"), VERSION,
0
+ strlen(VERSION), (void *)c);
0
+ vlen = sprintf(val, "%d", (int)(8 * sizeof(void *)));
0
+ nbytes = add_stats(pos, "pointer_size", strlen("pointer_size"), val, vlen,
0
- pos += sprintf(pos, "STAT rusage_user %ld.%06ld\r\n", (long)usage.ru_utime.tv_sec, (long)usage.ru_utime.tv_usec);
0
- pos += sprintf(pos, "STAT rusage_system %ld.%06ld\r\n", (long)usage.ru_stime.tv_sec, (long)usage.ru_stime.tv_usec);
0
+ vlen = sprintf(val, "%ld.%06ld", (long)usage.ru_utime.tv_sec,
0
+ (long)usage.ru_utime.tv_usec);
0
+ nbytes = add_stats(pos, "rusage_user", strlen("rusage_user"), val, vlen,
0
+ vlen = sprintf(val, "%ld.%06ld", (long)usage.ru_stime.tv_sec,
0
+ (long)usage.ru_stime.tv_usec);
0
+ nbytes = add_stats(pos, "rusage_system", strlen("rusage_system"), val,
0
- pos += sprintf(pos, "STAT curr_connections %u\r\n", stats.curr_conns - 1); /* ignore listening conn */
0
- pos += sprintf(pos, "STAT total_connections %u\r\n", stats.total_conns);
0
- pos += sprintf(pos, "STAT connection_structures %u\r\n", stats.conn_structs);
0
- pos += sprintf(pos, "STAT cmd_get %llu\r\n",
0
- (unsigned long long)stats.get_cmds);
0
- pos += sprintf(pos, "STAT cmd_set %llu\r\n",
0
- (unsigned long long)stats.set_cmds);
0
- pos += sprintf(pos, "STAT get_hits %llu\r\n",
0
- (unsigned long long)stats.get_hits);
0
- pos += sprintf(pos, "STAT get_misses %llu\r\n",
0
- (unsigned long long)stats.get_misses);
0
- pos += sprintf(pos, "STAT bytes_read %llu\r\n",
0
- (unsigned long long)stats.bytes_read);
0
- pos += sprintf(pos, "STAT bytes_written %llu\r\n",
0
- (unsigned long long)stats.bytes_written);
0
- pos += sprintf(pos, "STAT limit_maxbytes %llu\r\n",
0
- (unsigned long long)settings.maxbytes);
0
- pos += sprintf(pos, "STAT threads %u\r\n", settings.num_threads);
0
- /* "END" removed since the storage related stats is appended to this output */
0
- /* our work is done for ascii protocol */
0
- if((buf = malloc(strlen(temp))) == NULL)
0
- *buflen = strlen(temp);
0
- memcpy(buf, temp, strlen(temp));
0
- /* from here on is for the binary protocol */
0
- if((buf = malloc(1024)) == NULL)
0
+ vlen = sprintf(val, "%u", stats.curr_conns - 1); /* ignore listening conn */
0
+ nbytes = add_stats(pos, "curr_connections", strlen("curr_connections"),
0
+ val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%u", stats.total_conns);
0
+ nbytes = add_stats(pos, "total_connections", strlen("total_connections"),
0
+ val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%u", stats.conn_structs);
0
+ nbytes = add_stats(pos, "connection_structures",
0
+ strlen("connection_structures"), val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.get_cmds);
0
+ nbytes = add_stats(pos, "cmd_get", strlen("cmd_get"), val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.set_cmds);
0
+ nbytes = add_stats(pos, "cmd_set", strlen("cmd_set"), val, vlen, (void *)c);
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.get_hits);
0
+ nbytes = add_stats(pos, "get_hits", strlen("get_hits"), val, vlen,
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.get_misses);
0
+ nbytes = add_stats(pos, "get_misses", strlen("get_misses"), val, vlen,
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.bytes_read);
0
+ nbytes = add_stats(pos, "bytes_read", strlen("bytes_read"), val, vlen,
0
+ vlen = sprintf(val, "%llu", (unsigned long long)stats.bytes_written);
0
+ nbytes = add_stats(pos, "bytes_written", strlen("bytes_written"), val,
0
+ vlen = sprintf(val, "%llu", (unsigned long long)settings.maxbytes);
0
+ nbytes = add_stats(pos, "limit_maxbytes", strlen("limit_maxbytes"), val,
0
+ vlen = sprintf(val, "%u", settings.num_threads);
0
+ nbytes = add_stats(pos, "threads", strlen("threads"), val, vlen, (void *)c);
0
+ if(*buflen > 0 && (buf = malloc(*buflen)) == NULL) {
0
- char *end_attr, *end_row, *end_stats;
0
- end_stats = strchr(pos, '\0');
0
- while(pos < end_stats) {
0
- end_row = strchr(pos, '\n');
0
- pos += strlen("STATS");
0
- for (end_attr = pos; isgraph(*end_attr); end_attr++);
0
- memcpy(key, pos, (size_t)(end_attr - pos));
0
- for (end_attr = pos; !(isspace(*end_attr)); end_attr++);
0
- memcpy(val, pos, (size_t)(end_attr - pos));
0
- pos = end_row + 1; /* increment pointer to next row */
0
- bodylen = append_bin_stats(bufptr, key, strlen(key), val, strlen(val));
0
+ memcpy(buf, temp, *buflen);
0
uint32_t append_ascii_stats(char *buf, const char *key, const uint16_t klen,
0
- const char *val, const uint32_t vlen
) {
0
+ const char *val, const uint32_t vlen
, void *cookie) {
0
@@ -2093,23 +2147,24 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
0
command = tokens[COMMAND_TOKEN].value;
0
if (ntokens == 2 && strcmp(command, "stats") == 0) {
0
- int server_
statlen, engine_statlen;
0
+ int server_
len, engine_len;
0
char *buf, *ptr, *server_statbuf, *engine_statbuf;
0
- if ((server_statbuf = server_stats(false, &server_statlen)) == NULL) {
0
+ if ((server_statbuf = server_stats(&append_ascii_stats, c,
0
+ &server_len)) == NULL) {
0
out_string(c, "SERVER_ERROR out of memory writing stats");
0
- if ((engine_statbuf = get_stats(NULL, &append_ascii_stats,
0
- &engine_statlen)) == NULL) {
0
+ if ((engine_statbuf = get_stats(NULL, &append_ascii_stats, (void *)c,
0
+ &engine_len)) == NULL) {
0
out_string(c, "SERVER_ERROR out of memory writing stats");
0
/* 6 is: strlen("END\r\n") + sizeof("\0") */
0
- buf = calloc(1, server_
statlen + engine_statlen + 6);
0
+ buf = calloc(1, server_
len + engine_len + 6);
0
@@ -2120,18 +2175,18 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
0
- memcpy(ptr, server_statbuf, server_statlen);
0
- ptr += server_statlen;
0
- memcpy(ptr, engine_statbuf, engine_statlen);
0
- ptr += engine_statlen;
0
+ memcpy(ptr, server_statbuf, server_len);
0
+ memcpy(ptr, engine_statbuf, engine_len);
0
/* append terminator */
0
- engine_
statlen += append_ascii_stats(ptr, NULL, 0, NULL, 0);
0
+ engine_
len += append_ascii_stats(ptr, NULL, 0, NULL, 0, (void *)c);
0
- write_and_free(c, buf, server_
statlen + engine_statlen);
0
+ write_and_free(c, buf, server_
len + engine_len);
0
@@ -2147,7 +2202,7 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
0
#ifdef HAVE_STRUCT_MALLINFO
0
if (strcmp(subcommand, "malloc") == 0) {
0
- char *buf = get_stats("malloc", &append_ascii_stats,
&len);
0
+ char *buf = get_stats("malloc", &append_ascii_stats,
(void *)c, &len);
0
write_and_free(c, buf, len);
0
@@ -2228,7 +2283,7 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
0
/* getting here means that the subcommand is either engine specific or
0
is invalid. query the engine and see. */
0
- char *buf = get_stats(subcommand, &append_ascii_stats,
&bytes);
0
+ char *buf = get_stats(subcommand, &append_ascii_stats,
(void *)c, &bytes);
0
if (buf && bytes > 0) {
0
write_and_free(c, buf, bytes);