データベース関連モジュール
概要もしくは理想像
MLドライバはメールのさまざまな要素をデータとして保存する必要がありま
す。しかしながら、永続的に持つべきデータと、一定時間経過後に捨てて良い
データがあります。
前者の例はスレッドのデータです。一方、後者の例はフィルタシステムの持っ
ている message-id cache などです。スレッドデータベースも同じく
message-id のデータを持っていますし、記事の分については重複しています。
ですが、2つの有効期間は異なるため別々に取り扱う必要があります。
とはいえ実際問題スレッド関係とそれ以外に集約できそうなので、
各モジュールの理想的な関係は次のようになるのでしょう。
モジュールA ---|ア|----- スレッド DB
モジュールB ---|ダ|
モジュールC ---|プ|
モジュールD ---|タ|----- キャッシュ (有効期限つき)
このスレッド DB は
Mail::Message::DB
のようなものとし、アダプタ層が差異を吸収して欲しい。
キャッシュについては、現在のところ Tie::JournaledDir もしくは
FML::Cache::Ring のいづれかが使われることとなっています。
なお、
メンバーリストなどの永続性の必要なデータに対してデータベースを使う場合は、
本来、きちんとした DBMS (データベース管理システム)を使うべきです。
本章で述べるデータベースはそれとは異なり、
&fml8; が動作する上で内部的に使っているデータベースのことです。
永続的なデータの保持
永続的にデータを保持する方法はいくつかあります。いい加減なものから大真
面目なものまでいろいろです。大真面目に考えると、LRU などの機能を持った
モジュールを利用して作るのかもしれませんが、やや大げさで、いまひとつしっ
くりこない気がします。つまり、そこまで真面目に virtual memory のような
実装をしなくてもよいのでは?ということです。それに、もし切実な必要があ
るのなら、なんらかの
DBMS
DBMS = DataBase Management System
を使うべきでしょう。
ここでは &fml8; 内部で使っているモジュールの解説をします。
&fml8; では、データの expire の仕方に応じて2つのデータ保持クラスを用
意しています。
それは
「サイズを気にせず、時間を区切って expire するのか?」
「使用する領域のサイズをある程度気にするか?」
の2種類です。
Tie::JournaledFile クラス
これは、一つのファイルに append していくタイプです。
この機能は
Tie::JournaledFile
クラスが提供します。
このクラスは、データを追加する場合にも使われていますし、過去のデータを
参照したい場合にも用いられますが、追加のオペレーションしか行なえません。
つまり LFS (Log Structured File System) のような振舞いです。
参照する際は最後に追加したデータが取り出されます。
つまり、値は追加された値を last match で取り出しています。
原理上 last match 以上の情報抽出も可能です。
過去のログを追跡していくことで、全データ一覧の生成ができます。
また、 last match を first match に切替えることも出来ます。
このクラスは、サイズを度外視して一定期間のあいだ記録しておきたいデータ
に対して使います。たとえば、登録時の confirmation のキャッシュや
message-id キャッシュです。これらは expire を時間で制御したいからです。
このクラスは引数でファイル名を与えることになっているので、ファイル名に
日付つきのファイルを選ぶと良いでしょう。
なお、普通の tie() とは違う
key => [
ろぐ1 (どっかのふぁいるのどっかの行),
ろぐ2 (どっかのふぁいるのどっかの行),
ろぐ3 (どっかのふぁいるのどっかの行),
]
型のデータ取り出しをしたい場合があります。
この形のデータ取り出しは
get_all_values_as_hash_ref()
メソッドを使えば可能です。
なお検索時の挙動の first match と last match は切替えることができます。
どちらの戦略で探すのか、クラスオブジェクトを生成する際に明示的に指定す
ることが推奨されます。デフォルトは last match です(最後に書き込んだデー
タが返される振舞いが自然です)。
FML::Cache::Ring クラス
この
FML::Cache::Ring
クラスは、主にサイズに上限を設けたいタイプのデータを蓄える場合に用
います。時間(expire)については気にしません。
時間ではなくデータのサイズで有無を言わさずデータを廃棄します。
デバッグ等に用いるデータであれば、こういった扱いで十分と考えます。
普段は使わないデバッグのために、
ハードディスクを使われてしまうのは嫌ですから。
このクラスは、あるディレクトリ(例: db/)中に作られた有限個のファイル群
の中にデータを蓄えています。
たとえば db/ ディレクトリに 1 〜 100 の名前のファイルがつくられ、
順番に使われてきます。
これらのファイルはぐるぐる回って(1 2 3 4 ...)使われ、
一周してしまう(100 を超えると)と、元に戻って上書き(1 2 3 4 ...)されます。
旧 RingBuffer は FML::Cache::Ring に統合されました。
また、FML::Cache::Ring は File::CacheDir から作られました。