libmemcache を使ってみる

会社でちと memcached を使ってみるかってことになりまして、その C のクライアントの libmemcache を使って簡単に実装をしてみました。

手元のノート PC に入れてる coLinux、Linux debian 2.6.17-co-0.8.0 #1 PREEMPT Sun Jul 8 14:00:12 CEST 2007 i686 GNU/Linux で試しました。

つうわけで、まずは必要なライブラリをインストール。

CODE:
  1. [maihara@debian:~] $ aptitude search libmemcache
  2. p   libmemcache-dev - development headers for libmemcache C client API
  3. p   libmemcache0    - C client API for memcached memory object caching system
  4. [maihara@debian:~] $ sudo aptitude install libmemcache-dev
  5. [maihara@debian:~] $ dpkg -L libmemcache-dev
  6. /.
  7. /usr
  8. /usr/lib
  9. /usr/lib/libmemcache.a
  10. /usr/lib/libmemcache.la
  11. /usr/include
  12. /usr/include/memcache.h
  13. /usr/include/memcache
  14. /usr/include/memcache/buffer.h
  15. /usr/include/memcache/_buffer.h
  16. /usr/share
  17. /usr/share/doc
  18. /usr/share/doc/libmemcache-dev
  19. /usr/share/doc/libmemcache-dev/changelog.Debian.gz
  20. /usr/share/doc/libmemcache-dev/copyright
  21. /usr/share/doc/libmemcache-dev/changelog.gz
  22. /usr/lib/libmemcache.so

で、こんな感じのソース、mcclient.cc を書いてみました。

C++:
  1. #include <iostream>
  2. #include <string>
  3. #include <map>
  4.  
  5. #include <memcache.h>
  6.  
  7. using namespace std;
  8.  
  9. class memcacheWrapper {
  10. public:
  11.     memcacheWrapper() {
  12.         _mc = mc_new();
  13.     }
  14.  
  15.     ~memcacheWrapper() {
  16.         mc_free(_mc);
  17.     }
  18.  
  19.     struct memcache* _mc;
  20. };
  21.  
  22. class memcacheReqWrapper {
  23. public:
  24.     memcacheReqWrapper() {
  25.         _mcr = mc_req_new();
  26.     }
  27.  
  28.     ~memcacheReqWrapper() {
  29.         mc_req_free(_mcr);
  30.     }
  31.  
  32.     struct memcache_req* _mcr;
  33. };
  34.  
  35. int main(int argc, char* argv[]) {
  36.     // 初期化
  37.     memcacheWrapper mr;
  38.     int ret = mc_server_add4(mr._mc, "127.0.0.1:11211");
  39.     if (ret != MCM_ERR_NONE) {
  40.         cerr <<"mc_server_add4 failed" <<endl;
  41.         exit(1);
  42.     }
  43.     ret = mc_server_add4(mr._mc, "127.0.0.1:11212");
  44.     if (ret != MCM_ERR_NONE) {
  45.         cerr <<"mc_server_add4 failed" <<endl;
  46.         exit(1);
  47.     }
  48.  
  49.     // 適当に値追加
  50.     map<string, string> m;
  51.     string k1 = "0123";
  52.     string v1 = "forever";
  53.     string k2 = "4567";
  54.     string v2= "5years";
  55.     string k3 = "89ab";
  56.     string v3= "old";
  57.     string k4 = "cdef";
  58.     string v4= "net";
  59.     m.insert(make_pair(k1, v1));
  60.     m.insert(make_pair(k2, v2));
  61.     m.insert(make_pair(k3, v3));
  62.     m.insert(make_pair(k4, v4));
  63.     for (map<string, string>::const_iterator cit = m.begin();
  64.          cit != m.end();
  65.          ++cit) {
  66.         ret = mc_set(mr._mc,
  67.                      const_cast<char*>(cit->first.c_str()),
  68.                      k1.length(),
  69.                      const_cast<char*>(cit->second.c_str()),
  70.                      v1.length(),
  71.                      6000,
  72.                      MCM_RES_FREE_ON_DELETE);
  73.         if (ret != MCM_ERR_NONE) {
  74.             cerr <<"mc_set failed: " <<cit->first <<" : " <<cit->second <<endl;
  75.             exit(1);
  76.         }
  77.     }
  78.  
  79.     // 値を取得してみる
  80.     memcacheReqWrapper mrw;
  81.     memcache_res* res1 = mc_req_add(mrw._mcr, const_cast<char*>(k1.c_str()), k2.length());
  82.     memcache_res* res2 = mc_req_add(mrw._mcr, const_cast<char*>(k2.c_str()), k2.length());
  83.     memcache_res* res3 = mc_req_add(mrw._mcr, const_cast<char*>(k3.c_str()), k3.length());
  84.     memcache_res* res4 = mc_req_add(mrw._mcr, const_cast<char*>(k4.c_str()), k4.length());
  85.     mc_get(mr._mc, mrw._mcr);
  86.     cerr <<res1->key <<" : " <<static_cast<char*>(res1->val) <<endl;
  87.     cerr <<res2->key <<" : " <<static_cast<char*>(res2->val) <<endl;
  88.     cerr <<res3->key <<" : " <<static_cast<char*>(res3->val) <<endl;
  89.     cerr <<res4->key <<" : " <<static_cast<char*>(res4->val) <<endl;
  90.  
  91.     // 統計情報を取得する
  92.     struct memcache_server_stats* s = mc_stats(mr._mc);
  93.     cerr <<s->get_hits <<endl;
  94.     cerr <<s->total_items <<endl;
  95.     mc_server_stats_free(s);
  96.  
  97.     return 0;
  98. }

