ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

mod_mruby を読む。その1

諸事情で(早くこの諸事情を公表できるようにがんばる系)、Apacheの拡張の書き方や mod_mruby の設計思想、実装について知りたくなった。

ちまちまと読んでいく。もともと社内のNotionに雑にメモしていこうと思ったが、フィードバックも欲しいので晒していく。またこのブログにシリーズものが増えたのですあった...。


まずモジュールの定義全体。

https://github.com/matsumotory/mod_mruby/blob/master/src/mod_mruby.c#L918-L928

#ifdef __APACHE24__
AP_DECLARE_MODULE(mruby) = {
#else
module AP_MODULE_DECLARE_DATA mruby_module = {
#endif
    STANDARD20_MODULE_STUFF, mod_mruby_create_dir_config, /* dir config creater */
    NULL,                                                 /* dir merger */
    mod_mruby_create_config,                              /* server config */
    NULL,                                                 /* merge server config */
    mod_mruby_cmds,                                       /* command apr_table_t */
    register_hooks                                        /* register hooks */
};

ちなみにこれが何を意味するかはここに詳しい。

httpd.apache.org

抜粋すると

module AP_MODULE_DECLARE_DATA   example_module =
{ 
    STANDARD20_MODULE_STUFF,
    create_dir_conf, /* Per-directory configuration handler */
    merge_dir_conf,  /* Merge handler for per-directory configurations */
    create_svr_conf, /* Per-server configuration handler */
    merge_svr_conf,  /* Merge handler for per-server configurations */
    directives,      /* Any directives we may have for httpd */
    register_hooks   /* Our hook registering function */
};

ディレクトリ単位の設定、サーバ単位の設定などがあるらしい。コメントはわかるようなわからないようなだが、読み進めていけばわかりそう。

merge_* が何をどうマージするのかピンとこなかったが、mod_mrubyでは利用していなそうなので一旦次へ...。

で、mod_mruby_create_dir_config, mod_mruby_create_config, は mruby_*conf_t を生成して返す。

ここに並んでいるフックポイントが実質apacheに存在する全てのフックポイントだと思われる。

  mruby_dir_config_t *dir_conf = (mruby_dir_config_t *)apr_pcalloc(p, sizeof(*dir_conf));
// inline core in httpd.conf
  dir_conf->mod_mruby_handler_inline_code = NULL;
  dir_conf->mod_mruby_handler_first_inline_code = NULL;
  dir_conf->mod_mruby_handler_middle_inline_code = NULL;
  dir_conf->mod_mruby_handler_last_inline_code = NULL;
  dir_conf->mod_mruby_post_read_request_first_inline_code = NULL;
  dir_conf->mod_mruby_post_read_request_middle_inline_code = NULL;
  dir_conf->mod_mruby_post_read_request_last_inline_code = NULL;
  dir_conf->mod_mruby_translate_name_first_inline_code = NULL;
  dir_conf->mod_mruby_translate_name_middle_inline_code = NULL;
  dir_conf->mod_mruby_translate_name_last_inline_code = NULL;
  dir_conf->mod_mruby_map_to_storage_first_inline_code = NULL;
  dir_conf->mod_mruby_map_to_storage_middle_inline_code = NULL;
  dir_conf->mod_mruby_map_to_storage_last_inline_code = NULL;

とか

  mruby_config_t *conf = (mruby_config_t *)apr_pcalloc(p, sizeof(mruby_config_t));
  conf->mod_mruby_child_init_first_code = NULL;
  conf->mod_mruby_child_init_middle_code = NULL;
  conf->mod_mruby_child_init_last_code = NULL;
  conf->mod_mruby_post_config_first_code = NULL;
  conf->mod_mruby_post_config_middle_code = NULL;
  conf->mod_mruby_post_config_last_code = NULL;
  conf->mod_mruby_quick_handler_first_code = NULL;
  conf->mod_mruby_quick_handler_middle_code = NULL;
  conf->mod_mruby_quick_handler_last_code = NULL;
  conf->mod_mruby_insert_filter_first_code = NULL;
  conf->mod_mruby_insert_filter_middle_code = NULL;
  conf->mod_mruby_insert_filter_last_code = NULL;

ちなみにdir_configの方では構造体をアロケートするしかできないが、configの方はサーバ単位の設定なのでサーバ構造体 server_rec *server に触れられる。ということでmrb_stateを初めて作成しているのはmod_mruby_create_configのタイミングである。

  mrb_state *mrb = ap_mrb_create_mrb_state();
  ap_mrb_set_mrb_state(server->process->pconf, mrb);

server->process->pconf というところから後続のコードでも取り出している。

ap_mrb_create_mrb_state のコードはmrubyコアで見かけるようなこういうやつで、

static mrb_state *ap_mrb_create_mrb_state()
{
  TRACER;
  mrb_state *mrb = mrb_open();
  ap_mruby_class_init(mrb);
  return mrb;
}

ap_mruby_class_init からそのほかの ap_mruby_*_init を読んでmod_mruby固有のクラスなどを定義している。

https://github.com/matsumotory/mod_mruby/blob/e4d61c3530d23a5ba149afe989cffc466753b3df/src/ap_mrb_init.c

こんな感じでふわっとやってく。


次は(あるのかな?)

  • mod_mruby_cmds
  • register_hooks

がやっていることを眺める。