From 52778791807b6678295495f90006a251de1a2ba3 Mon Sep 17 00:00:00 2001 From: Dustin Sallings Date: Tue, 17 Mar 2009 23:17:33 -0700 Subject: Added stats settings. Stats settings gives a dump of the overall settings of the server. This is useful for verifying the effect of commandline parameters as well as helping others debug odd behaviors. --- doc/protocol.txt | 37 +++++++++++++++++++++ memcached.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ memcached.h | 1 + t/binary.t | 12 ++++++- t/stats.t | 8 ++++- 5 files changed, 153 insertions(+), 2 deletions(-) diff --git a/doc/protocol.txt b/doc/protocol.txt index 9bfe901..743b4ac 100644 --- a/doc/protocol.txt +++ b/doc/protocol.txt @@ -408,6 +408,43 @@ integers separated by a colon (treat this as a floating point number). | | | (see doc/threads.txt) | |-----------------------+---------+-------------------------------------------| +Settings statistics +------------------- +CAVEAT: This section describes statistics which are subject to change in the +future. + +The "stats" command with the argument of "settings" returns details of +the settings of the running memcached. This is primarily made up of +the results of processing commandline options. + +Note that these are not guaranteed to return in any specific order and +this list may not be exhaustive. Otherwise, this returns like any +other stats command. + +|-----------------+----------+----------------------------------------------| +| Name | Type | Meaning | +|-----------------+----------+----------------------------------------------| +| maxbytes | size_t | Maximum number of bytes allows in this cache | +| maxconns | 32 | Maximum number of clients allowed. | +| tcpport | 32 | TCP listen port. | +| udpport | 32 | UDP listen port. | +| inter | string | Listen interface. | +| verbosity | 32 | 0 = none, 1 = some, 2 = lots | +| oldest | 32u | Age of the oldest honored object. | +| evictions | on/off | When off, LRU evictions are disabled. | +| domain_socket | string | Path to the domain socket (if any). | +| umask | 32 (oct) | umask for the creation of the domain socket. | +| growth_factor | float | Chunk size growth factor. | +| chunk_size | 32 | Minimum space allocated for key+value+flags | +| num_threads | 32 | Number of threads (including dispatch). | +| stat_key_prefix | char | Stats prefix separator character. | +| detail_enabled | bool | If yes, stats detail is enabled. | +| reqs_per_event | 32 | Max num IO ops processed within an event. | +| cas_enabled | bool | When no, CAS is not enabled for this server. | +| tcp_backlog | 32 | TCP listen backlog. +|-----------------+----------+----------------------------------------------| + + Item statistics --------------- CAVEAT: This section describes statistics which are subject to change in the diff --git a/memcached.c b/memcached.c index 1772b8c..1612668 100644 --- a/memcached.c +++ b/memcached.c @@ -69,6 +69,14 @@ static char *server_stats(uint32_t (*add_stats)(char *buf, const char *key, const uint16_t klen, const char *val, const uint32_t vlen, void *cookie), conn *c, int *buflen); +static char *process_stat_settings(uint32_t (*add_stats)(char *buf, + const char *k, + const uint16_t kl, + const char *v, + const uint32_t vl, + void *cookie), + void *c, int *buflen); + /* defaults */ static void settings_init(void); @@ -1367,6 +1375,23 @@ static void process_bin_stat(conn *c) { append_bin_stats(buf, NULL, 0, NULL, 0, (void *)c); write_and_free(c, buf, sizeof(header->response)); + } else if (strncmp(subcommand, "settings", 8) == 0) { + int buflen = 0; + char *buf = NULL, *ptr = NULL; + + if ((buf = process_stat_settings(&append_bin_stats, (void *)c, + &buflen)) == NULL) { + write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); + return; + } + + /* XXX: append termination packet Like all these, assume it + fits. :/ */ + ptr = buf + buflen; + append_bin_stats(ptr, NULL, 0, NULL, 0, (void *)c); + + write_and_free(c, buf, buflen + sizeof(header->response)); + return; } else if (strncmp(subcommand, "detail", 6) == 0) { char *subcmd_pos = subcommand + 6; char *bufpos; @@ -2306,6 +2331,61 @@ uint32_t append_ascii_stats(char *buf, const char *key, const uint16_t klen, return nbytes; } +/* Local macro existing specifically to process stats */ +#define APPEND_STAT(fmt, name, val) \ + vlen = sprintf(val_str, fmt, val); \ + size = add_stats(pos, name, strlen(name), val_str, vlen, c); \ + *buflen += size; \ + pos += size; \ + assert(*buflen < allocated); + +static char *process_stat_settings(uint32_t (*add_stats)(char *buf, + const char *k, + const uint16_t kl, + const char *v, + const uint32_t vl, + void *cookie), + void *c, int *buflen) { + char *buf = NULL, *pos = NULL; + char val_str[128]; + int size = 0, vlen = 0, allocated = 2048; + *buflen = 0; + + assert(add_stats); + + buf = calloc(allocated, 1); + if (!buf) { + return NULL; + } + + pos = buf; + + APPEND_STAT("%u", "maxbytes", (unsigned int)settings.maxbytes); + APPEND_STAT("%d", "maxconns", settings.maxconns); + APPEND_STAT("%d", "tcpport", settings.port); + APPEND_STAT("%d", "udpport", settings.udpport); + APPEND_STAT("%s", "inter", settings.inter ? settings.inter : "NULL"); + APPEND_STAT("%d", "verbosity", settings.verbose); + APPEND_STAT("%lu", "oldest", (unsigned long)settings.oldest_live); + APPEND_STAT("%s", "evictions", settings.evict_to_free ? "on" : "off"); + APPEND_STAT("%s", "domain_socket", + settings.socketpath ? settings.socketpath : "NULL"); + APPEND_STAT("%o", "umask", settings.access); + APPEND_STAT("%.2f", "growth_factor", settings.factor); + APPEND_STAT("%d", "chunk_size", settings.chunk_size); + APPEND_STAT("%d", "num_threads", settings.num_threads); + APPEND_STAT("%c", "stat_key_prefix", settings.prefix_delimiter); + APPEND_STAT("%s", "detail_enabled", + settings.detail_enabled ? "yes" : "no"); + APPEND_STAT("%d", "reqs_per_event", settings.reqs_per_event); + APPEND_STAT("%s", "cas_enabled", settings.use_cas ? "yes" : "no"); + APPEND_STAT("%d", "tcp_backlog", settings.backlog); + + return buf; +} + +#undef APPEND_STAT + static void process_stat(conn *c, token_t *tokens, const size_t ntokens) { char *command; char *subcommand; @@ -2380,6 +2460,23 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) { return; } + if (strcmp(subcommand, "settings") == 0) { + int buflen = 0; + char *buf = NULL, *ptr = NULL; + + if ((buf = process_stat_settings(&append_ascii_stats, (void *)c, + &buflen)) == NULL) { + out_string(c, "SERVER_ERROR out of memory writing stats"); + return; + } + + ptr = buf + buflen; + /* XXX: append terminator (assumes space) */ + buflen += append_ascii_stats(ptr, NULL, 0, NULL, 0, (void *)c); + + write_and_free(c, buf, buflen); + return; + } if (strcmp(subcommand, "cachedump") == 0) { diff --git a/memcached.h b/memcached.h index 0b2f0df..9298192 100644 --- a/memcached.h +++ b/memcached.h @@ -103,6 +103,7 @@ struct stats { #define MAX_VERBOSITY_LEVEL 2 +/* When adding a setting, be sure to update process_stat_settings */ struct settings { size_t maxbytes; int maxconns; diff --git a/t/binary.t b/t/binary.t index c0605ca..2f0396b 100755 --- a/t/binary.t +++ b/t/binary.t @@ -2,7 +2,7 @@ use strict; use warnings; -use Test::More tests => 797; +use Test::More tests => 857; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -333,6 +333,16 @@ $mc->silent_mutation(::CMD_ADDQ, 'silentadd', 'silentaddval'); } } +# diag "Test stats settings." +{ + my %stats = $mc->stats('settings'); + + is(1024, $stats{'maxconns'}); + is('NULL', $stats{'domain_socket'}); + is('on', $stats{'evictions'}); + is('yes', $stats{'cas_enabled'}); +} + # Along with the assertion added to the code to verify we're staying # within bounds when we do a stats detail dump (detail turned on at # the top). diff --git a/t/stats.t b/t/stats.t index e5d3af8..28f9133 100755 --- a/t/stats.t +++ b/t/stats.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; -use Test::More tests => 70; +use Test::More tests => 74; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -146,3 +146,9 @@ is(scalar <$sock>, "STORED\r\n", "good cas"); check_cas_stats(1, 1, 1); my ($newid, $v) = mem_gets($sock, 'c'); is('z', $v, 'got the expected value'); + +my $settings = mem_stats($sock, ' settings'); +is(1024, $settings->{'maxconns'}); +is('NULL', $settings->{'domain_socket'}); +is('on', $settings->{'evictions'}); +is('yes', $settings->{'cas_enabled'}); -- cgit v1.2.1