で、コンパイルして実行してみますと、

CODE:
  1. [maihara@debian:~/work] $ g++ -lmemcache -o mcclient mcclient.cc
  2. [maihara@debian:~/work] $ ./mcclient
  3. [NOTICE@1186032723.409892] mcm_server_connect():2302: Software caused connection abort
  4. [NOTICE@1186032723.410127] mcm_server_connect_next_avail():2333: Software caused connection abort
  5. [WARN@1186032723.410197] mcm_server_connect_next_avail():2338
  6. mc_add failed

ハイ。memcached 自体を上げてないので当たり前。インストールしてデーモン上げます。

CODE:
  1. [maihara@debian:~/work] $ aptitude search memcached
  2. [maihara@debian:~/work] $ sudo aptitude install memcached
  3. [maihara@debian:~/work] $ sudo /etc/init.d/memcached stop
  4. [maihara@debian:~/work] $ sudo /usr/bin/memcached -m 64 -p 11211 -u root &
  5. [maihara@debian:~/work] $ sudo /usr/bin/memcached -m 64 -p 11212 -u root &
  6. [maihara@debian:~/work] $ ps alwwx | grep memcached
  7. 4     0  5130  4686  21   5   5924  4736 epoll_ SN   pts/0      0:00 /usr/bin/memcached -m 64 -p 11211 -u root
  8. 4     0  5131  4686  22   5   5920  4736 epoll_ SN   pts/0      0:00 /usr/bin/memcached -m 64 -p 11212 -u root
  9. 0  1000  5133  4686  15   0   2784   752 pipe_w S+   pts/0      0:00 grep memcached

で、mcclient 再実行。

CODE:
  1. [maihara@debian:~/work] $ ./mcclient                                                                                                             [1556   9:52午後]
  2. 0123 : forever
  3. 4567 : 5years
  4. 89ab : old
  5. cdef : net
  6. 4
  7. 4

下の 2 行は統計情報の出力です。set して get するだけですが、とりあえず動きました。

で、ここまでは良かったんですが、set し続けるプログラムを作って走らせている間に、memcached を 1 つ kill したりすると、

CODE:
  1. [ERROR@1186044634.069779] mcm_buf_read():361: read(2) failed: Operation now in progress: server unexpectedly closed connection

つって怒られて exit しちゃう現象に遭遇。Python extension for libmemcache の Known Bugs と同じですわ。アガガ。

というわけで、パッチ作ったるワイと今日 1 日を潰すことになるのですが、それはこの続き、「libmemcache のパッチを作ってみる」に書きます。

フー。久しぶりにプログラムの話がでけました。


About this entry