<!-- -*- mode:text coding:euc-jp -*-
   $FML: db_modules.sgml,v 1.5 2009/12/26 13:33:26 fukachan Exp $
-->

<!--
    XXX-TODO: データベース関連モジュール も書き直した方が…
-->


<chapter id="db.module">
	<title>
	データベース関連モジュール
	</title>


<sect1 id="db.module.ovewview">
	<title>
	概要もしくは理想像
	</title>

<para>
ＭＬドライバは、
メールのさまざまな要素をデータとして保存する必要があります。
しかしながら、
永続的に持つべきデータと、
一定時間経過後に捨てて良いデータが混在しています。
</para>

<para>
前者の例は(メール)スレッドのデータです。
一方、
後者の例はフィルタシステムの持っている message-id cache などです。
スレッドデータベースも同じく message-id のデータを持っていますし、
記事の分については重複しています。
しかしなが、
これら２つの有効期間は異なるため、別々に取り扱う必要があります。
</para>

<para>
とはいえ、
実際問題、
スレッド関係とそれ以外に集約できそうなので、
各モジュールの理想的な関係は次のようになるのでしょう。
<screen>
モジュールＡ ---|ア|----- スレッド DB
モジュールＢ ---|ダ|
モジュールＣ ---|プ|
モジュールＤ ---|タ|----- キャッシュ (有効期限つき)
</screen>
このスレッド DB は 
<link linkend="threadtrack.db">
Mail::Message::DB
</link>
のようなものとし、アダプタ層が差異を吸収して欲しいと考えました。
そこで、
キャッシュについては、
現在のところ Tie::JournaledDir もしくは FML::Cache::Ring
のいづれかが使われています。
</para>

<para>
なお、
メンバーリストなど永続的データに対しては、
本来、きちんとした DBMS (データベース管理システム)を使うべきです。
</para>

<para>
それらとは異なり、 
本章で述べるデータベースとは、
&fml8; が動作する上で内部的に使っているデータ操作の話になります。
</para>

</sect1>


<sect1 id="db.module.persistent">
	<title>
	永続的なデータの保持
	</title>

<para>
ここでは &fml8; 内部で使っているモジュールの解説をします。
</para>

<para>
永続的にデータを保持する方法はいくつかあります。
いい加減なものから大真面目な実装までいろいろです。
大真面目に考えると、
LRU などの機能を持ったモジュールを利用して作るのかもしれませんが、
やや大げさで、いまひとつしっくりこない気がします。
つまり、
そこまで真面目に virtual memory のような実装をしなくてもよいのでは？
ということです。
それに、もし切実な必要があるのなら、なんらかの
<link linkend="dbms">
DBMS
</link>
	<footnote>
	<para>
	DBMS = DataBase Management System
	</para>
	</footnote>
を使うべきでしょう。
</para>

<para>
&fml8; では、
データの expire の仕方に応じて二種類のデータ保持クラスを用意しています。
二つあるのは、
「サイズを気にせず、時間を区切って expire するのか？」
「使用する領域のサイズをあるていど気にするか？」
という異なる要求に応えるためです。
</para>

</sect1>


<sect1 id="db.module.Tie.JournaledFile">
	<title>
	Tie::JournaledFile クラス
	</title>

<para>
これは、一つのファイルに append していくタイプです。
この機能は
	<ulink url="../../en/modules/Tie/JournaledFile.txt">
	Tie::JournaledFile
	</ulink>
クラスが提供します。
</para>

<para>
このクラスは、
データを追加する場合にも使われていますし、
過去のデータを参照したい場合にも用いられますが、
追加のオペレーションしか行なえません。
つまりジャーナル型ファイルシステム
(Journalized-FS,  LFS (Log Structured File System)(
ような振舞いです。
</para>

<para>
参照する際は、最後に追加したデータが取り出されます。
つまり、値は追加された値を last match で取り出しています。
<footnote>
<para>
原理上 last match 以上の情報抽出も可能です。
過去のログを追跡していくことで、全データ一覧の生成ができます。
また、 last match を first match に切替えることも出来ます。
</para>
</footnote>
</para>

<para>
このクラスは、
サイズを度外視して一定期間のあいだ記録しておきたいデータに対して使います。
たとえば、
登録時の confirmation や message-id のキャッシュです。
これらは expire を時間で制御したいからです。
このクラスは引数でファイル名を与えることになっているので、
ファイル名に日付つきのファイルを選ぶと良いでしょう。
</para>


<para>
なお、普通の tie() とは違う
<screen>
key => [
	ろぐ1	 (どっかのふぁいるのどっかの行),
	ろぐ2	 (どっかのふぁいるのどっかの行),
	ろぐ3	 (どっかのふぁいるのどっかの行),
]
</screen>
型のデータ取り出しをしたい場合があります。
この形のデータ取り出しは
get_all_values_as_hash_ref()
メソッドを使うことで可能です。
</para>


<warning>
<para>
なお検索時の挙動の first match と last match は切替えることができます。
どちらの戦略で探すのか、
クラスオブジェクトを生成する際に明示的に指定することが推奨されます。
デフォルトは last match です
(最後に書き込んだデータが返される振舞いが自然です)。
</para>
</warning>

</sect1>


<sect1 id="db.module.FML.Cache.Ring">
	<title>
	FML::Cache::Ring クラス
	</title>

<para>
この
	<ulink url="../../en/modules/File/CacheDir.txt">
	FML::Cache::Ring
	</ulink>
クラスは、
主にサイズに上限を設けたいタイプのデータを蓄える場合に用います。
時間(expire)については気にしません。
時間ではなくデータのサイズで有無を言わさずデータを廃棄します。
</para>

<para>
デバッグ等に用いるデータであれば、こういった扱いで十分と考えます。
普段は使わないデバッグのために、
ハードディスクを使われてしまうのは嫌ですから。
</para>

<para>
このクラスは、
あるディレクトリ(例: db/)
中に作られた有限個のファイル群の中にデータを蓄えています。
たとえば db/ ディレクトリに 1 〜 100 の名前のファイルが作られ、
順番に使われてきます。
これらのファイルはぐるぐる回って(1 2 3 4 ...)使われ、
一周してしまう(100 を超えると)と、
元に戻って上書き(1 2 3 4 ...)されます。
</para>


<warning>
<para>
ノート:
旧 RingBuffer は FML::Cache::Ring に統合されました。
また、FML::Cache::Ring は File::CacheDir から作られました。
</para>
</warning>

</sect1>


</chapter>
