バージョン依存性を解決するための fml ブートローダ
&fmldevel; にはインストールされている fml のバージョン依存性を考慮するた
めに、本章で述べるようなブートストラップの過程があります。
fml (libexec/distribute) が boot していく様子
functions class
----------------------------------------
main::Bootstrap() libexec/loader
|
V
main::Bootstrap2() FML::Process::Switch
|
V
ProcessSwitch() FML::Process::Switch
|
|
| switch to ($obj = FML::Process:Distribute)
|
V
ProcessStart($obj,$args) FML::Process::Flow
例: 配送の場合
loader から次々と呼ばれていく様子は、例えば配送処理の場合、次のよう
になります。
libexec/loader は /usr/local/etc/fml/main.cf を読みこみ、
fml_version 変数から使うべきライブラリのバージョンを決めます。
例えば fml_vesrion が current-20010501 となっていたら
/usr/local/lib/fml/current-20010501/ 以下にあるライブラリを使うといった
具合です。
@INC を設定した後、
loader は FML::Process::Switch をロードし、
$0 を調べます。
その名前から自分の仕事は配送処理だと知ります。
配送処理なので
FML::Process::Distribute クラスをロードし、配送処理に移ります。
なお、プログラム名とクラスの対応関係は
etc/fml/defaults/バージョン/modules
で定義されています。
こういった処理は見かけ上
FML::Process::Flow::ProcessStart() という関数が制御しています。
ProcessStart() が引数として
FML::Process::Distribute を渡され、
FML::Process::Distribute を実行していくという流れになります。
FML::Process:: クラスの階層構造
FML::Process::Distribute >-|
FML::Process::Command >-|-- FML::Process::Kernel
FML::Process::Mead >-| |
|-use-a FML::Parse
|-use-a FML::Config
|-use-a FML::Log
|-use-a ... その他 ...
プロセス実行時に使われるモジュール群
libexec/loader (wrapper)
Bootstrap() を実行する。
fml.pl などはこの loader へのシンボリックリンクです。
/usr/local/libexec/fml/ を参照して下さい。
/usr/local/etc/fml/main.cf を読み込む。
読み込むと fml のバージョンが分かる。
main.cf の値から @INC を再設定しバージョン依存性を解決します。
default_config.cf はバージョン依存であるので、
ここでまずバージョンを評価しなければいけないことに注意してください。
@ARGV を評価し、
どのMLの config.cf 群をロードすればいいのかを準備します。
次に
FML::Process::Switch
(バージョン依存)クラスを
ロードします。
Bootstrap2() および ProcessSwitch() を実行し、
配送用、コマンドモード用などの各
プログラム/プロセスなどへ制御を移します(分岐する)。
この時は $0 から自分の名前を知り、
どのプロセスへ分岐すればいいのかを判断しています。
(ポリモーフィズムの例)
モジュールをダイナミックバインディングし、
該当するプロセスオブジェクトを生成する。
そして、プロセスをスタートさせます。
FML::Process::Flow の中に、
どのように fml プロセスを実行するかが
定義されています。大雑把には
$process = new FML::Process::なにか;
$process->prepare($args);
$process->verify_request($args);
$process->run($args);
$process->finish($args);
のように実行されています。
各プロセスは、それぞれについて適当なメソッドを
FML::Process:: 以下に用意する必要があります。
議論: ml_name と ml_domain の値はどこで解決するのが正しいか?
現在では、FML::Process:: の prepare() あたりで解決しています。
以下、2、3の走り書き/おぼえがきを残しておきます。
main::Bootstrap()
main.cf から fml のバージョン依存性を解く
hints を渡す (CGI のみ)
◎ CGI だけ
嘘の入力がありうる
そのため、loader に hints として
ml_domain や ml_name がハードコードされている。
main::Bootstrap2()
ProcessSwitch()
使うモジュール( Process::なんか )を決める
読み込むべき cf ファイルの決定(なんで?)
ライブラリパスの決定や @INC の修正など
hints を渡す?使う? (CGI のみ?)
ProcessStart($obj,$args)
処理本体のスタート
new
prepare
ml_name と ml_domain の決定
CGI からの入力を解析する
hints を使う?(CGI のみ?)
読み込むべき cf ファイルの決定
parse
メールを読み込む
コマンドラインを解析する