<!-- -*- mode:text coding:euc-jp -*-
   $FML: internal.sgml,v 1.13 2008/08/17 18:28:36 fukachan Exp $
-->


<sect1 id="fml.command.internal.change">
	<title>
	補足:
	『&fml4;と &fml8; のコードの書き方はどのくらい違うか？』
	</title>

<para>
コマンドの典型である『ファイルを送り返す』だけの 
help コマンドを例にとり、
&fml4;と &fml8; のコードの相違点を説明しましょう。
</para>

<para>
&fml4; では、適当な関数、たとえば myProcHelpFileSendBack を作り、
%LocalProcedure に書いておきます。
<screen>
%LocalProcedure = (
                    'help',     'myProcHelpFileSendBack',
                );
</screen>
myProcHelpFileSendBack をあえて書きくだすと、次のようなものでしょう。
<screen>
sub myProcHelpFileSendBack
{
    local($proc, *Fld, *e, *misc) = @_;
    my $UJA_FILE = "/some/where/help";
    &amp;SendFile($Envelope{'Addr2Reply:'}, "UJA $ML_FN", $UJA_FILE);
}
</screen>
</para>

<para>
一方、&fml8; の help ファイルを送り返すコードの実体は
FML::Command::User::help にあり、
FML::Process::Command クラスから
(FML::Command の AUTOLOAD を経由して)呼び出されます。
</para>

<warning>
<para>
全てのコマンドは
「FML::Command::User::コマンド」
もしくは
「FML::Command::Admin::コマンド」
クラスとして実装されています。
なお 
makefml は「FML::Command::Admin::コマンド」を使います。
コマンドメールや CGI は User や Admin を権限に応じて適宜使い分けます。
</para>
</warning>

<para>
help コマンドの実体は FML::Command::User::help の process() 関数です。
<screen>
sub process
{
    my ($self, $curproc, $optargs) = @_;
    my $config    = $curproc->config();
    my $charset   = $config->{ report_mail_charset_ja };
    my $help_file = $config->{ help_file };

    # template substitution: kanji code, $varname expansion et. al.
    my $params = {
        src         => $help_file,
        charset_out => $charset,
    };
    my $help_template = $curproc->reply_message_prepare_template( $params );

    if (-f $help_template) {
        $curproc->reply_message( {
            type        => "text/plain; charset=$charset",
            path        => $help_template,
            filename    => "help",
            disposition => "help",
        });
    }
    else {
        croak("no help file ($help_template)\n");
    }
}
</screen>
ここで $curproc はハッシュリファレンスで、
&fml4; の %Envelope におおむね相当しています。
名前のとおり、
Unix カーネルでおなじみの current process 構造体へのポインタのようなもので、
プロセス関連の様々なデータ構造やオブジェクトへのリファレンスを含んでいます。
</para>

<para>
&fml4; の変数は、すべてグローバル変数です。
一方 &fml8; では
$config オブジェクトを通じてアクセスできる設定変数空間の中にあります。
よって、つねに $config オブジェクトを通じて読み書きをしてください。
</para>

<para>
reply_message_prepare_template() メソッドは、
送り返すメッセージのテンプレート中にある変数の展開や文字コード変換を行ない、
生成されたテンプレートへのファイルパスを返します
(テンプレートファイルは $tmp_dir ディレクトリに作られます)。
</para>

<para>
首尾よくテンプレートファイルを用意できたなら、
$curproc->reply_message()
というプロセス全体のメッセージ処理を行なうトップレベルのメソッドを呼び出し、
メッセージの返送処理を依頼します。
</para>

<para>
$curproc->reply_message() は引数によって振舞いが異なりますが、
いずれにせよ、
メッセージをメッセージキューに入れるメソッドです。
</para>

<para>
コマンドモジュールでの処理は、キューに入れたところで終りとなります。
以下の返送処理は、どんな時でも行なわれる通常のフローの一部です。
</para>

<para>
メッセージキューに入れられたメッセージ群は、
プロセスの終了直前に受信者ごとにメッセージがまとめられ、
一通のメールとして組み立てなおされます。
メッセージキューの種類がファイルとメッセージが混在している場合は、
適宜 MIME マルチパートのメッセージが生成されます。
</para>

<para>
メッセージの準備が整うと、送信処理を担当するメソッドが呼ばれます。
Mail::Delivery クラスが送信処理を担当するモジュールです。
生成されたメールは、
最終的に Mail::Delivery クラスへ渡され送信処理が行なわれます。
</para>

<para>
この返送の大筋は &fml4; の Notify() と同様ですが、
あらゆるメッセージが一度キューに入れられ、
最後に一気に処理されるという点で大きく異なります。
</para>

<para>
なお get コマンドなども同じキューイングの仕組みを使っています。
つまり &fml4; の Notify() 相当部分が
(通常の記事配送以外の)あらゆる送信機能を担当し、
かつキューイングのみをします。
そしてキューイングされたメッセージは最後に一気に処理されます。
この点において、
送信のキューイングのメカニズムが &fml4; と大きく異なっているわけです。
</para>

</sect1>
