memcachedのフルダンププログラムを書いてみる

libmemcachedにはmemdumpというユーティリティが着いて来ますが,mysqldumpのようにキーとバリューが全て取れるものではありません.
そこでlibmemcachedを使って,unixのodコマンドのように,キーとバリューの全ての値と,あとコントロールコードみたいな不可視な値のためにアスキーコードも表示するプログラムを作ってみました.

#include <libmemcached/memcached.h>
#include <stdio.h>
#include <string.h>
char *stored_keys[100];
int stored_keys_index = 0;
static memcached_return_t dumper(memcached_st *memc ,
             const char *key, size_t key_length, void *context )
{
  stored_keys[stored_keys_index] = (char *)malloc(key_length);
  strcpy(stored_keys[stored_keys_index++],key);
  return MEMCACHED_SUCCESS;
}

int main(int argc, char *argv[])
{
  memcached_st *memc;
  memcached_return rc;
  memcached_server_st *servers;
  char *key, *val;
  size_t key_length,val_length;
  uint32_t flags;

  int i;
  memcached_dump_fn callbacks[1];
  callbacks[0]= &dumper;

  memc= memcached_create(NULL);

  servers= memcached_servers_parse(argv[1]);
  memcached_server_push(memc, servers);
  memcached_server_list_free(servers);

  rc= memcached_dump(memc, callbacks, NULL, 1);
  for(i=0;i<stored_keys_index;++i)
  {
    int j;
    printf("------------------ ITEM #=%d\n",i);
    key = stored_keys[i];
    key_length = strlen(stored_keys[i]);
    val = memcached_get(memc, key, key_length,
                        &val_length, &flags, &rc);
    if (rc != MEMCACHED_SUCCESS)
    {
      fprintf(stderr, "memod: %s: memcache error %s",
            key, memcached_strerror(memc, rc));
      if (memc->cached_errno)
        fprintf(stderr, " system error %s", strerror(memc->cached_errno));
      fprintf(stderr, "\n");
    }
    printf("--- KEY\n");
    for(j=0;j<(int)key_length;++j) printf("%3c", key[j]);
    printf("\n");
    for(j=0;j<(int)key_length;++j) printf("%3x", key[j]);
    printf("\n--- VAL\n");

    for(j=0;j<(int)val_length;++j) printf("%3c", val[j]);
    printf("\n");
    for(j=0;j<(int)val_length;++j) printf("%3x", val[j]);
    printf("\n");
  }
  free(val);
  memcached_free(memc);
  return(0);
}

コンパイルと実行は,libmemcachedが/usr/local以下にあるとすると,次のような感じです.

> gcc -o memod memod.c -lmemcached -I/usr/local/include -L/usr/local/lib
# memcached -vv -p 11211 -u nobody  ←違うターミナルで
> telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set qwerty 0 0 5
asdfg
STORED
^]
telnet> close
Connection closed.
> ./memod 127.0.0.1:11211
------------------ ITEM #=0
--- KEY
  q  w  e  r  t  y
 71 77 65 72 74 79
--- VAL
  a  s  d  f  g
 61 73 64 66 67