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 が作成されて、正常に終了した。