バージョン依存性を解決するための fml ブートローダ
&fml8; には、
インストールされている 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 から次々とモジュールが呼ばれていく様子は次のようになります。
/usr/local/libexec/fml/distributre
(の実体は /usr/local/libexec/fml/loader)
は
/usr/local/etc/fml/main.cf を読みこみ、
fml_version 変数から使うべきライブラリのバージョンを決めます。
たとえば fml_vesrion が 8.0.0 となっていれば、
/usr/local/lib/fml/8.0.0/
以下にあるライブラリを使うといった具合です。
@INC を再設定した後、
loader は FML::Process::Switch をロードし、
$0 (プロセス名)を調べます。
プロセス名から自分の仕事は配送処理なので、
FML::Process::Distribute クラスをロードすればよいことを理解します。
このクラスをロードし、配送処理に移ります。
ここで、プロセス名とロードするべきクラスの対応関係は
/usr/local/etc/fml/defaults/バージョン/modules
(例 /usr/local/etc/fml/defaults/8.0.0/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 ... その他 ...
プロセス実行時の様子
[/usr/local/libexec/fml/loader (wrapper)の実行]
この段階では、まだ &fml8; Perl モジュール群に制御が移っていません。
このプログラムは、loader 内の関数 Bootstrap() を実行します。
distribute など libexec/ 以下にあるプログラム群は、
どれも、この loader へのシンボリックリンクです。
/usr/local/libexec/fml/ 以下を参照してください。
[loader 内 Bootstrap() 関数の実行]
/usr/local/etc/fml/main.cf を読み込み、
実行するべき fml のバージョンを知ります。
また、
main.cf の値から
@INC (Perl のライブラリサーチパス)を再設定し、
読み込むべきライブラリのバージョン依存性を解決します。
default_config.cf.{ja,en} はバージョン依存ですので、
設定ファイルを読み込む前に、
この段階でバージョンを評価しなければいけません。
@ARGV (実行されたプログラムの引数)を評価し、
どのMLの config.cf (設定ファイル)群を読み込むべきか?を判断します。
このあと、ようやく
FML::Process::Switch
(バージョン依存)クラスをロードします。
Bootstrap2() および ProcessSwitch() を実行し、
FML::Process::Flow 経由で、
配送用、コマンドメール用などの各プロセスへ制御を移していきます。
この時点で、
どのモジュール(例: FML::Process::Distribute)
をロードするのかは分かっています。
FML::Process::Distribute オブジェクトなどは、
FML::Process::Flow の関数を呼び出す際に引数として渡されています。
FML::Process::Flow 経由で、
各モジュール(例: FML::Process::Distribute)
のメソッドを呼び出します。
FML::Process::Flow の中には、
どのように &fml8; プロセスを実行するかが規格化/定義されています。
おおむね、どのプロセスも
$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() メソッドあたりで解決しています。
以下、内部構造についての走り書き/おぼえがきです。
一応、こういった構造を考慮して、
prepare()
に持ってきています。
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
メールを読み込む
コマンドラインを解析する