[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
dbm
- 汎用DBMインタフェース DBM系のライブラリはキーでインデックスされた値をファイルに格納する簡単な方法を 提供します。一種の永続的な連想記憶と言えるでしょう。
このモジュールが定義する抽象クラス<dbm>
は、DBM系ライブラリへの
統一されたインタフェースを提供します。dbm
モジュールだけをインポートすれば、
既にオープンされたデータベースを操作することができます。
データベースをオープンしたり作成したりするには、dbmインタフェースを実装した モジュールが必要になります。今のところGaucheでは以下の実装が使えます。 それぞれのモジュールは、dbmインタフェース共通の手続きの他に、 直接実装を操作できる低レベルの手続きも提供します。 システムによっては以下のインタフェースの全てが実装されているわけではないことに 注意してください。Gaucheではシステムが提供する実装のみを定義します。
dbm.fsdbm
ファイルシステムdbm (dbm.fsdbm
- ファイルシステムdbm参照).
dbm.gdbm
GDBMライブラリ (dbm.gdbm
- GDBMインタフェース参照).
dbm.ndbm
NDBMライブラリ (dbm.ndbm
- NDBMインタフェース参照).
dbm.odbm
DBMライブラリ (dbm.odbm
- オリジナルのDBMインタフェース参照).
以下にdbmデータベースの使用例を示します。
(use dbm) ; dbm abstract interface (use dbm.gdbm) ; dbm concrete interface ; open the database (define *db* (dbm-open <gdbm> :path "mydb" :rw-mode :write)) ; put the value to the database (dbm-put! *db* "key1" "value1") ; get the value from the database (define val (dbm-get *db* "key1")) ; iterate over the database (dbm-for-each *db* (lambda (key val) (foo key val))) ; close the database (dbm-close *db*) |
11.5.1 DBMデータベースのオープンとクローズ | ||
11.5.2 DBMデータベースのアクセス | ||
11.5.3 DBMデータベース上の繰り返し処理 | ||
11.5.4 DBMデータベースインスタンスの管理 | ||
11.5.5 DBM実装を書く |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
DBM系のデータベースのための抽象クラスです。データベースへの共通のオペレーションを
定義します。以下のインスタンススロットを持ちます。これらのスロットの値は
dbm-open
によってデータベースがオープンされる前にセットされて
いなければなりません。
具体クラスは、データベースの操作をより細かく行うための追加のスロット(例えばロックを 行うかどうか)を持つかもしれません。
データベースファイルのパス名。dbmの実装によっては、このパスにサフィックスが追加されます。
読み書きのモードを指定します。以下の値のいずれかを取ります。
:read
データベースはdbm-open
によって読みだし専用モードでオープンされます。
オープンされる時点でデータベースは存在していなければなりません。
:write
データベースはdbm-open
によって読み書き可能なモードでオープンされます。
データベースが存在しなければ、dbm-open
は新しいデータベースを作成します。
:create
dbm-open
によって新しいデータベースが作成され、読み書き可能なモードでオープンされます。
既にデータベースが存在していた場合、その内容はクリアされます。
データベースが作成されるときのファイルパーミッションを指定します。
デフォルトは#o664
です。
デフォルトでは、dbmデータベースはキーにも値にも文字列しか使うことはできません。 これらのスロットによって、それ以外のSchemeオブジェクトを取り扱う方法を指定することが できます。以下の値のいずれかが可能です。
#f
デフォルトの値です。キーあるいは値は変換されません。それらは文字列でなければなりません。
#t
キーあるいは値はwrite
を使って文字列に変換されデータベースに格納されます。
そしてread
を使って文字列からSchemeオブジェクトへと変換されます。
後でread
で読みこめるようなキーあるいは値のみを扱うことができます。
(但し、dbmライブラリは書き込み時にそれが後で読み込めるかどうかのチェックは行いません)。
キーの比較は文字列に変換された後で行われるので、同じ値となるキーは同じ文字列表現を
持つ必要があります。
どちらの手続きも一つの引数を取ります。最初の手続きはSchemeオブジェクトを受け取り、 文字列を返します。キーあるいは値をデータベースに格納する時に呼ばれます。 二つ目の手続きは文字列を受け取りSchemeオブジェクトを返します。データベースから キーあるいは値を取り出す時に呼ばれます。 キーの比較は文字列に変換された後で行われるので、同じ値となるキーは同じ文字列に 変換される必要があります。
<dbm>クラス及びそのサブクラスのメタクラスです。
DBMデータベースをオープンします。dbmは、<dbm>
クラスを継承した
具体クラスのインスタンスでなければなりません。また、そのスロットには適切な値が
セットされている必要があります。オープンに成功したらdbm自身が返されます。
失敗した場合はエラーが報告されます。
DBMインスタンスを作成してオープンするための便利なメソッドです。 次のように定義されます。
(define-method dbm-open ((class <class>) . initargs) (dbm-open (apply make class initargs))) |
データベースファイルはガベージコレクトされる際にクローズされますが、 変更を正しくデータベースに反映するには、明示的にクローズした方が良いでしょう。
<dbm>
)
データベースdbmをクローズします。データベースがクローズされると、 それ以降のアクセスオペレーションはエラーとなります。
<dbm>
)
データベースdbmが既にクローズされていたら#t
を返します。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
データベースがオープンされたら、以下のアクセスメソッドが使えます。
<dbm>
) key value
値valueをキーkeyと関連付けて保存します。
<dbm>
) key &optional default
キーkeyに関連付けられた値を返します。もし値が存在しなければ、defaultが 与えられていればそれを返し、そうでなければエラーを報告します。
<dbm>
) key
キーkeyに関連付けられた値が存在すれば#t
を返します。
<dbm>
) key
キーkeyに関連付けられた値を消去します。値が存在しない場合は何もしません。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
全データベースを渡り歩く処理のために、以下のメソッドが用意されています。
<dbm>
) procedure knil
基本的な繰り返し処理です。データベース内の各キー/値のペアに関して、手続き
procedureが (procedure key value r)
,
のように呼ばれます。ここでrは、最初のprocedureの呼び出しの時にはknil
が、以降の呼び出しの時にはその直前のprocedureが返した値が渡されます。
最後のprocedureの戻り値がdbm-fold
の戻り値となります。
データベース中にデータがひとつもなければknilがそのまま返されます。
次の例は、データベース中の整数の値を全て加算します。
(dbm-fold dbm (lambda (k v r) (if (integer? v) (+ v r) r)) 0) |
<dbm>
) procedure
データベース内の各キー/値のペアに関して、手続きprocedureを呼び出します。 procedureにはキーと値が渡されます。procedureの戻り値は捨てられます。
<dbm>
) procedure
データベース内の各キー/値のペアに関して、手続きprocedureを呼び出します。
procedureにはキーと値が渡されます。procedureの戻り値はリストに
集められてdbm-map
の戻り値となります。
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
各DBM実装は、データベースを格納するのに独自の方法を使います。
レガシーなDBMは、pathスロットの値にそれぞれ‘.dir’と
‘.pag’を付けた名前の2つのファイルを使います。
fsdbm
はpathの下にディレクトリを作ります。
DBMデータベースが他のデータベースサーバによってバック
アップされる場合は、pathはそのサーバで単なるキーと
して使われるでしょう。
以下のメソッドは、そのようなバリエーションを隠し、 データベースそれ自体を管理する簡易な方法を提供します。 最初の引数に、具体的なDBMデータベースを実装している クラスを渡す必要があります。
nameで指定されたclassクラスのデータベースが
存在する場合は#t
を返します。
;; Returns #t if testdb.dir and testdb.pag exist (dbm-db-exists? <odbm> "testdb") |
nameで指定されるclassクラスのデータベース 全体を削除します。
fromで指定されたclassクラスのデータベースを toへコピーします。 classのdbm実装がロックをサポートしている限り、fromの一貫性は 保たれます (つまり、コピー中に他のプロセスがfromを 変更しようとした場合であっても、toが壊れたデータベースになることは ありません)。 もしコピー先のtoが既に存在するデータベースで あった場合、toの元の内容は失われます。 コピーが中断された場合にtoが不完全な状態のままになるかどうかは dbm実装に依存します。dbm実装の多くはトランザクショナルな振る舞い、 すなわち、コピーが失敗した場合に元のtoを復元することを試みます。 しかし確実な操作のためには、コピーが失敗した場合には呼び出し側でtoの 状態を確認することが必要です。
(dbm-db-copy <gdbm> "testdb.dbm" "backup.dbm") |
fromで指定されたclassクラスのデータベースを
toへ移動、あるいはリネームします。dbm-db-copy
と同じく、
classのdbm実装がロックをサポートしていれば
データベースの一貫性は保証されます。移動先のtoが既に
存在していた場合、その元の内容は失われます。
存在
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
When you write an extension module that behaves like a persistent hashtable, it is a good idea to adapt it to the dbm interface, so that the application can use the module in a generic way.
The minimum procedures to conform the dbm interface are as follow:
<foo-meta>
. It doesn't
need to inherit anything except <class>
.
<foo>
that inherits <dbm>
and whose metaclass is <foo-meta>
.
dbm-open
, dbm-close
,
dbm-put!
, dbm-get
, dbm-exists
,
dbm-delete!
, dbm-fold
, dbm-closed?
,
specialized for <foo>
.
(The case of dbm-open
for <foo-meta>
is
handled automatically, so you don't need to define it unless
you want something special).
Also note that the specialized dbm-open
must call
next-method
in it to set up dbm base class internals.
dbm-db-exists?
and
dbm-db-remove
on <foo-meta>
.
Besides above, you may define the following methods.
dbm-for-each
and dbm-map
.
If you don't define them, a generic implementation
by dbm-fold
is used. There may be an implementation
specific way which is more efficient.
dbm-db-copy
and dbm-db-move
.
If you don't define them, a fallback method
opens the specified databases and copies elements one by
one, and removes the original if the method is dbm-db-move
.
Note that the fallback method is not only inefficient,
but also it may not copy any implementation-specific
meta information. It is highly recommended for the
dbm implementation to provide these methods as well.
It is generally recommended to name the implementation module
as dbm.foo
, and the class of the implementation
as <foo>
. With this convention it is easier to
write an application that dynamically loads and uses
dbm implementation specified at runtime.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.