前回です。
前回読んでいなかった重要なメソッドに ap_mrb_set_mrb_state
があった。
定義:
static void ap_mrb_set_mrb_state(apr_pool_t *pool, mrb_state *mrb) { TRACER; apr_pool_userdata_set(mrb, "mod_mruby_state", cleanup_mrb_state, pool); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "%s DEBUG %s: set mrb_state to mod_mruby_state", MODULE_NAME, __func__); }
apr_pool_userdata_set
というのが apr_pool_t に、特定のキーを指定して任意のデータを紐づける関数。
そうするとpconfというのが鍵だが、まずserver_recってのがここから確認できて
メンバのprocessっていうのが*process_recで
実は二つプールがあって使い分けできて
apr_pool_t* process_rec::pconf Configuration pool. Cleared upon restart apr_pool_t* process_rec::pool Global pool. Cleared upon normal exit
とのこと。restartとnormal exitってなにがちがうんだ...
pconfはワーカが入れ替わったら消えるけど、poolはワーカの根っこに紐づくから全体の停止がない限り消えない?
ひとまず ap_mrb_set_mrb_state
はわかった。 ap_mrb_get_mrb_state
も同じようなコードだと想像できる。
ようやく mod_mruby_cmds
を読むと、
static const command_rec mod_mruby_cmds[] = { AP_INIT_FLAG("mrubyHandlerEnable", set_mod_mruby_handler_enable, NULL, RSRC_CONF | ACCESS_CONF, "can use addhandler or sethandler for mruby-script. (default Off)"), AP_INIT_TAKE1("mrubyHandlerCode", set_mod_mruby_handler_inline, NULL, RSRC_CONF | ACCESS_CONF, "hook inline code for handler phase."), MOD_MRUBY_SET_ALL_CMDS_INLINE(handler, Handler), MOD_MRUBY_SET_ALL_CMDS_INLINE(post_read_request, PostReadRequest), //... AP_INIT_TAKE12("mrubyHandler", set_mod_mruby_handler, NULL, RSRC_CONF | ACCESS_CONF, "hook for handler phase."), MOD_MRUBY_SET_ALL_CMDS(handler, Handler), MOD_MRUBY_SET_ALL_CMDS(post_config, PostConfig), MOD_MRUBY_SET_ALL_CMDS(child_init, ChildInit), //... AP_INIT_TAKE12("mrubyOutputFilter", set_mod_mruby_output_filter, NULL, RSRC_CONF | ACCESS_CONF, "set mruby output filter script."), {NULL}};
command_rec
型の配列(これは struct command__struct
のエイリアス)であるとわかる。見た目の通り明らかにディレクティブを定義している。
command_rec
型のレコードを作るためにいくつかマクロがあるとわかる。
まず AP_INIT_*
のほうはApacheで提供しているマクロで、
ここに一通り載っている。つかっているものは:
AP_INIT_FLAG
mechanism for declaring a directive which takes a flag (on/off) argumentAP_INIT_TAKE1
mechanism for declaring a directive which takes 1 argumentAP_INIT_TAKE12
mechanism for declaring a directive which takes 1 or 2 arguments
ここでmod_mrubyを触ったことがある方なら、TAKE1の方はインライン、TAKE12のほうはファイル指定で、optionalな2つ目のフラグをキャッシュの有効無効に使っている、というルールが読み取れると思う。
AP_INIT_TAKE1の引数の意味と取りうる型について説明する。
"mrubyHandlerCode"
これはディレクティブの名前。set_mod_mruby_handler_inline
ディレクティブがセットされた時に動く関数。- この関数はマクロでまとめて定義されているので注意なのだが
- mod_mruby.c#L271-L283
static const char *set_mod_mruby_##hook##_inline(cmd_parms * cmd, void *mconfig, const char *arg)
- らしい、 char* を返すの?(実装ではNULL返してる)。
- char* はエラーメッセージを返すのか
- mconfigは下を参照。
cmd_parms *
からserver_rec、module_configが辿れる- mruby_config_t にそれぞれのインラインフックのコードが格納されているので、そこに格納しつつ、
- ap_mrb_set_stringはmod_mruby_code_t *をアロケートして生成している
- mod_mruby_compile_code はコンパイルだけをして、mod_mruby_code_tにコンパイルしたバイトコード(コンテクスト)を渡している(
c->proc
)。
- らしい、 char* を返すの?(実装ではNULL返してる)。
const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); \ mruby_config_t *conf = (mruby_config_t *)ap_get_module_config(cmd->server->module_config, &mruby_module); \ if (err != NULL) \ return err; \ conf->mod_mruby_##hook##_inline_code = ap_mrb_set_string(cmd->pool, arg); \ mod_mruby_compile_code(ap_mrb_get_mrb_state(cmd->server->process->pconf), conf->mod_mruby_##hook##_inline_code, \ cmd->server); \ return NULL;
- NULL 三番目の引数
mconfig
は使っていない。これは複数回呼び出すようなディレクティブで状態を持ち回す時に使うそう RSRC_CONF | ACCESS_CONF
- これはどのコンテクストで使える設定かというフラグで、ここに詳しい
- Developing modules for the Apache HTTP Server 2.4
"hook inline code for handler phase."
これはヘルプメッセージ。
なおインラインじゃない方の定義:
#define SET_MOD_MRUBY_DIR_CMDS(hook) \ static const char *set_mod_mruby_##hook(cmd_parms *cmd, void *mconfig, const char *path, const char *cache_opt); \ static const char *set_mod_mruby_##hook(cmd_parms *cmd, void *mconfig, const char *path, const char *cache_opt) \ { \ const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); \ mruby_dir_config_t *dir_conf = (mruby_dir_config_t *)mconfig; \ TRACER; \ if (err != NULL) \ return err; \ dir_conf->mod_mruby_##hook##_code = ap_mrb_set_file(cmd->pool, path, cache_opt, "" #hook ""); \ mod_mruby_compile_code(ap_mrb_get_mrb_state(cmd->server->process->pconf), dir_conf->mod_mruby_##hook##_code, \ cmd->server); \ return NULL; \ }
は、ap_mrb_set_file
が大きな違いで、mod_mruby_code_tのCacheフラグを一緒に操作している。 TAKE12
だと関数の側の引数の数が増えているのも注目する。
で、もう一つのマクロ MOD_MRUBY_SET_ALL_CMDS(_INLINE)
は以下の定義:
#define MOD_MRUBY_SET_ALL_CMDS_INLINE(hook, dir_name) \ AP_INIT_TAKE1("mruby" #dir_name "FirstCode", set_mod_mruby_##hook##_first_inline, NULL, RSRC_CONF | ACCESS_CONF, \ "hook inline code for " #hook " first phase."), \ AP_INIT_TAKE1("mruby" #dir_name "MiddleCode", set_mod_mruby_##hook##_middle_inline, NULL, \ RSRC_CONF | ACCESS_CONF, "hook inline code for " #hook " middle phase."), \ AP_INIT_TAKE1("mruby" #dir_name "LastCode", set_mod_mruby_##hook##_last_inline, NULL, RSRC_CONF | ACCESS_CONF, \ "hook inline code for " #hook " last phase.")
フックポイントによりFirst, Middle, Lastそれぞれでフックがあるので3つまとめて定義しているということ。
これにより
を実現している。
結構長くなったw
いまだに register_hooks
に到達しておらず、登録できないので次はそこへ。