<!--
   $FML: bootloader.sgml,v 1.12 2004/10/06 09:07:37 fukachan Exp $
-->


<chapter id="bootloader">
	<title>
	バージョン依存性を解決するための fml ブートローダ
	</title>

<para>
&fml8; にはインストールされている fml のバージョン依存性を考慮するため
に、本章で述べるようなブートストラップの過程があります。
<screen>
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
</screen>
</para>


<sect1 id="bootloader.example.distribute">
	<title>
	例: 配送の場合
	</title>

<para>
loader から次々と呼ばれていく様子は、例えば配送処理の場合、次のよう
になります。
</para>

<para>
/usr/local/libexec/fml/distributre (の実体は 
/usr/local/libexec/fml/loader) は /usr/local/etc/fml/main.cf を読みこ
み、fml_version 変数から使うべきライブラリのバージョンを決めます。例え
ば fml_vesrion が current-20010501 となっていたら
/usr/local/lib/fml/current-20010501/ 以下にあるライブラリを使うといっ
た具合です。
</para>

<para>
@INC を再設定した後、
loader は FML::Process::Switch をロードし、
$0 を調べます。
その名前から自分の仕事は配送処理配送処理なので
FML::Process::Distribute クラスをロードし、配送処理に移ります。
</para>

<para>
なお、プログラム名とクラスの対応関係は 
etc/fml/defaults/バージョン/modules 
で定義されています。
</para>

<para>
こういった処理は見かけ上 FML::Process::Flow::ProcessStart() という関数
が制御しています。ProcessStart() が引数として FML::Process::Distribute 
オブジェクトを渡され、FML::Process::Distribute オブジェクトを実行して
いくという流れになります。
</para>

</sect1>


<sect1 id="bootloader.classes">
	<title>
	FML::Process:: クラスの階層構造
	</title>

<para>
<screen>
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  ... その他 ...
</screen>

</para>
</sect1>


<sect1 id="bootloader.classes2">
	<title>
	プロセス実行時に使われるモジュール群
	</title>

<itemizedlist>

   <listitem>
	<para>
	libexec/loader (wrapper)
	Bootstrap() を実行する。
	libexec/distribute などは、皆この loader へのシンボリックリンクです。
	/usr/local/libexec/fml/ 以下を参照して下さい。
	</para>
   </listitem>

   <listitem>
   <itemizedlist>
	<listitem>
	<para>
	/usr/local/etc/fml/main.cf を読み込む。
	読み込むと fml のバージョンが分かる。
	main.cf の値から @INC を再設定しバージョン依存性を解決します。
	default_config.cf はバージョン依存ですので、
	設定ファイルを読み込む前に、
	この段階でバージョンを評価しなければいけないことに注意してください。
	</para>
	</listitem>

	<listitem>
	<para>
	@ARGV を評価し、
	どのＭＬの config.cf 群をロードすればいいのかを準備します。
	</para>
	</listitem>

	<listitem>
	<para>
	次に
	FML::Process::Switch
	(バージョン依存)クラスを
	ロードします。
	</para>

	   <itemizedlist>
		<listitem>
		<para>
		Bootstrap2() および ProcessSwitch() を実行し、
		配送用、コマンドメール用の各プロセスへ
		制御を移します。
		この時は $0 から自分の名前を知り、
		どのプロセスへ分岐すればいいのかを判断しています。
		</para>
		</listitem>

		<listitem>
		<para>
		(ポリモーフィズムの例)
		モジュールをダイナミックバインディングし、
		該当するプロセスオブジェクトを生成する。
		そして、プロセスをスタートさせます。

		FML::Process::Flow の中に、
		どのように fml8 プロセスを実行するかが
		定義されています。大雑把には
<screen>
$process = new FML::Process::なにか;
$process->prepare($args);
$process->verify_request($args);
$process->run($args);
$process->finish($args);
</screen>
		のように実行されています。
		各プロセスは、それぞれについて適当なメソッドを
		FML::Process:: 以下に用意する必要があります。
		</para>
		</listitem>
	   </itemizedlist>
	</listitem>
   </itemizedlist>
   </listitem>
</itemizedlist>
</sect1>


<sect1 id="bootloader.resolv.mlxxx">
	<title>
	議論: ml_name と ml_domain の値はどこで解決するのが正しいか？
	</title>

<para>
現在では、FML::Process:: の prepare() あたりで解決しています。
</para>

<para>
以下、内部構造について、２、３の走り書き/おぼえがきを残しておきます。
一応、こういった構造を鑑みて、prepare() のあたりに持ってきているわけです。 
<screen>
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
			メールを読み込む
			コマンドラインを解析する
</screen>
</para>

</sect1>


</chapter>
