いきなりgroongaってなんぞやって感じですが、ElasticSearchみたいなもんです。ライブラリがCなのでCから高速に使いたいときはこっちを使うと楽です。日本人が開発してるので日本語完全対応もうれしい。もうちょっとドキュメント整理してほしいけど、、、
http://groonga.org/ja/docs/index.html
(ちょっとおまけ)static ライブラリを作りたい
staticライブラリを作りたい時もありますよね?ありますよね?(白目
groongaはcmakeで楽ちんに作れますが、--help-property-listで出力してもstaticライブラリを作れそうなプロパティが出てきません。configureしてもいいけどどうしてもcmakeでやりたい。。。大丈夫。GRNG_EMBED=onとしてビルドすればできます。
まずはソースコードをダウンロードします。
git clone --recursive git@github.com:groonga/groonga.git
オプション付きでビルドします
cmake . -DGRNG_EMBED=on
libの下にlibgroonga.aができます。
ちなみにこれで作ったlibgroonga.aをリンクする際は一緒につくられるonigmoライブラリへのリンクもいっしょに追加しないといけません(onigmoを使わない場合は不要です)
例)
gcc -o sample main.c -L(groonga root)/lib -L(groonga root)/vendor/onigmo -lgroonga -ldl -lstdc++ -lonigmo -lz -lm
libstdc++, libmはbuild-essentialをインストールしたらだいたい一緒に入ると思うがlibdl, libzはlibltdl, zlib1gをインストールしないとだめみたい。
マルチスレッドで使う
よーやく本題。
groongaはマルチスレッド対応で特になにか設定をする必要はないようなことを書いてあるが、よーく読むとgrn_ctxは各スレッドに対して一つ与えてやらないといけないらしい。
ためしにinsert/deleteをマルチスレッドでやるサンプルを書いてみます。
#include <stdlib.h> #include <stdio.h> #include <groonga.h> #include <pthread.h> #define DATA(str, key) sprintf(str, "[{¥"_key¥":¥"%d¥",¥"value¥":¥"value¥"}]", key); grn_ctx ctx_insert; grn_ctx ctx_delete; grn_obj* open(grn_ctx* ctx, const char* path) { grn_obj* db; int i = 0; //grn_ctxオブジェクトの初期化 ctx = grn_ctx_open(0); grn_ctx_init(ctx, 0); //DBが存在しない場合は作成する。ある場合は開いてctxと関連付ける GRN_DB_OPEN_OR_CREATE(ctx, path, 0, db); //JSONで出力させる grn_ctx_set_output_type(ctx, GRN_CONTENT_JSON); return db; } int close(grn_ctx* ctx, grn_obj* db) { grn_obj_close(ctx, db); return grn_ctx_fin(ctx); } int insert_record(grn_ctx* ctx, char* data) { //レコードを追加する処理 } int delete_record(grn_ctx* ctx, char* key) { //レコードを冊書する処理 } void *insert(void* arg) { int i = 0; char str[128]; for(i = 0; i < 100; i++) { DATA(str, i); insert_record(&ctx_insert, str); } } void *delete(void* arg) { usleep(100); int i = 0; char index[2]; for(i = 0; i < 100; i++) { sprintf(index, "%2d", i); delete_record(&ctx_delete, index); } } int main(void) { grn_init(); grn_obj* db_insert = open(&ctx_insert, "db"); //おなじDBなので同じオブジェクトを使い回せば良いのではと思ったが今のところうまく行ってないので grn_obj* db_delete = open(&ctx_delete, "db"); //pthreadでスレッドを作り、joinさせて動かす pthread_t delete_th, insert_th; pthread_create(&insert_th, NULL, insert, NULL); pthread_create(&delete_th, NULL, delete, NULL); pthread_join(insert_th, NULL); pthread_join(delete_th, NULL); close(&ctx_insert, db_insert); close(&ctx_delete, db_delete); //一回で良い grn_fin(); return 0; }
割りと省略しまくりですが、大事なのはgrn_ctx, grn_dbをそれぞれのスレッドに対して作ること。