tdb(Trivial Database) は、dbm の一種で、key/value の形でデータを保存できる。 install の仕方は、以下のとおり
以下から download する http://sourceforge.net/projects/tdb/ $ wget "http://downloads.sourceforge.net/project/tdb/tdb/1.0.6/tdb-1.0.6.tar.gz?use_mirror=jaist&ts=1279553081" $ tar zxvf tdb-1.0.6.tar.gz $ cd tdb-1.0.6 $ ./configure --prefix=$HOME/local --host="i860-linux-gnu" --enable-shared $ perl -pi -e 's/$/\\n\\/ if( $.>=172 && $.<=187)' tdbtool.c $ perl -pi -e 's/#define u32 unsigned/#define u32 unsigned long long/' tdb.h $ make $ make install
tdb は、ファイル1つに対しデータベースを作っており、offset と size でデータを取り出したり、 保存したりしている。 offset の指定が unsigned int になっているので、4GB を超えるあたりで、動かなくなる問題があったので、 改善方法を考えてみた。
offset は u32 型で定義しているので、以下のようにmacroを書き換えればよい
$ perl -pi -e 's/#define u32 unsigned/#define u32 unsigned long long/' tdb.h
正常に動くかどうかは、以下のプログラムを動かして確認した。
$ cat tdb_overflow.cc #include#include #include "tdb.h" #include #include using namespace std; #define TDB_DB "tdb.db" #define TDB_HASH_SIZE 2000*10000 void log(TDB_CONTEXT *tdb, int Num, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } void get_tdb_val(TDB_CONTEXT *tdb, int num, TDB_DATA *tkey, TDB_DATA *tvalue){ static string pre_key = ""; static string pre_value = ""; if( "" == pre_key ){ pre_key = "key"; } if( "" == pre_value ){ for(int i=0;i<100*5000;++i){ pre_value += "0123456789"; } } char numStr[1024]; snprintf(numStr, 1024, "%d", num); static string key; key = pre_key + numStr; tkey->dptr = (char *)key.c_str(); tkey->dsize = key.length() + 1; static string value; value = pre_value + numStr; tvalue->dptr = (char *)value.c_str(); tvalue->dsize = value.length() + 1; } int main(){ printf("tdb file:%s\n", TDB_DB); printf("hash size:%u\n", TDB_HASH_SIZE); TDB_CONTEXT *tdb; tdb = tdb_open_ex(TDB_DB, TDB_HASH_SIZE, TDB_CLEAR_IF_FIRST|TDB_NOMMAP, O_RDWR|O_CREAT, S_IRWXU, &log); if(NULL == tdb){ fprintf(stderr, "can't open tdb\n"); return -1; } // set TDB_DATA tkey; TDB_DATA tvalue; for(int i=0;i<1000;++i){ get_tdb_val(tdb, i, &tkey, &tvalue); if(0 != tdb_store(tdb, tkey, tvalue, TDB_INSERT)){ printf("fault. key:%s val:%s\n", tkey.dptr, tvalue.dptr); continue; } printf("success set %d\n", i); } // get for(int i=0;i<1000;++i){ TDB_DATA tret; get_tdb_val(tdb, i, &tkey, &tvalue); tret = tdb_fetch(tdb, tkey); if( strcmp(tvalue.dptr, tret.dptr) ){ printf("fault. key:%s val:%s ret:%s\n", tkey.dptr, tvalue.dptr, tret.dptr); continue; } delete tret.dptr; printf("success. get %d\n", i); } tdb_close(tdb); printf("success end.\n"); }
$ cat Makefile INCDIR=/home/sikaku/local/include LIBDIR=/home/sikaku/local/lib default: all tdb_overflow:tdb_overflow.cc g++ -g -I$(INCDIR) -L$(LIBDIR) -ltdb tdb_overflow.cc -o $@ all:tdb_overflow clean: rm ./tdb_overflow test: LD_LIBRARY_PATH=$(LIBDIR) ./tdb_overflow
5160394752byte の tdb.db が作成されて、正常に終了した。
No comments:
Post a Comment