ファイルシステムがエラーの場合の動作は?
ファイルの読み書きでエラーが起きた場合、
MTA による再送処理が行なわれるように「 &fml8; が異常終了する」か、
「&fml8; 自身が配送処理を行なうか?」の処理が行なわれます。
&fml8; 自身が頑張って配送を終らせようとした場合には、
ログファイルやサマリファイルには欠落が出る可能性があり得ますが、
投稿された記事の内容が失われることだけはないつもりです。
以下、
記事の配送処理でファイルシステムのエラーで書き込みがうまくいかない時、
何が起こるかを説明します。
MTA から &fml8; へメールが渡される時
&fml8; は STDIN から読みこんだメールを一度ディスクに書きます。
この書き込みが成功すれば、処理を進めます。
失敗した場合、
MTA に再挑戦してもらうため、
exit(EX_TEMPFAIL) で &fml8; プロセスを異常終了させます。
くわしくは
を参照してください。
このとき、&fml8; の
incoming queue には中途半端にメールが書き込まれたファイルが残り得ます。
異常終了時には、このファイルを消すようにしていますが、
万が一残ってしまっても、
あとでキュー管理システムにより削除されます。
正確には古くなった
incoming queue のファイルを消す処理が定期的に行なわれるため、
その時に消去される仕組みです。
記事番号の更新に失敗した場合
きちんと新しい記事番号(+1 されたもの)が、
シークエンスファイル(seq)に書き込めたか
(ファイルに書いて、閉じて、再び開いて、再度読みこんでみる)を確認し、
成功していれば、その先へ処理を進めます。
失敗していた場合、
&fml8; は exit(EX_TEMPFAIL) で終了し、
MTA から &fml8; を再呼び出してもらうようにします。
よって、(理論上、ないしは、"ほぼ"確実に)
&fml8; では記事番号重複問題は起こらないようになっています。
なお、記事番号を更新できた「この処理」以降、
exit(EX_TEMPFAIL) で終了するようにプログラムを書いてはいけません。
重複配送がおきてしまうので MTA に再配送を依頼してはいけないのです。
記事の保存の際にエラーになった場合
この処理を開始する時、すでに記事番号は更新されています。
記事の書き込みはできませんが、
オリジナルのメールは既にディスクに書き込まれています。
記事の方は、ヘッダ部分には色々と追加がありますが、
本文はオリジナルメールのものと一緒です。
そこで、incoming queue ディレクトリから
「spool/割り当てられた記事番号」ファイルへ link(2) することで、
記事の内容だけは保存するようにします。
さらに、
記事ファイルにヘッダをつけてあげるコマンドが別途あるとよいでしょうね。
でも、未実装です。
配送するべき記事をディスクに保存することができませんでしたが、
メモリ上に配送するべき記事を確保してあるので、
それを使って記事の配送処理をこころみます。
ただ、このときは( outgoing )メールキューに書き込めないため、
もし配送過程でエラーが生じた場合、
配送は中途半端に終了となります。
ただ、ディスクに記録は残っているので、
管理者の人、よろしくおねがいします
(まぁ、それは最悪の場合で、
たいていは投稿者にもう一度再送をおねがいするほうが簡単でしょう)。
配送処理
配送するべき内容を( outgoing )キューに書き、
書き込み成功後にはじめて配送処理が行なわれます。
キューに書き込めない場合、メモリ上のデータの配送を試みますが、
配送過程でエラーが生じた場合、配送は中途半端に終了となります。
トリッキーな拡張が必要ではありますが、
ちゃんとキューイングをフェイクできる仕組みが必要でしょう。
たとえば、別の(のちに起動された)プロセスが、
「中途半端に終了した記事を再成し、配送キューに挿入を試みる」
といった拡張を”本来は”するべきなのでしょう。
この部分は未実装です。
outgoing キューについての詳細は、
を参照してください。