<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -335,7 +335,7 @@ char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit
 
 char *do_item_stats(uint32_t (*add_stats)(char *buf,
                     const char *key, const uint16_t klen, const char *val,
-                    const uint32_t vlen), int *bytes) {
+                    const uint32_t vlen, void *cookie), void *c, int *bytes) {
 
     size_t bufleft = (size_t) LARGEST_ID * 240;
     char *buffer = malloc(bufleft);
@@ -358,31 +358,31 @@ char *do_item_stats(uint32_t (*add_stats)(char *buf,
 
             sprintf(key, &quot;items:%d:number&quot;, i);
             sprintf(val, &quot;%u&quot;, sizes[i]);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;items:%d:age&quot;, i);
             sprintf(val, &quot;%u&quot;, now - tails[i]-&gt;time);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;items:%d:evicted&quot;, i);
             sprintf(val, &quot;%u&quot;, itemstats[i].evicted);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;items:%d:evicted_time&quot;, i);
             sprintf(val, &quot;%u&quot;, itemstats[i].evicted_time);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;items:%d:outofmemory&quot;, i);
             sprintf(val, &quot;%u&quot;, itemstats[i].outofmemory);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
@@ -397,7 +397,7 @@ char *do_item_stats(uint32_t (*add_stats)(char *buf,
     }
 
     /* getting here means both ascii and binary terminators fit */
-    linelen += add_stats(bufcurr, NULL, 0, NULL, 0);
+    linelen += add_stats(bufcurr, NULL, 0, NULL, 0, c);
     *bytes = linelen;
 
     return buffer;
@@ -405,9 +405,9 @@ char *do_item_stats(uint32_t (*add_stats)(char *buf,
 
 /** dumps out a list of objects of each size, with granularity of 32 bytes */
 /*@null@*/
-char *do_item_stats_sizes(uint32_t (*add_stats)(char *buf, const char *key,
-                          const uint16_t klen, const char *val,
-                          const uint32_t vlen), int *bytes) {
+char *do_item_stats_sizes(uint32_t (*add_stats)(char *buf,
+                          const char *key, const uint16_t klen, const char *val,
+                          const uint32_t vlen, void *cookie), void *c, int *bytes) {
 
     const int num_buckets = 32768;   /* max 1MB object, divided into 32 bytes size buckets */
     unsigned int *histogram = (unsigned int *)malloc((size_t)num_buckets * sizeof(int));
@@ -445,13 +445,13 @@ char *do_item_stats_sizes(uint32_t (*add_stats)(char *buf, const char *key,
         if (histogram[i] != 0) {
             sprintf(key, &quot;%d&quot;, i * 32);
             sprintf(val, &quot;%u&quot;, histogram[i]);
-            nbytes = add_stats(ptr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(ptr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             ptr += nbytes;
         }
     }
 
-    nbytes = add_stats(ptr, NULL, 0, NULL, 0);
+    nbytes = add_stats(ptr, NULL, 0, NULL, 0, c);
     *bytes = linelen + nbytes;
 
     free(histogram);</diff>
      <filename>items.c</filename>
    </modified>
    <modified>
      <diff>@@ -15,11 +15,11 @@ int  do_item_replace(item *it, item *new_it);
 char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, unsigned int *bytes);
 char *do_item_stats(uint32_t (*add_stats)(char *buf, const char *key,
                     const uint16_t klen, const char *val,
-                    const uint32_t vlen), int *bytes);
+                    const uint32_t vlen, void *cookie), void *c, int *bytes);
 /*@null@*/
-char *do_item_stats_sizes(uint32_t (*add_stats)(char *buf, const char *key,
-                          const uint16_t klen, const char *val,
-                          const uint32_t vlen), int *bytes);
+char *do_item_stats_sizes(uint32_t (*add_stats)(char *buf,
+                          const char *key, const uint16_t klen, const char *val,
+                          const uint32_t vlen, void *cookie), void *c, int *bytes);
 
 void do_item_flush_expired(void);
 </diff>
      <filename>items.h</filename>
    </modified>
    <modified>
      <diff>@@ -67,7 +67,10 @@ static void conn_set_state(conn *c, enum conn_states state);
 /* stats */
 static void stats_reset(void);
 static void stats_init(void);
-static char *server_stats(bool binprot, int *size);
+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);
 
 /* defaults */
 static void settings_init(void);
@@ -1227,11 +1230,12 @@ static void process_bin_get(conn *c) {
 }
 
 uint32_t append_bin_stats(char *buf, const char *key, const uint16_t klen,
-                          const char *val, const uint32_t vlen) {
+                          const char *val, const uint32_t vlen, void *cookie) {
     protocol_binary_response_header *header;
     char *ptr = buf;
     uint32_t bodylen = klen + vlen;
     header = (protocol_binary_response_header *)ptr;
+    conn *c = (conn *)cookie;
 
     header-&gt;response.magic = (uint8_t)PROTOCOL_BINARY_RES;
     header-&gt;response.opcode = PROTOCOL_BINARY_CMD_STAT;
@@ -1240,8 +1244,8 @@ uint32_t append_bin_stats(char *buf, const char *key, const uint16_t klen,
     header-&gt;response.datatype = (uint8_t)PROTOCOL_BINARY_RAW_BYTES;
     header-&gt;response.status = (uint16_t)htons(0);
     header-&gt;response.bodylen = htonl(bodylen);
-    header-&gt;response.opaque = htonl(0);
-    header-&gt;response.cas = swap64(0); /* this can be anything... */
+    header-&gt;response.opaque = c-&gt;opaque;
+    header-&gt;response.cas = swap64(0);
     ptr += sizeof(header-&gt;response);
 
     if (klen &gt; 0) {
@@ -1276,12 +1280,13 @@ static void process_bin_stat(conn *c) {
         int server_statlen, engine_statlen;
         char *ptr, *server_statbuf, *engine_statbuf;
 
-        if ((server_statbuf = server_stats(true, &amp;server_statlen)) == NULL) {
+        if ((server_statbuf = server_stats(&amp;append_bin_stats, (void *)c,
+                                           &amp;server_statlen)) == NULL) {
             write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0);
             return;
         }
 
-        if ((engine_statbuf = get_stats(NULL, &amp;append_bin_stats,
+        if ((engine_statbuf = get_stats(NULL, &amp;append_bin_stats, (void *)c,
                                         &amp;engine_statlen)) == NULL) {
             free(server_statbuf);
             write_bin_error(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0);
@@ -1304,7 +1309,8 @@ static void process_bin_stat(conn *c) {
         memcpy(ptr, engine_statbuf, engine_statlen);
         ptr += engine_statlen;
 
-        append_bin_stats(ptr, NULL, 0, NULL, 0); /* append termination packet */
+        /* append termination packet */
+        append_bin_stats(ptr, NULL, 0, NULL, 0, (void *)c);
 
         free(server_statbuf);
         free(engine_statbuf);
@@ -1319,7 +1325,7 @@ static void process_bin_stat(conn *c) {
 
         stats_reset();
 
-        append_bin_stats(buf, NULL, 0, NULL, 0);
+        append_bin_stats(buf, NULL, 0, NULL, 0, (void *)c);
         write_and_free(c, buf, sizeof(header-&gt;response));
     } else if (strncmp(subcommand, &quot;detail&quot;, 6) == 0) {
         char *subcmd_pos = subcommand + 6;
@@ -1346,9 +1352,9 @@ static void process_bin_stat(conn *c) {
             bufpos = buf;
 
             nbytes = append_bin_stats(bufpos, &quot;detailed&quot;, strlen(&quot;detailed&quot;),
-                                      dump_buf, len);
+                                      dump_buf, len, (void *)c);
             bufpos += nbytes;
-            nbytes += append_bin_stats(bufpos, NULL, 0, NULL, 0);
+            nbytes += append_bin_stats(bufpos, NULL, 0, NULL, 0, (void *)c);
             free(dump_buf);
 
             write_and_free(c, buf, nbytes);
@@ -1372,12 +1378,12 @@ static void process_bin_stat(conn *c) {
             return;
         }
 
-        len = append_bin_stats(bufpos, NULL, 0, NULL, 0);
+        len = append_bin_stats(bufpos, NULL, 0, NULL, 0, (void *)c);
         write_and_free(c, buf, len);
         return;
     } else {
         int len = 0;
-        buf = get_stats(subcommand, &amp;append_bin_stats, &amp;len);
+        buf = get_stats(subcommand, &amp;append_bin_stats, (void *)c, &amp;len);
         memset(subcommand, 0, strlen(subcommand));
 
         /* len is set to -1 in get_stats if memory couldn't be allocated */
@@ -1971,11 +1977,17 @@ inline static void process_stats_detail(conn *c, const char *command) {
 }
 
 /* return server specific stats only */
-static char *server_stats(bool binprot, int *buflen) {
+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) {
     char temp[1024];
-    char *buf;
-    pid_t pid = getpid();
+    char val[128];
+    char *buf = NULL;
     char *pos = temp;
+    size_t nbytes;
+    int vlen = 0;
+    pid_t pid = getpid();
     rel_time_t now = current_time;
     *buflen = 0;
 
@@ -1985,84 +1997,126 @@ static char *server_stats(bool binprot, int *buflen) {
 #endif /* !WIN32 */
 
     STATS_LOCK();
-    pos += sprintf(pos, &quot;STAT pid %lu\r\n&quot;, (long)pid);
-    pos += sprintf(pos, &quot;STAT uptime %u\r\n&quot;, now);
-    pos += sprintf(pos, &quot;STAT time %ld\r\n&quot;, now + stats.started);
-    pos += sprintf(pos, &quot;STAT version &quot; VERSION &quot;\r\n&quot;);
-    pos += sprintf(pos, &quot;STAT pointer_size %d\r\n&quot;, (int)(8 * sizeof(void *)));
+    memset(val, 0, 128);
+
+    vlen = sprintf(val, &quot;%lu&quot;, (long)pid);
+    nbytes = add_stats(pos, &quot;pid&quot;, strlen(&quot;pid&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%u&quot;, now);
+    nbytes = add_stats(pos, &quot;uptime&quot;, strlen(&quot;uptime&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%ld&quot;, now + stats.started);
+    nbytes = add_stats(pos, &quot;time&quot;, strlen(&quot;time&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    nbytes = add_stats(pos, &quot;version&quot;, strlen(&quot;version&quot;), VERSION,
+                       strlen(VERSION), (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%d&quot;, (int)(8 * sizeof(void *)));
+    nbytes = add_stats(pos, &quot;pointer_size&quot;, strlen(&quot;pointer_size&quot;), val, vlen,
+                       (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
 #ifndef WIN32
-    pos += sprintf(pos, &quot;STAT rusage_user %ld.%06ld\r\n&quot;, (long)usage.ru_utime.tv_sec, (long)usage.ru_utime.tv_usec);
-    pos += sprintf(pos, &quot;STAT rusage_system %ld.%06ld\r\n&quot;, (long)usage.ru_stime.tv_sec, (long)usage.ru_stime.tv_usec);
+    vlen = sprintf(val, &quot;%ld.%06ld&quot;, (long)usage.ru_utime.tv_sec,
+                   (long)usage.ru_utime.tv_usec);
+    nbytes = add_stats(pos, &quot;rusage_user&quot;, strlen(&quot;rusage_user&quot;), val, vlen,
+                       (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%ld.%06ld&quot;, (long)usage.ru_stime.tv_sec,
+                   (long)usage.ru_stime.tv_usec);
+    nbytes = add_stats(pos, &quot;rusage_system&quot;, strlen(&quot;rusage_system&quot;), val,
+                       vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
 #endif /* !WIN32 */
-    pos += sprintf(pos, &quot;STAT curr_connections %u\r\n&quot;, stats.curr_conns - 1); /* ignore listening conn */
-    pos += sprintf(pos, &quot;STAT total_connections %u\r\n&quot;, stats.total_conns);
-    pos += sprintf(pos, &quot;STAT connection_structures %u\r\n&quot;, stats.conn_structs);
-    pos += sprintf(pos, &quot;STAT cmd_get %llu\r\n&quot;,
-                   (unsigned long long)stats.get_cmds);
-    pos += sprintf(pos, &quot;STAT cmd_set %llu\r\n&quot;,
-                   (unsigned long long)stats.set_cmds);
-    pos += sprintf(pos, &quot;STAT get_hits %llu\r\n&quot;,
-                   (unsigned long long)stats.get_hits);
-    pos += sprintf(pos, &quot;STAT get_misses %llu\r\n&quot;,
-                   (unsigned long long)stats.get_misses);
-    pos += sprintf(pos, &quot;STAT bytes_read %llu\r\n&quot;,
-                   (unsigned long long)stats.bytes_read);
-    pos += sprintf(pos, &quot;STAT bytes_written %llu\r\n&quot;,
-                   (unsigned long long)stats.bytes_written);
-    pos += sprintf(pos, &quot;STAT limit_maxbytes %llu\r\n&quot;,
-                   (unsigned long long)settings.maxbytes);
-    pos += sprintf(pos, &quot;STAT threads %u\r\n&quot;, settings.num_threads);
-    /* &quot;END&quot; removed since the storage related stats is appended to this output */
-    STATS_UNLOCK();
 
-    /* our work is done for ascii protocol */
-    if(!binprot) {
-        if((buf = malloc(strlen(temp))) == NULL)
-            return NULL;
-
-        *buflen = strlen(temp);
-        memcpy(buf, temp, strlen(temp));
-        return buf;
-    }
-
-    /* from here on is for the binary protocol */
-    if((buf = malloc(1024)) == NULL)
+    vlen = sprintf(val, &quot;%u&quot;, stats.curr_conns - 1); /* ignore listening conn */
+    nbytes = add_stats(pos, &quot;curr_connections&quot;, strlen(&quot;curr_connections&quot;),
+                       val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%u&quot;, stats.total_conns);
+    nbytes = add_stats(pos, &quot;total_connections&quot;, strlen(&quot;total_connections&quot;),
+                       val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%u&quot;, stats.conn_structs);
+    nbytes = add_stats(pos, &quot;connection_structures&quot;,
+                       strlen(&quot;connection_structures&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.get_cmds);
+    nbytes = add_stats(pos, &quot;cmd_get&quot;, strlen(&quot;cmd_get&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.set_cmds);
+    nbytes = add_stats(pos, &quot;cmd_set&quot;, strlen(&quot;cmd_set&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.get_hits);
+    nbytes = add_stats(pos, &quot;get_hits&quot;, strlen(&quot;get_hits&quot;), val, vlen,
+                       (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.get_misses);
+    nbytes = add_stats(pos, &quot;get_misses&quot;, strlen(&quot;get_misses&quot;), val, vlen,
+                       (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.bytes_read);
+    nbytes = add_stats(pos, &quot;bytes_read&quot;, strlen(&quot;bytes_read&quot;), val, vlen,
+                       (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.bytes_written);
+    nbytes = add_stats(pos, &quot;bytes_written&quot;, strlen(&quot;bytes_written&quot;), val,
+                       vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)settings.maxbytes);
+    nbytes = add_stats(pos, &quot;limit_maxbytes&quot;, strlen(&quot;limit_maxbytes&quot;), val,
+                       vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    vlen = sprintf(val, &quot;%u&quot;, settings.num_threads);
+    nbytes = add_stats(pos, &quot;threads&quot;, strlen(&quot;threads&quot;), val, vlen, (void *)c);
+    pos += nbytes;
+    *buflen += nbytes;
+
+    if(*buflen &gt; 0 &amp;&amp; (buf = malloc(*buflen)) == NULL) {
+        STATS_UNLOCK();
         return NULL;
-
-    char *end_attr, *end_row, *end_stats;
-    char *bufptr = buf;
-    char key[128];
-    char val[256];
-    uint32_t bodylen;
-
-    pos = temp;
-    end_stats = strchr(pos, '\0');
-
-    while(pos &lt; end_stats) {
-        memset(key, 0, 128);
-        memset(val, 0, 256);
-
-        end_row = strchr(pos, '\n');
-        pos += strlen(&quot;STATS&quot;);
-
-        for (end_attr = pos; isgraph(*end_attr); end_attr++);
-        memcpy(key, pos, (size_t)(end_attr - pos));
-
-        pos = end_attr + 1;
-        for (end_attr = pos; !(isspace(*end_attr)); end_attr++);
-        memcpy(val, pos, (size_t)(end_attr - pos));
-
-        pos = end_row + 1; /* increment pointer to next row */
-        bodylen = append_bin_stats(bufptr, key, strlen(key), val, strlen(val));
-        bufptr += bodylen;
-        *buflen += bodylen;
     }
 
+    memcpy(buf, temp, *buflen);
+    STATS_UNLOCK();
+
     return buf;
 }
 
 uint32_t append_ascii_stats(char *buf, const char *key, const uint16_t klen,
-                            const char *val, const uint32_t vlen) {
+                            const char *val, const uint32_t vlen, void *cookie) {
     char *pos = buf;
     uint32_t nbytes = 0;
 
@@ -2093,23 +2147,24 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
     command = tokens[COMMAND_TOKEN].value;
 
     if (ntokens == 2 &amp;&amp; strcmp(command, &quot;stats&quot;) == 0) {
-        int server_statlen, engine_statlen;
+        int server_len, engine_len;
         char *buf, *ptr, *server_statbuf, *engine_statbuf;
 
-        if ((server_statbuf = server_stats(false, &amp;server_statlen)) == NULL) {
+        if ((server_statbuf = server_stats(&amp;append_ascii_stats, c,
+                                           &amp;server_len)) == NULL) {
             out_string(c, &quot;SERVER_ERROR out of memory writing stats&quot;);
             return;
         }
 
-        if ((engine_statbuf = get_stats(NULL, &amp;append_ascii_stats,
-                                        &amp;engine_statlen)) == NULL) {
+        if ((engine_statbuf = get_stats(NULL, &amp;append_ascii_stats, (void *)c,
+                                        &amp;engine_len)) == NULL) {
             free(server_statbuf);
             out_string(c, &quot;SERVER_ERROR out of memory writing stats&quot;);
             return;
         }
 
         /* 6 is: strlen(&quot;END\r\n&quot;) + sizeof(&quot;\0&quot;) */
-        buf = calloc(1, server_statlen + engine_statlen + 6);
+        buf = calloc(1, server_len + engine_len + 6);
 
         if (buf == NULL) {
             free(server_statbuf);
@@ -2120,18 +2175,18 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
 
         ptr = buf;
 
-        memcpy(ptr, server_statbuf, server_statlen);
-        ptr += server_statlen;
-        memcpy(ptr, engine_statbuf, engine_statlen);
-        ptr += engine_statlen;
+        memcpy(ptr, server_statbuf, server_len);
+        ptr += server_len;
+        memcpy(ptr, engine_statbuf, engine_len);
+        ptr += engine_len;
 
         /* append terminator */
-        engine_statlen += append_ascii_stats(ptr, NULL, 0, NULL, 0);
+        engine_len += append_ascii_stats(ptr, NULL, 0, NULL, 0, (void *)c);
 
         free(server_statbuf);
         free(engine_statbuf);
 
-        write_and_free(c, buf, server_statlen + engine_statlen);
+        write_and_free(c, buf, server_len + engine_len);
         return;
     }
 
@@ -2147,7 +2202,7 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
 #ifdef HAVE_STRUCT_MALLINFO
     if (strcmp(subcommand, &quot;malloc&quot;) == 0) {
         int len = 0;
-        char *buf = get_stats(&quot;malloc&quot;, &amp;append_ascii_stats, &amp;len);
+        char *buf = get_stats(&quot;malloc&quot;, &amp;append_ascii_stats, (void *)c, &amp;len);
         write_and_free(c, buf, len);
         return;
     }
@@ -2228,7 +2283,7 @@ static void process_stat(conn *c, token_t *tokens, const size_t ntokens) {
     /* getting here means that the subcommand is either engine specific or
        is invalid. query the engine and see. */
     int bytes = 0;
-    char *buf = get_stats(subcommand, &amp;append_ascii_stats, &amp;bytes);
+    char *buf = get_stats(subcommand, &amp;append_ascii_stats, (void *)c, &amp;bytes);
 
     if (buf &amp;&amp; bytes &gt; 0) {
         write_and_free(c, buf, bytes);</diff>
      <filename>memcached.c</filename>
    </modified>
    <modified>
      <diff>@@ -281,9 +281,9 @@ char *do_add_delta(conn *c, item *item, const bool incr, const int64_t delta,
 int do_store_item(item *item, int comm, conn* c);
 conn *conn_new(const int sfd, const enum conn_states init_state, const int event_flags, const int read_buffer_size, enum protocol prot, struct event_base *base);
 uint32_t append_bin_stats(char *buf, const char *key, const uint16_t klen,
-                          const char *val, const uint32_t vlen);
+                          const char *val, const uint32_t vlen, void *cookie);
 uint32_t append_ascii_stats(char *buf, const char *key, const uint16_t klen,
-                            const char *val, const uint32_t vlen);
+                            const char *val, const uint32_t vlen, void *cookie);
 extern int daemonize(int nochdir, int noclose);
 
 
@@ -323,10 +323,10 @@ void  item_remove(item *it);
 int   item_replace(item *it, item *new_it);
 char *item_stats(uint32_t (*add_stats)(char *buf, const char *key,
                  const uint16_t klen, const char *val,
-                 const uint32_t vlen), int *bytes);
-char *item_stats_sizes(uint32_t (*add_stats)(char *buf, const char *key,
-                       const uint16_t klen, const char *val,
-                       const uint32_t vlen), int *bytes);
+                 const uint32_t vlen, void *cookie), void *c, int *bytes);
+char *item_stats_sizes(uint32_t (*add_stats)(char *buf,
+                       const char *key, const uint16_t klen, const char *val,
+                       const uint32_t vlen, void *cookie), void *c, int *bytes);
 void  item_unlink(item *it);
 void  item_update(item *it);
 void *slabs_alloc(size_t size, unsigned int id);
@@ -334,7 +334,7 @@ void  slabs_free(void *ptr, size_t size, unsigned int id);
 int   slabs_reassign(unsigned char srcid, unsigned char dstid);
 char *slabs_stats(uint32_t (*add_stats)(char *buf,
                   const char *key, const uint16_t klen, const char *val,
-                  const uint32_t vlen), int *buflen);
+                  const uint32_t vlen, void *cookie), void *c, int *buflen);
 void  STATS_LOCK(void);
 void  STATS_UNLOCK(void);
 int   store_item(item *item, int comm, conn *c);</diff>
      <filename>memcached.h</filename>
    </modified>
    <modified>
      <diff>@@ -311,12 +311,11 @@ void do_slabs_free(void *ptr, const size_t size, unsigned int id) {
 
 char *get_stats(const char *stat_type, uint32_t (*add_stats)(char *buf,
                 const char *key, const uint16_t klen, const char *val,
-                const uint32_t vlen), int *buflen) {
-
+                const uint32_t vlen, void *cookie), void *c, int *buflen) {
     char *buf, *pos;
     char val[128];
-    int size = 0;
-    *buflen = 0;
+    int size, vlen;
+    *buflen = size = vlen = 0;
 
     if (add_stats == NULL)
         return NULL;
@@ -330,40 +329,38 @@ char *get_stats(const char *stat_type, uint32_t (*add_stats)(char *buf,
         pos = buf;
 
         /* prepare general statistics for the engine */
-        sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.curr_bytes);
-        size = add_stats(pos, &quot;bytes&quot;, strlen(&quot;bytes&quot;), val, strlen(val));
+        vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.curr_bytes);
+        size = add_stats(pos, &quot;bytes&quot;, strlen(&quot;bytes&quot;), val, vlen, c);
         *buflen += size;
         pos += size;
 
-        sprintf(val, &quot;%u&quot;, stats.curr_items);
-        size = add_stats(pos, &quot;curr_items&quot;, strlen(&quot;curr_items&quot;), val,
-                         strlen(val));
+        vlen = sprintf(val, &quot;%u&quot;, stats.curr_items);
+        size = add_stats(pos, &quot;curr_items&quot;, strlen(&quot;curr_items&quot;), val, vlen, c);
         *buflen += size;
         pos += size;
 
-        sprintf(val, &quot;%u&quot;, stats.total_items);
-        size = add_stats(pos, &quot;total_items&quot;, strlen(&quot;total_items&quot;), val,
-                         strlen(val));
+        vlen = sprintf(val, &quot;%u&quot;, stats.total_items);
+        size = add_stats(pos, &quot;total_items&quot;, strlen(&quot;total_items&quot;), val, vlen,
+                         c);
         *buflen += size;
         pos += size;
 
-        sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.evictions);
-        size = add_stats(pos, &quot;evictions&quot;, strlen(&quot;evictions&quot;), val,
-                         strlen(val));
+        vlen = sprintf(val, &quot;%llu&quot;, (unsigned long long)stats.evictions);
+        size = add_stats(pos, &quot;evictions&quot;, strlen(&quot;evictions&quot;), val, vlen, c);
         *buflen += size;
         pos += size;
 
         return buf;
     } else if (strcmp(stat_type, &quot;items&quot;) == 0) {
-        buf = item_stats(add_stats, &amp;size);
+        buf = item_stats(add_stats, c, &amp;size);
         *buflen = size;
         return buf;
     } else if (strcmp(stat_type, &quot;slabs&quot;) == 0) {
-        buf = slabs_stats(add_stats, &amp;size);
+        buf = slabs_stats(add_stats, c, &amp;size);
         *buflen = size;
         return buf;
     } else if (strcmp(stat_type, &quot;sizes&quot;) == 0) {
-        buf = item_stats_sizes(add_stats, &amp;size);
+        buf = item_stats_sizes(add_stats, c, &amp;size);
         *buflen = size;
         return buf;
     }
@@ -386,67 +383,67 @@ char *get_stats(const char *stat_type, uint32_t (*add_stats)(char *buf,
         char val[128];
         uint32_t nbytes = 0;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.arena);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.arena);
         nbytes = add_stats(pos, &quot;arena_size&quot;, strlen(&quot;arena_size&quot;), val,
-                           strlen(val));
+                           vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.ordblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.ordblks);
         nbytes = add_stats(pos, &quot;free_chunks&quot;, strlen(&quot;free_chunks&quot;), val,
-                           strlen(val));
+                           vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.smblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.smblks);
         nbytes = add_stats(pos, &quot;fastbin_blocks&quot;, strlen(&quot;fastbin_blocks&quot;),
-                           val, strlen(val));
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.hblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.hblks);
         nbytes = add_stats(pos, &quot;mmapped_regions&quot;, strlen(&quot;mmapped_regions&quot;),
-                           val, strlen(val));
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.hblkhd);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.hblkhd);
         nbytes = add_stats(pos, &quot;mmapped_space&quot;, strlen(&quot;mmapped_space&quot;),
-                           val, strlen(val));
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.usmblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.usmblks);
         nbytes = add_stats(pos, &quot;max_total_alloc&quot;, strlen(&quot;max_total_alloc&quot;),
-                           val, strlen(val));
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.fsmblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.fsmblks);
         nbytes = add_stats(pos, &quot;fastbin_space&quot;, strlen(&quot;fastbin_space&quot;),
-                           val, strlen(val));
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.uordblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.uordblks);
         nbytes = add_stats(pos, &quot;total_alloc&quot;, strlen(&quot;total_alloc&quot;), val,
-                           strlen(val));
+                           vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.fordblks);
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.fordblks);
         nbytes = add_stats(pos, &quot;total_free&quot;, strlen(&quot;total_free&quot;), val,
-                            strlen(val));
+                           vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        sprintf(val, &quot;%ld&quot;, (long)info.keepcost);
-        nbytes = add_stats(pos, &quot;releasable_space&quot;,
-                           strlen(&quot;releasable_space&quot;), val, strlen(val));
+        vlen = sprintf(val, &quot;%ld&quot;, (long)info.keepcost);
+        nbytes = add_stats(pos, &quot;releasable_space&quot;, strlen(&quot;releasable_space&quot;),
+                           val, vlen, c);
         linelen += nbytes;
         pos += nbytes;
 
-        linelen += add_stats(pos, NULL, 0, NULL, 0);
+        linelen += add_stats(pos, NULL, 0, NULL, 0, c);
         *buflen = linelen;
 
         return buf;
@@ -458,9 +455,9 @@ char *get_stats(const char *stat_type, uint32_t (*add_stats)(char *buf,
 }
 
 /*@null@*/
-char *do_slabs_stats(uint32_t (*add_stats)(char *buf, const char *key,
-                     const uint16_t klen, const char *val,
-                     const uint32_t vlen), int *buflen) {
+char *do_slabs_stats(uint32_t (*add_stats)(char *buf,
+                     const char *key, const uint16_t klen, const char *val,
+                     const uint32_t vlen, void *cookie), void *c, int *buflen) {
     int i, total, linelen;
     char *buf = (char *)malloc(power_largest * 200 + 100);
     char *bufcurr = buf;
@@ -487,43 +484,43 @@ char *do_slabs_stats(uint32_t (*add_stats)(char *buf, const char *key,
 
             sprintf(key, &quot;%d:chunk_size&quot;, i);
             sprintf(val, &quot;%u&quot;, p-&gt;size);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:chunks_per_page&quot;, i);
             sprintf(val, &quot;%u&quot;, perslab);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:total_page&quot;, i);
             sprintf(val, &quot;%u&quot;, slabs);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:total_chunks&quot;, i);
             sprintf(val, &quot;%u&quot;, slabs*perslab);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:used_chunks&quot;, i);
             sprintf(val, &quot;%u&quot;, ((slabs*perslab) - p-&gt;sl_curr));
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:free_chunks&quot;, i);
             sprintf(val, &quot;%u&quot;, p-&gt;sl_curr);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
             sprintf(key, &quot;%d:free_chunks_end&quot;, i);
             sprintf(val, &quot;%u&quot;, p-&gt;end_page_free);
-            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+            nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
             linelen += nbytes;
             bufcurr += nbytes;
 
@@ -538,17 +535,17 @@ char *do_slabs_stats(uint32_t (*add_stats)(char *buf, const char *key,
 
     sprintf(key, &quot;active_slabs&quot;);
     sprintf(val, &quot;%d&quot;, total);
-    nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+    nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
     linelen += nbytes;
     bufcurr += nbytes;
 
     sprintf(key, &quot;total_malloced&quot;);
     sprintf(val, &quot;%llu&quot;, (unsigned long long)mem_malloced);
-    nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val));
+    nbytes = add_stats(bufcurr, key, strlen(key), val, strlen(val), c);
     linelen += nbytes;
     bufcurr += nbytes;
 
-    linelen += add_stats(bufcurr, NULL, 0, NULL, 0);
+    linelen += add_stats(bufcurr, NULL, 0, NULL, 0, c);
     *buflen = linelen;
 
     return buf;</diff>
      <filename>slabs.c</filename>
    </modified>
    <modified>
      <diff>@@ -25,12 +25,12 @@ void do_slabs_free(void *ptr, size_t size, unsigned int id);
 /** Return a datum for stats in binary protocol */
 char *get_stats(const char *stat_type, uint32_t (*add_stats)(char *buf,
                 const char *key, const uint16_t klen, const char *val,
-                const uint32_t vlen), int *buflen);
+                const uint32_t vlen, void *cookie), void *arg, int *buflen);
 
 /** Fill buffer with stats */ /*@null@*/
-char *do_slabs_stats(uint32_t (*add_stats)(char *buf, const char *key,
-                     const uint16_t klen, const char *val,
-                     const uint32_t vlen), int *buflen);
+char *do_slabs_stats(uint32_t (*add_stats)(char *buf,
+                     const char *key, const uint16_t klen, const char *val,
+                     const uint32_t vlen, void *cookie), void *c, int *buflen);
 
 /* Request some slab be moved between classes
   1 = success</diff>
      <filename>slabs.h</filename>
    </modified>
    <modified>
      <diff>@@ -257,7 +257,7 @@ sub _do_command {
     $extra_header = '' unless defined $extra_header;
     my $opaque = int(rand(2**32));
     $self-&gt;send_command($cmd, $key, $val, $opaque, $extra_header, $cas);
-    (undef, my $rv, my $rcas) = $self-&gt;_handle_single_response($opaque);
+    my (undef, $rv, $rcas) = $self-&gt;_handle_single_response($opaque);
     return ($rv, $rcas);
 }
 </diff>
      <filename>t/binary.t</filename>
    </modified>
    <modified>
      <diff>@@ -507,12 +507,12 @@ char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int
  * Dumps statistics about slab classes
  */
 char *item_stats(uint32_t (*add_stats)(char *buf, const char *key,
-                 const uint16_t klen, const char *val, const uint32_t vlen),
-                 int *bytes) {
+                 const uint16_t klen, const char *val, const uint32_t vlen,
+                 void *cookie), void *c, int *bytes) {
     char *ret;
 
     pthread_mutex_lock(&amp;cache_lock);
-    ret = do_item_stats(add_stats, bytes);
+    ret = do_item_stats(add_stats, c, bytes);
     pthread_mutex_unlock(&amp;cache_lock);
     return ret;
 }
@@ -520,13 +520,13 @@ char *item_stats(uint32_t (*add_stats)(char *buf, const char *key,
 /*
  * Dumps a list of objects of each size in 32-byte increments
  */
-char *item_stats_sizes(uint32_t (*add_stats)(char *buf, const char *key,
-                       const uint16_t klen, const char *val,
-                       const uint32_t vlen), int *bytes) {
+char *item_stats_sizes(uint32_t (*add_stats)(char *buf,
+                       const char *key, const uint16_t klen, const char *val,
+                       const uint32_t vlen, void *cookie), void *c, int *bytes) {
     char *ret;
 
     pthread_mutex_lock(&amp;cache_lock);
-    ret = do_item_stats_sizes(add_stats, bytes);
+    ret = do_item_stats_sizes(add_stats, c, bytes);
     pthread_mutex_unlock(&amp;cache_lock);
     return ret;
 }
@@ -556,13 +556,13 @@ void slabs_free(void *ptr, size_t size, unsigned int id) {
     pthread_mutex_unlock(&amp;slabs_lock);
 }
 
-char *slabs_stats(uint32_t (*add_stats)(char *buf, const char *key,
-                  const uint16_t klen, const char *val,
-                  const uint32_t vlen), int *buflen) {
+char *slabs_stats(uint32_t (*add_stats)(char *buf,
+                  const char *key, const uint16_t klen, const char *val,
+                  const uint32_t vlen, void *cookie), void *c, int *buflen) {
     char *ret;
 
     pthread_mutex_lock(&amp;slabs_lock);
-    ret = do_slabs_stats(add_stats, buflen);
+    ret = do_slabs_stats(add_stats, c, buflen);
     pthread_mutex_unlock(&amp;slabs_lock);
     return ret;
 }</diff>
      <filename>thread.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>df5d1bf9d87428d3e777782d9b676baf37667b53</id>
    </parent>
  </parents>
  <author>
    <name>Toru Maesaka</name>
    <email>dev@torum.net</email>
  </author>
  <url>http://github.com/tmaesaka/memcached/commit/86159eb7b5c611d25a33eb1cb6c750c806350912</url>
  <id>86159eb7b5c611d25a33eb1cb6c750c806350912</id>
  <committed-date>2008-10-19T05:33:25-07:00</committed-date>
  <authored-date>2008-10-19T05:33:25-07:00</authored-date>
  <message>Fix for stats opaque issue pointed out at the hackathon and removed some wasteful function calls (more to come).</message>
  <tree>0999112a62230d18393587b633fd251543ac09c5</tree>
  <committer>
    <name>Toru Maesaka</name>
    <email>dev@torum.net</email>
  </committer>
</commit>
