Groongaプラグイン自作入門 - 2015-12-10 - ククログ

ククログ

株式会社クリアコード > ククログ > Groongaプラグイン自作入門

Groongaプラグイン自作入門

Groonga Advent Calendar 2015の10日目の記事です。

全文検索エンジンGroongaにはプラグイン機構があり、本体に手を加えずに独自の機能を追加することができます1

この記事では、主にプラグインを作ったことがない人向けに、プラグインの概要と作り方について説明します。また、プラグインの雛形を作成するツールの紹介もあるので、その部分はプラグインを作ったことがある人にとっても有用かもしれません。

プラグインでできること

GroongaはC言語のライブラリーとして使うためのAPIを提供していて、プラグインからもAPIを使うことができます。主な機能はAPI経由で使うことができるため、プラグインでも多くのことが可能です。

APIでどんなことができるかは、リファレンスマニュアルヘッダーファイルで調べることができます。

使いたい機能がAPIとして公開されていない場合、メーリングリストなどで相談すれば公開してもらえるかもしれません。

プラグインの使い方

プラグインの使い方を簡単に説明します。プラグインを使うには以下の手順が必要です。

  • インストール

  • 登録

インストール

Groonga本体に付属している場合は不要ですが、本体とは別のパッケージになっていたり、サードバーティのものについてはインストールが必要です。パッケージが提供されているものはAPTやYumなどでインストールできますが、パッケージが提供されていないものについてはソースコードをビルドしてインストールする必要があります。

登録

プラグインの機能を使う前に、登録する必要があります。登録はplugin_registerコマンド(Groonga 5.0.0まではregisterコマンド)で実行します。詳細はリファレンスマニュアルをご覧ください。

プラグインの形式

プラグインはいろいろな形式で作成することができます。例えば、コマンドや関数、トークナイザー、ノーマライザーなどです。詳細はリファレンスマニュアルのそれぞれの章をご覧ください。

プラグインを作り始める場合、最初はコマンドから始めるのがわかりやすいと思います。

プラグインの例

プラグインには、Groonga本体に同梱されているものと、Groongaプロジェクトやサードパーティが別パッケージとして提供しているものがあります。

本体に同梱

Groonga本体に同梱されているものについては、こちらでソースコードを見ることができます2

別パッケージ

Groonga本体に同梱されていないプラグインには以下のようなものがあります。

プラグインの作り方

ここから、実際にプラグインを作成しながら説明します。サンプルとして、「hi」と出力するだけのコマンドを作成してみます。

一から作成するのは大変なので、雛形作成ツールを作成しました。まだ実験的なツールなので、今後、機能や名前が変わるかもしれません。

RubyGems.orgで公開しているので、以下のコマンドでインストールできます。

gem install grnplum

雛形の作成

以下のコマンドで雛形を作成できます。プラグイン名はgreetにします。

$ grnplum new greet

実行すると、以下のファイルが生成されます。

$ grnplum new greet
      create  groonga-plugin-greet/.gitignore
      create  groonga-plugin-greet/LICENSE
      create  groonga-plugin-greet/Makefile.am
      create  groonga-plugin-greet/README.md
      create  groonga-plugin-greet/autogen.sh
      create  groonga-plugin-greet/configure.ac
      create  groonga-plugin-greet/greet/Makefile.am
      create  groonga-plugin-greet/greet/greet.c
      create  groonga-plugin-greet/greet/sources.am
      create  groonga-plugin-greet/test/Makefile.am
      create  groonga-plugin-greet/test/run-test.sh
      create  groonga-plugin-greet/test/suite/register.expected
      create  groonga-plugin-greet/test/suite/register.test

ビルド

以下の手順でビルドしてテストを実行できます。詳細は上記で生成されたREADME.mdにも書かれています。--prefixにはGroogaのインストール先を指定してください。

$ cd groonga-plugin-greet
$ ./autogen.sh
$ ./configure --prefix=/tmp/local
$ make
$ test/run-test.sh

コードの修正&実行

ビルド用のファイルが多いですが、プラグインの本体はgreet/greet.cになります。簡単に解説します。

#include <groonga/plugin.h>

プラグイン向けのヘッダーファイルを読み込んでいます。ライブラリー用のAPIに加えて、プラグイン用の関数も使えるようになります。

static grn_obj *
command_greet(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
  grn_ctx_output_bool(ctx, GRN_FALSE);
  return NULL;
}

コマンドの本体です。実装時はこの部分を修正していきます。

grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
  return GRN_SUCCESS;
}

プラグインの初期化処理です。何か初期化処理が必要な場合はここに追記します。

grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
  grn_expr_var vars[0];

  grn_plugin_command_create(ctx, "greet", -1, command_greet, 0, vars);

  return ctx->rc;
}

ここで、command_greet関数をgreetコマンドに登録しています。

grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
  return GRN_SUCCESS;
}

プラグインの終了処理です。何か後始末が必要な場合はここに追記します。

では、コマンド本体を以下のように修正します。

static grn_obj *
command_greet(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
{
  grn_ctx_output_cstr(ctx, "hi");
  return NULL;
}

grn_ctx_output_cstr()で、文字列を出力することができます。差分は以下です。

 static grn_obj *
 command_greet(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
 {
-  grn_ctx_output_output(ctx, GRN_FALSE);
+  grn_ctx_output_cstr(ctx, "hi");
   return NULL;
 }

それでは、インストールして実行してみましょう。

$ make
$ make install
$ groonga
> plugin_register greet/greet
[[0,1449653297.6119,0.000138044357299805],true]
> greet
[[0,1449653298.65187,3.62396240234375e-05],"hi"]

上記のように、hiと出力されれば成功です。

なお、make uninstallコマンドでアンインストールできます。

また、テスト方法については、Groongaのプラグインを多数作成されている村上さんGroongaコマンドのテストツールgrntestの使い方 - CreateFieldという記事をまとめてくれているので、そちらも合わせてご覧ください。

まとめ

Groongaのプラグインを作ったことがない人向けに、Groongaのプラグインを「どう」作るのか簡単に説明しました。Groongaの機能拡張に興味がある方は参考にしてみてください。

  1. GroongaのプラグインはC言語やmrubyで作成できます。mrubyで作成する場合、Groongaのビルド時にmrubyを有効にする必要があります。おおまかな作り方は変わりませんが、使うAPIなどは異なってきます。この記事ではC言語で作成する場合について説明します。

  2. ソースコードは本体に同梱されているけどパッケージとしては別になっているものもあります。MeCabなどのライブラリーが別途必要なプラグインはそうなっていることが多いです。