Hi evreyone,

I just found out the "stats detail" command, which is not far from a point I
raised some time ago about more detailed statistics :-)
However, in my use, the keys are using a fixed size prefix without delimiter
so the -D option is pretty useless :-(
So I have just added in what I hope a seamless way the support for fixed
sized prefix.

the patch is attached,

cheers,
Jean-Charles
diff --git a/memcached.c b/memcached.c
index 98578c4..3898153 100644
--- a/memcached.c
+++ b/memcached.c
@@ -189,6 +189,7 @@ static void settings_init(void) {
     settings.chunk_size = 48;         /* space for a modest key and value */
     settings.num_threads = 4 + 1;     /* N workers + 1 dispatcher */
     settings.prefix_delimiter = ':';
+    settings.prefix_size = 0;
     settings.detail_enabled = 0;
     settings.reqs_per_event = 20;
     settings.backlog = 1024;
@@ -2136,6 +2137,7 @@ static void process_stat_settings(ADD_STAT add_stats, 
void *c) {
     APPEND_STAT("chunk_size", "%d", settings.chunk_size);
     APPEND_STAT("num_threads", "%d", settings.num_threads);
     APPEND_STAT("stat_key_prefix", "%c", settings.prefix_delimiter);
+    APPEND_STAT("stat_key_prefix_size", "%d", settings.prefix_size);
     APPEND_STAT("detail_enabled", "%s",
                 settings.detail_enabled ? "yes" : "no");
     APPEND_STAT("reqs_per_event", "%d", settings.reqs_per_event);
@@ -3717,7 +3719,9 @@ static void usage(void) {
 #endif
            );
 
-    printf("-D <char>     Use <char> as the delimiter between key prefixes and 
IDs.\n"
+    printf("-D <char>|[len]  Use <char> as the delimiter between key prefixes 
and IDs.\n"
+           "              If the given value is surrounded by [], this is 
interpreted\n"
+           "              as a fixed size prefix length. \n"
            "              This is used for per-prefix stats reporting. The 
default is\n"
            "              \":\" (colon). If this option is specified, stats 
collection\n"
            "              is turned on automatically; if not, then it may be 
turned on\n"
@@ -4024,7 +4028,17 @@ int main (int argc, char **argv) {
                 fprintf(stderr, "No delimiter specified\n");
                 return 1;
             }
-            settings.prefix_delimiter = optarg[0];
+            if(optarg[1] != 0 && (optarg[0] == '[' || optarg[0] == '_')) /* 
looks like a prefix length, '_' is to allow bypassing perl issue with '['*/
+            {
+              settings.prefix_size = atoi(optarg+1);
+              if (settings.prefix_size == 0) {
+                  fprintf(stderr, "Prefix size must be greater than 0\n");
+                  return 1;
+              }
+            }
+            else {
+              settings.prefix_delimiter = optarg[0]; /* single character 
delimiter */
+            }
             settings.detail_enabled = 1;
             break;
         case 'L' :
diff --git a/memcached.h b/memcached.h
index 2764b52..4e3fa81 100644
--- a/memcached.h
+++ b/memcached.h
@@ -252,6 +252,7 @@ struct settings {
     int chunk_size;
     int num_threads;        /* number of libevent threads to run */
     char prefix_delimiter;  /* character that marks a key prefix (for stats) */
+    int prefix_size;        /* prefix length if fixed size prefix (used rather 
than prefix_delimiter if not null)*/
     int detail_enabled;     /* nonzero if we're collecting detailed stats */
     int reqs_per_event;     /* Maximum number of io to process on each
                                io-event. */
diff --git a/stats.c b/stats.c
index 636107e..65cd7d7 100644
--- a/stats.c
+++ b/stats.c
@@ -71,9 +71,14 @@ static PREFIX_STATS *stats_prefix_find(const char *key, 
const size_t nkey) {
 
     assert(key != NULL);
 
-    for (length = 0; key[length] != '\0' && length < nkey; length++)
-        if (key[length] == settings.prefix_delimiter)
-            break;
+    if( settings.prefix_size == 0) /* we are using prefix_delimiter */
+    {
+      for (length = 0; key[length] != '\0' && length < nkey; length++)
+          if (key[length] == settings.prefix_delimiter)
+              break;
+    } else { /* we are using fixed size prefix */
+      length = settings.prefix_size < nkey ? settings.prefix_size : nkey;
+    }
 
     hashval = hash(key, length, 0) % PREFIX_HASH_SIZE;
 
diff --git a/t/stats-detail-fixed-size.t b/t/stats-detail-fixed-size.t
new file mode 100755
index 0000000..11e1144
--- /dev/null
+++ b/t/stats-detail-fixed-size.t
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+use strict;
+use Test::More tests => 24;
+use FindBin qw($Bin);
+use lib "$Bin/lib";
+use MemcachedTest;
+
+my $server = new_memcached('-D _3');
+my $sock = $server->sock;
+my $expire;
+
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "END\r\n", "verified empty stats at start");
+
+print $sock "stats detail on\r\n";
+is(scalar <$sock>, "OK\r\n", "detail collection turned on");
+
+print $sock "set foo:123 0 0 6\r\nfooval\r\n";
+is(scalar <$sock>, "STORED\r\n", "stored foo");
+
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 0 hit 0 set 1 del 0\r\n", "details after 
set");
+is(scalar <$sock>, "END\r\n", "end of details");
+
+mem_get_is($sock, "foo:123", "fooval");
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 1 del 0\r\n", "details after 
get with hit");
+is(scalar <$sock>, "END\r\n", "end of details");
+
+mem_get_is($sock, "foo:124", undef);
+
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 2 hit 1 set 1 del 0\r\n", "details after 
get without hit");
+is(scalar <$sock>, "END\r\n", "end of details");
+
+print $sock "delete foo:125 0\r\n";
+is(scalar <$sock>, "NOT_FOUND\r\n", "sent delete command");
+
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 2 hit 1 set 1 del 1\r\n", "details after 
delete");
+is(scalar <$sock>, "END\r\n", "end of details");
+
+print $sock "stats reset\r\n";
+is(scalar <$sock>, "RESET\r\n", "stats cleared");
+
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "END\r\n", "empty stats after clear");
+
+mem_get_is($sock, "foo:123", "fooval");
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 0 del 0\r\n", "details after 
clear and get");
+is(scalar <$sock>, "END\r\n", "end of details");
+
+print $sock "stats detail off\r\n";
+is(scalar <$sock>, "OK\r\n", "detail collection turned off");
+
+mem_get_is($sock, "foo:124", undef);
+
+mem_get_is($sock, "foo:123", "fooval");
+print $sock "stats detail dump\r\n";
+is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 0 del 0\r\n", "details after 
stats turned off");
+is(scalar <$sock>, "END\r\n", "end of details");

Reply via email to