現在trunkにあるTokyoCabinetのdbaハンドラをPHP5.3で使ってみる
dba関数というのを知っていますか?dbm形式のデータベースの抽象化レイヤとなる関数を提供するモジュールで、PHPのソースコードに同梱されています。
例えば、dbm や qdbm といったものを利用できる他、inifile という php.ini 形式のようなファイルをDBMのように読み書きできるハンドラが用意されています。
で、現在、PHPのソースコードのtrunkには、TokyoCabinetのハンドラがコミットされています。
- php/php-src/trunk/ext/dba/dba_tcadb.c (実装本体)
- php/php-src/trunk/ext/dba/php_tcadb.h (ヘッダ)
- php/php-src/trunk/ext/dba/config.m4
いつ、これが提供されるようになるかは不明ですが、現時点でもbackportすれば利用はできるので、使ってみました。手元ではPHP5.2.8、5.3.1で確認しています。
パッチを適用
TokyoCabinet用のドライバである php_tcadb.h と tcadb.c をそのままコピーと、dba.c と config.m4 のTokyoCabinetに関する部分の追加分をパッチで適用します。
ほとんどファイル追加なので長ったらしいパッチは以下。
PHP5.3のソースコードの、ext/dba ディレクトリで patch -p0 -d . < PATCH_FILE してください。
$ patch -p0 -d . < ../php53-dba-tcadb.patch patching file config.m4 patching file dba.c patching file dba_tcadb.c patching file php_tcadb.h
1点修正を加えてます
うまく動かなかったので、TokyoCabinetのマニュアルを見ながらオープン周りを確認してみたところ、
http://1978th.net/tokyocabinet/spex-ja.html
bool tcadbopen(TCADB *adb, const char *name);
.. snip ..
If successful, the return value is true, else, it is false.
とあるのに、オープン処理で if (tcadbopen(...)) { return FAILURE; } になっていたので、失敗したときに成功とみなし操作できない、成功したときにオープン失敗とエラーが出るという状態になっていたので、上のパッチではその箇所も修正しています。
--- dba_tcadb.c 2010-01-17 14:10:39.000000000 +0900 +++ dba_tcadb.c.new 2010-01-17 16:50:04.000000000 +0900 @@ -65,7 +65,7 @@ return FAILURE; } - if (tcadbopen(tcadb, path_string)) { + if (!tcadbopen(tcadb, path_string)) { efree(path_string); return FAILURE; }
さすがに初っ端で動かないので、この状態でコミットされているのが謎ですが、他にも問題あるかもしれません。
ビルド
PHP本体はすでにビルドされていて、dbaモジュールは組み込んでない場合として、動的モジュールとしてビルドしてみます。
当然ながら、tokyocabinetがインストールされている必要があります。Ubuntuで試したので sudo apt-get install libtokyocabinet-dev で導入しました。
まずはphpize
$ phpize Configuring for: PHP Api Version: 20041225 Zend Module Api No: 20060613 Zend Extension Api No: 220060519
configureで、--with-tcadb。必要に応じて、パスを指定します。
$ ./configure --with-tcadb
そして、make
$ make
成功すると、modules/下に dba.so ができるので、extension_dir の下に配置して、php.iniに、
extension=dba.so
と設定して、読み込ませます。
動作させてみる
こんな感じですね。
<?php sleep(1); $id = dba_open("test.tch", "n", "tcadb"); if (!$id) { echo "dba_open failed\n"; exit; } dba_replace("key", "This is an example!", $id); if (dba_exists("key", $id)) { echo dba_fetch("key", $id); dba_delete("key", $id); } dba_close($id); ?>