バージョン依存性を解決するための 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 メールを読み込む コマンドラインを解析する