=encoding euc-jp =head1 NAME =begin original DB_File - Perl5 access to Berkeley DB version 1.x =end original DB_File - Berkeley DB バージョン 1.xへの Perl5 アクセス =head1 SYNOPSIS =begin original use DB_File; =end original use DB_File; =begin original [$X =] tie %hash, 'DB_File', [$filename, $flags, $mode, $DB_HASH] ; [$X =] tie %hash, 'DB_File', $filename, $flags, $mode, $DB_BTREE ; [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ; =end original [$X =] tie %hash, 'DB_File', [$filename, $flags, $mode, $DB_HASH] ; [$X =] tie %hash, 'DB_File', $filename, $flags, $mode, $DB_BTREE ; [$X =] tie @array, 'DB_File', $filename, $flags, $mode, $DB_RECNO ; =begin original $status = $X->del($key [, $flags]) ; $status = $X->put($key, $value [, $flags]) ; $status = $X->get($key, $value [, $flags]) ; $status = $X->seq($key, $value, $flags) ; $status = $X->sync([$flags]) ; $status = $X->fd ; =end original $status = $X->del($key [, $flags]) ; $status = $X->put($key, $value [, $flags]) ; $status = $X->get($key, $value [, $flags]) ; $status = $X->seq($key, $value, $flags) ; $status = $X->sync([$flags]) ; $status = $X->fd ; =begin original # BTREE only $count = $X->get_dup($key) ; @list = $X->get_dup($key) ; %list = $X->get_dup($key, 1) ; $status = $X->find_dup($key, $value) ; $status = $X->del_dup($key, $value) ; =end original # BTREE のみ $count = $X->get_dup($key) ; @list = $X->get_dup($key) ; %list = $X->get_dup($key, 1) ; $status = $X->find_dup($key, $value) ; $status = $X->del_dup($key, $value) ; =begin original # RECNO only $a = $X->length; $a = $X->pop ; $X->push(list); $a = $X->shift; $X->unshift(list); @r = $X->splice(offset, length, elements); =end original # RECNO のみ $a = $X->length; $a = $X->pop ; $X->push(list); $a = $X->shift; $X->unshift(list); @r = $X->splice(offset, length, elements); =begin original # DBM Filters $old_filter = $db->filter_store_key ( sub { ... } ) ; $old_filter = $db->filter_store_value( sub { ... } ) ; $old_filter = $db->filter_fetch_key ( sub { ... } ) ; $old_filter = $db->filter_fetch_value( sub { ... } ) ; =end original # DBM フィルタ $old_filter = $db->filter_store_key ( sub { ... } ) ; $old_filter = $db->filter_store_value( sub { ... } ) ; $old_filter = $db->filter_fetch_key ( sub { ... } ) ; $old_filter = $db->filter_fetch_value( sub { ... } ) ; =begin original untie %hash ; untie @array ; =end original untie %hash ; untie @array ; =head1 DESCRIPTION =begin original B is a module which allows Perl programs to make use of the facilities provided by Berkeley DB version 1.x (if you have a newer version of DB, see L). It is assumed that you have a copy of the Berkeley DB manual pages at hand when reading this documentation. The interface defined here mirrors the Berkeley DB interface closely. =end original B は Berkeley DB version 1.x によって提供されている機能を Perl プログラムが使えるようにするモジュールです (もしさらに新しいバージョンの DB を持っているのであれば、 L をご覧ください)。 このドキュメントを読むとき、あなたが Berkeley DBマ ニュアルページを 手元においていることを前提としています。 ここで定義されているインターフェースは Berkeley DB インターフェースを かなり反映しています。 =begin original Berkeley DB is a C library which provides a consistent interface to a number of database formats. B provides an interface to all three of the database types currently supported by Berkeley DB. =end original Berkeley DB はいくつかのデータベースフォーマットに対する 一貫性のあるインターフェースを提供する C ライブラリです。 B は現在 Berkeley DB によってサポートされている三つ全ての データベースタイプへのインタフェースを提供しています。 =begin original The file types are: =end original そのファイルタイプには以下ものがあります: =over 5 =item B =begin original This database type allows arbitrary key/value pairs to be stored in data files. This is equivalent to the functionality provided by other hashing packages like DBM, NDBM, ODBM, GDBM, and SDBM. Remember though, the files created using DB_HASH are not compatible with any of the other packages mentioned. =end original このデータベースタイプは、任意のキー/値の組をデータファイルに 格納することを可能にします。 これは機能の面で DBM, NDBM, ODBM, GDBM, SDBMといった他のハッシュを おこなうパッケージが提供する機能と同じです。 しかし DB_HASH を使って作られたファイルは、いま上げた他のパッケージと 互換性がないということを忘れないでください。 =begin original A default hashing algorithm, which will be adequate for most applications, is built into Berkeley DB. If you do need to use your own hashing algorithm it is possible to write your own in Perl and have B use it instead. =end original デフォルトのハッシュアルゴリズムが Berkeley DB に組み込まれており、 ほとんどのアプリケーションに適合します。 もし独自のハッシュアルゴリズムを 使う必要があれば、Perl で独自に書込み、B が代わりにそれを 使うようにすることも出来ます。 =item B =begin original The btree format allows arbitrary key/value pairs to be stored in a sorted, balanced binary tree. =end original btree フォーマットは任意のキー/値の組を、バランスがとれた 二分木に格納できます。 =begin original As with the DB_HASH format, it is possible to provide a user defined Perl routine to perform the comparison of keys. By default, though, the keys are stored in lexical order. =end original DB_HASH フォーマットの場合と同じように、キーの比較を実行するユーザ定義の Perl のルーチンを提供することが出来ます。 しかしデフォルトでは、キーは文字(lexical)の順に格納されます。 =item B =begin original DB_RECNO allows both fixed-length and variable-length flat text files to be manipulated using the same key/value pair interface as in DB_HASH and DB_BTREE. In this case the key will consist of a record (line) number. =end original DB_RECNO は固定長と可変長の両方のフラットなテキストファイルを、 DB_HASH や DB_BTREE と同じキー/値の組のインターフェースを使って扱える ようにします。 この場合、キーはレコード(行)番号になります。 =back =head2 Using DB_File with Berkeley DB version 2 or greater (DB_File を Berkeley DB バージョン 2 以上で使う) =begin original Although B is intended to be used with Berkeley DB version 1, it can also be used with version 2, 3 or 4. In this case the interface is limited to the functionality provided by Berkeley DB 1.x. Anywhere the version 2 or greater interface differs, B arranges for it to work like version 1. This feature allows B scripts that were built with version 1 to be migrated to version 2 or greater without any changes. =end original B は Berkeley DB バージョン 1 を使うようになっていますが、 バージョン 2, 3, 4 で使うことも出来ます。 この場合、インターフェースは Berkeley DB 1.x によって 提供されている機能に限定されます。 バージョン 2 以上のインターフェースで異なる箇所は、 どこでもバージョン 1 のように機能するよう B が変更しています。 この機能により、バージョン 1 で構築された B スクリプトを変更することなく、バージョン 2 以上に 移行できます。 =begin original If you want to make use of the new features available in Berkeley DB 2.x or greater, use the Perl module B instead. =end original もし Berkeley DB 2.x 以上で利用可能な新しい機能を使いたいのであれば、 Perl モジュール B を代わりに使ってください。 =begin original B The database file format has changed multiple times in Berkeley DB version 2, 3 and 4. If you cannot recreate your databases, you must dump any existing databases with either the C or the C utility that comes with Berkeley DB. Once you have rebuilt DB_File to use Berkeley DB version 2 or greater, your databases can be recreated using C. Refer to the Berkeley DB documentation for further details. =end original B<注意:> Berkeley DB version 2, 3, 4 でデータベースファイルの フォーマットは何回か変更されています。 もしデータベースを再作成できないのであれば、 Berkeley DB に付いてくる C あるいは C ユーティリティのどちらかで、既存の全てのデータベースを ダンプしなければなりません。 一度、Berkeley DB version 2 以上を使うために DB_File を再作成すれば、 C を使って再作成することができます。 さらなる詳細は Berkeley DB ドキュメントを参照してください。 =begin original Please read L<"COPYRIGHT"> before using version 2.x or greater of Berkeley DB with DB_File. =end original DB_File で Berkeley DB のバージョン 2.x 以上を使う前に L<"COPYRIGHT"> をご覧になってください。 =head2 Interface to Berkeley DB (Berkeley DBへのインターフェース) =begin original B allows access to Berkeley DB files using the tie() mechanism in Perl 5 (for full details, see L). This facility allows B to access Berkeley DB files using either an associative array (for DB_HASH & DB_BTREE file types) or an ordinary array (for the DB_RECNO file type). =end original B は Berkeley DB ファイルに Perl 5 の tie() 機能を使ってアクセスする ことを可能にします。 (完全な詳細については L をご覧下さい)。 この機能は DB_File に連想配列(DB_HASH と DB_BTREE ファイルタイプ)を使ったり、 通常の配列(DB_RECNO ファイルタイプ)を使って Berkeley DB ファイルにアクセスする ことを可能にします。 =begin original In addition to the tie() interface, it is also possible to access most of the functions provided in the Berkeley DB API directly. See L. =end original tie() インターフェースに加えて、Berkeley DB API によって提供される、ほとんど 全ての関数に直接アクセスすることもできます。 L をご覧下さい。 =head2 Opening a Berkeley DB Database File (Berkeley DB データベースファイルのオープン) =begin original Berkeley DB uses the function dbopen() to open or create a database. Here is the C prototype for dbopen(): =end original Berkeley DB はデータベースのオープンや作成に dbopen() 関数を使います。 dbopen() の C プロトタイプは以下の通りです: DB* dbopen (const char * file, int flags, int mode, DBTYPE type, const void * openinfo) =begin original The parameter C is an enumeration which specifies which of the 3 interface methods (DB_HASH, DB_BTREE or DB_RECNO) is to be used. Depending on which of these is actually chosen, the final parameter, I points to a data structure which allows tailoring of the specific interface method. =end original パラメータ C は列挙子(enumeration)で、三つのインタフェースメソッド (DB_HASH, DB_BTREE, DB_RECNO)のどれを使うかを指定します。 実際にどれが選ばれたかによって、最後のパラメータ I には指定された インタフェースメソッドに適合するデータ構造体を指定します。 =begin original This interface is handled slightly differently in B. Here is an equivalent call using B: =end original インターフェースは B では若干異なります。 B を使った同じ呼び出しは以下の通りです: tie %array, 'DB_File', $filename, $flags, $mode, $DB_HASH ; =begin original The C, C and C parameters are the direct equivalent of their dbopen() counterparts. The final parameter $DB_HASH performs the function of both the C and C parameters in dbopen(). =end original C, C, C パラメータは dbopen() での対応する ものとそのまま同じです。 最後のパラメータ $DB_HASH は dbopen() での C と C パラメータの両方の機能を行います。 =begin original In the example above $DB_HASH is actually a pre-defined reference to a hash object. B has three of these pre-defined references. Apart from $DB_HASH, there is also $DB_BTREE and $DB_RECNO. =end original 上記の例では $DB_HASH は実際にあらかじめ定義されたハッシュオブジェクトへの リファレンスになります。 DB_File はこれらの既に定義された三つのリファレンスを 持っています。 $DB_HASH のほかに $DB_BTREE と $DB_RECNO があります。 =begin original The keys allowed in each of these pre-defined references is limited to the names used in the equivalent C structure. So, for example, the $DB_HASH reference will only allow keys called C, C, C, C, C and C. =end original これら既に定義されているリファレンスで許されるキーは、 等価な C 構造体で使われている名前に限定されます。 そのため例えば $DB_HASH は C, C, C, C, C, C だけをキーとして許します。 =begin original To change one of these elements, just assign to it like this: =end original これらの要素を変更するには、以下のように代入するだけです: $DB_HASH->{'cachesize'} = 10000 ; =begin original The three predefined variables $DB_HASH, $DB_BTREE and $DB_RECNO are usually adequate for most applications. If you do need to create extra instances of these objects, constructors are available for each file type. =end original 三つのあらかじめ定義された変数 $DB_HASH, $DB_BTREE そして $DB_RECNO は大抵の アプリケーションに適応します。 もしこられオブジェクトの特別なインスタンスを作る必要があれば、 それぞれのファイルタイプのためにコンストラクタを利用します。 =begin original Here are examples of the constructors and the valid options available for DB_HASH, DB_BTREE and DB_RECNO respectively. =end original DB_HASH, DB_BTREE そして DB_RECNOに対応するコンストラクタと適切なオプションの それぞれの例を以下に示します: $a = new DB_File::HASHINFO ; $a->{'bsize'} ; $a->{'cachesize'} ; $a->{'ffactor'}; $a->{'hash'} ; $a->{'lorder'} ; $a->{'nelem'} ; $b = new DB_File::BTREEINFO ; $b->{'flags'} ; $b->{'cachesize'} ; $b->{'maxkeypage'} ; $b->{'minkeypage'} ; $b->{'psize'} ; $b->{'compare'} ; $b->{'prefix'} ; $b->{'lorder'} ; $c = new DB_File::RECNOINFO ; $c->{'bval'} ; $c->{'cachesize'} ; $c->{'psize'} ; $c->{'flags'} ; $c->{'lorder'} ; $c->{'reclen'} ; $c->{'bfname'} ; =begin original The values stored in the hashes above are mostly the direct equivalent of their C counterpart. Like their C counterparts, all are set to a default values - that means you don't have to set I of the values when you only want to change one. Here is an example: =end original 上記でハッシュに格納される値はCの対応する部分と全く同じです。 それらは C の対応部分のように、全てはデフォルトに設定されます - つまり一部を変更したいだけであれば全ての値を設定する 必要が無いということです。 以下に例を示します: $a = new DB_File::HASHINFO ; $a->{'cachesize'} = 12345 ; tie %y, 'DB_File', "filename", $flags, 0777, $a ; =begin original A few of the options need extra discussion here. When used, the C equivalent of the keys C, C and C store pointers to C functions. In B these keys are used to store references to Perl subs. Below are templates for each of the subs: =end original いくつかのオプションについては、さらに説明する必要があります。 使用するさい、CでのC、C、Cという項目は C関数へのポインタを格納します。 Bでは、これらのキーは Perlサブルーチンへのリファレンスを格納するために使われます。 各サブルーチンのテンプレートは以下に示します: =begin original sub hash { my ($data) = @_ ; ... # return the hash value for $data return $hash ; } =end original sub hash { my ($data) = @_ ; ... # $data のためのハッシュ値を返す return $hash ; } =begin original sub compare { my ($key, $key2) = @_ ; ... # return 0 if $key1 eq $key2 # -1 if $key1 lt $key2 # 1 if $key1 gt $key2 return (-1 , 0 or 1) ; } =end original sub compare { my ($key, $key2) = @_ ; ... # 戻り値 $key1 eq $key2 ならば 0 # $key1 lt $key2 ならば -1 # $key1 gt $key2 ならば 1 return (-1 , 0 or 1) ; } =begin original sub prefix { my ($key, $key2) = @_ ; ... # return number of bytes of $key2 which are # necessary to determine that it is greater than $key1 return $bytes ; } =end original sub prefix { my ($key, $key2) = @_ ; ... # $key1 よりも大きいと判定するために必要な # $key2 の長さの長さを返します return $bytes ; } =begin original See L for an example of using the C template. =end original C テンプレートを使った例については L を ご覧下さい。 =begin original If you are using the DB_RECNO interface and you intend making use of C, you should check out L. =end original DB_RECNO インターフェースを使っていて、C を使おうとするのであれば、 L をチェックする必要があります。 =head2 Default Parameters (デフォルトパラメータ) =begin original It is possible to omit some or all of the final 4 parameters in the call to C and let them take default values. As DB_HASH is the most common file format used, the call: =end original C の呼び出しでの最後の四つのパラメータのいくつか、 あるいは全てを省略し、デフォルト値をとるようにすることができます。 以下のように呼び出すと、最も一般的なファイルフォーマットである DB_HASH が使われます: =begin original tie %A, "DB_File", "filename" ; =end original tie %A, "DB_File", "filename" ; =begin original is equivalent to: =end original これは以下のものと同等です: tie %A, "DB_File", "filename", O_CREAT|O_RDWR, 0666, $DB_HASH ; =begin original It is also possible to omit the filename parameter as well, so the call: =end original ファイル名(filename)パラメータも省略することが可能です。 以下のように 呼び出します: tie %A, "DB_File" ; =begin original is equivalent to: =end original これは以下のものと同等です: tie %A, "DB_File", undef, O_CREAT|O_RDWR, 0666, $DB_HASH ; =begin original See L for a discussion on the use of C in place of a filename. =end original ファイル名の場所でCを使うことについての説明は L をご覧下さい。 =head2 In Memory Databases (メモリ上のデータベース) =begin original Berkeley DB allows the creation of in-memory databases by using NULL (that is, a C<(char *)0> in C) in place of the filename. B uses C instead of NULL to provide this functionality. =end original Berkeley DB はファイル名の場所に NULL(つまり C での C<(char *)0>)を 使うことにより、メモリ上のデータベース(in-memory database)を 作成することを可能にしています。 B では、この機能を提供するために NULL の代わりに C を使います。 =head1 DB_HASH =begin original The DB_HASH file format is probably the most commonly used of the three file formats that B supports. It is also very straightforward to use. =end original DB_HASH ファイルフォーマットは B がサポートしている三つの ファイルフォーマットの中で、おそらく最も一般的に使われています。 これは非常に使い方がわかりやすいものです。 =head2 A Simple Example (簡単な例) =begin original This example shows how to create a database, add key/value pairs to the database, delete keys/value pairs and finally how to enumerate the contents of the database. =end original この例ではデータベースの作り方、データベースへのキー/値の組の追加、 キー/値の組の削除、そして最後にデータベースを順に出力する方法を示します。 use warnings ; use strict ; use DB_File ; our (%h, $k, $v) ; unlink "fruit" ; tie %h, "DB_File", "fruit", O_RDWR|O_CREAT, 0666, $DB_HASH or die "Cannot open file 'fruit': $!\n"; =begin original # Add a few key/value pairs to the file $h{"apple"} = "red" ; $h{"orange"} = "orange" ; $h{"banana"} = "yellow" ; $h{"tomato"} = "red" ; =end original # いくつかのキー/値の組をファイルに追加 $h{"apple"} = "red" ; $h{"orange"} = "orange" ; $h{"banana"} = "yellow" ; $h{"tomato"} = "red" ; =begin original # Check for existence of a key print "Banana Exists\n\n" if $h{"banana"} ; =end original # キーが存在するかチェック print "Banana Exists\n\n" if $h{"banana"} ; =begin original # Delete a key/value pair. delete $h{"apple"} ; =end original # キー/値の組を削除 delete $h{"apple"} ; =begin original # print the contents of the file while (($k, $v) = each %h) { print "$k -> $v\n" } =end original # ファイルの内容を出力する while (($k, $v) = each %h) { print "$k -> $v\n" } untie %h ; =begin original here is the output: =end original 以下のように出力されます: Banana Exists orange -> orange tomato -> red banana -> yellow =begin original Note that the like ordinary associative arrays, the order of the keys retrieved is in an apparently random order. =end original 通常の連想配列(ハッシュ)と同様、取り出されるキーの順番は見た目上、 でたらめになることに注意してください。 =head1 DB_BTREE =begin original The DB_BTREE format is useful when you want to store data in a given order. By default the keys will be stored in lexical order, but as you will see from the example shown in the next section, it is very easy to define your own sorting function. =end original 与えられた順序でデータを格納したいとき、DB_BTREE フォーマットは便利です。 デフォルトではキーは文字の(lexical)順で格納されます。 しかし次のセクションでの例からもわかるように、 ソートするための独自の関数を定義するのは、よても簡単です。 =head2 Changing the BTREE sort order (BTREEソート順の変更) =begin original This script shows how to override the default sorting algorithm that BTREE uses. Instead of using the normal lexical ordering, a case insensitive compare function will be used. =end original このスクリプトは BTREE が使うデフォルトのソート用アルゴリズムを 上書きする方法を示しています。 通常の文字による順序を使う代わりに、大文字/小文字の 違いを無視した比較関数を使います。 use warnings ; use strict ; use DB_File ; my %h ; sub Compare { my ($key1, $key2) = @_ ; "\L$key1" cmp "\L$key2" ; } =begin original # specify the Perl sub that will do the comparison $DB_BTREE->{'compare'} = \&Compare ; =end original # 比較を行う Perl sub を指定します $DB_BTREE->{'compare'} = \&Compare ; unlink "tree" ; tie %h, "DB_File", "tree", O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open file 'tree': $!\n" ; =begin original # Add a key/value pair to the file $h{'Wall'} = 'Larry' ; $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; $h{'duck'} = 'donald' ; =end original # ファイルにキー/値の組を追加 $h{'Wall'} = 'Larry' ; $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; $h{'duck'} = 'donald' ; =begin original # Delete delete $h{"duck"} ; =end original # 削除 delete $h{"duck"} ; =begin original # Cycle through the keys printing them in order. # Note it is not necessary to sort the keys as # the btree will have kept them in order automatically. foreach (keys %h) { print "$_\n" } =end original # 順番にキーを繰り返し、出力します # btree が自動的に順番を保っているので # キーをソートする必要がないことに注意してください foreach (keys %h) { print "$_\n" } untie %h ; =begin original Here is the output from the code above. =end original 上記のコードは以下のように出力します: mouse Smith Wall =begin original There are a few point to bear in mind if you want to change the ordering in a BTREE database: =end original BTREE データベースで順序を変更したいのであれば、いくつか注意すべき ポイントがあります: =over 5 =item 1. =begin original The new compare function must be specified when you create the database. =end original 新しい比較関数はデータベースを作成するときに指定されなければなりません。 =item 2. =begin original You cannot change the ordering once the database has been created. Thus you must use the same compare function every time you access the database. =end original 一度データベースを作成してしまったら順序を変更することはできまんせん。 このためデータベースにアクセスするときには、いつも同じ比較関数を 使わなければなりません。 =item 3 =begin original Duplicate keys are entirely defined by the comparison function. In the case-insensitive example above, the keys: 'KEY' and 'key' would be considered duplicates, and assigning to the second one would overwrite the first. If duplicates are allowed for (with the R_DUPS flag discussed below), only a single copy of duplicate keys is stored in the database --- so (again with example above) assigning three values to the keys: 'KEY', 'Key', and 'key' would leave just the first key: 'KEY' in the database with three values. For some situations this results in information loss, so care should be taken to provide fully qualified comparison functions when necessary. For example, the above comparison routine could be modified to additionally compare case-sensitively if two keys are equal in the case insensitive comparison: =end original キーの重複は完全に比較関数によって定義されます。 上記の大文字/小文字を区別しない例では、キー: 'KEY'と'key' は 重複するものと考えられ、2 番目のものを代入すると最初のものを上書き するでしょう。 (下記で説明する R_DUPS フラグで)重複が許されるれるので あれば、一つの重複したキーがデータベースに格納されます --- そのため (再び上記の例では)キー: 'KEY'、'Key' そして 'key' は、データベースに 三つの値を持った最初のキー: 'KEY' だけを残します。 状況によってはこれは情報のロスになります。 そこで必要なときには完全に修飾された 比較を提供するように注意しなければなりません。 例えば上記の比較ルーチンは、もし二つのキーが大文字/小文字を 区別しないときに同じであれば、追加として大文字/小文字を区別して 比較するように変更することができます: =begin original sub compare { my($key1, $key2) = @_; lc $key1 cmp lc $key2 || $key1 cmp $key2; } =end original sub compare { my($key1, $key2) = @_; lc $key1 cmp lc $key2 || $key1 cmp $key2; } =begin original And now you will only have duplicates when the keys themselves are truly the same. (note: in versions of the db library prior to about November 1996, such duplicate keys were retained so it was possible to recover the original keys in sets of keys that compared as equal). =end original こうすれば、キーそのものが本当に同じときにだけ、 重複を持つことになります。 (注意:1996 年 11 月頃までの db ライブラリのバージョンでは、 そのような重複したキーが残され、そのため同じであると比較されるキーの 集合で元のキーを戻すことができました)。 =back =head2 Handling Duplicate Keys (重複するキーの取り扱い) =begin original The BTREE file type optionally allows a single key to be associated with an arbitrary number of values. This option is enabled by setting the flags element of C<$DB_BTREE> to R_DUP when creating the database. =end original BTREE ファイルタイプはオプションで、一つのキーを任意の個数の値に 関連付けることを可能にしています。 このオプションはデータベースを作成するとき、 C<$DB_BTREE> のフラグ要素を R_DUP に設定することにより可能になります。 =begin original There are some difficulties in using the tied hash interface if you want to manipulate a BTREE database with duplicate keys. Consider this code: =end original BTREE データベースを重複したキーを持って扱いたいならば、tie されている ハッシュインターフェースを使う場合、いくつかの問題があります。 以下のコードについて考えてみてください: use warnings ; use strict ; use DB_File ; my ($filename, %h) ; $filename = "tree" ; unlink $filename ; =begin original # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; =end original # レコードの重複を可能とします $DB_BTREE->{'flags'} = R_DUP ; tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; =begin original # Add some key/value pairs to the file $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # Note the duplicate key $h{'Wall'} = 'Brick' ; # Note the duplicate key and value $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; =end original # いくつかのキー/値の組をファイルに追加します $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # キーの重複に注意 $h{'Wall'} = 'Brick' ; # キーと値の重複に注意 $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; =begin original # iterate through the associative array # and print each key/value pair. foreach (sort keys %h) { print "$_ -> $h{$_}\n" } =end original # 連想配列の分繰り返し、 # 各キー/値の組を出力します foreach (sort keys %h) { print "$_ -> $h{$_}\n" } untie %h ; =begin original Here is the output: =end original これは以下のように出力します: Smith -> John Wall -> Larry Wall -> Larry Wall -> Larry mouse -> mickey =begin original As you can see 3 records have been successfully created with key C - the only thing is, when they are retrieved from the database they I to have the same value, namely C. The problem is caused by the way that the associative array interface works. Basically, when the associative array interface is used to fetch the value associated with a given key, it will only ever retrieve the first value. =end original キーCで3つのレコードが正常に作成できたように見えます - これが唯一本当のことです。 データベースから取り出すと、まるで C という名前で 同じ値が入っているかのように見えます。 問題は連想配列インターフェースが機能する方法によって発生します。 基本的に連想配列インターフェースは与えられたキーに関連付けられた値を 取り出すために使われます。 これは最初の値だけを取り出します。 =begin original Although it may not be immediately obvious from the code above, the associative array interface can be used to write values with duplicate keys, but it cannot be used to read them back from the database. =end original これは上記のコードでは、あまり明確にはなっていませんが、 連想配列インターフェースは重複するキーで値を書きこむことはできます。 しかし、データベースから値を読みこむためには使えません。 =begin original The way to get around this problem is to use the Berkeley DB API method called C. This method allows sequential access to key/value pairs. See L for details of both the C method and the API in general. =end original この問題を回避するためには C という Berkeley DB API メソッドを 使います。 このメソッドは順番にキー/値の組にアクセスすることを可能にします。 C メソッドの詳細とAPI全般については L を ご覧下さい。 =begin original Here is the script above rewritten using the C API method. =end original C API メソッドを使って上記のスクリプトを書き直したものは 以下の通りです: use warnings ; use strict ; use DB_File ; my ($filename, $x, %h, $status, $key, $value) ; $filename = "tree" ; unlink $filename ; =begin original # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; =end original # レコードの重複を可能とします $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; =begin original # Add some key/value pairs to the file $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # Note the duplicate key $h{'Wall'} = 'Brick' ; # Note the duplicate key and value $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; =end original # いくつかのキー/値の組をファイルに追加します $h{'Wall'} = 'Larry' ; $h{'Wall'} = 'Brick' ; # キーの重複に注意 $h{'Wall'} = 'Brick' ; # キーと値の重複に注意 $h{'Smith'} = 'John' ; $h{'mouse'} = 'mickey' ; =begin original # iterate through the btree using seq # and print each key/value pair. $key = $value = 0 ; for ($status = $x->seq($key, $value, R_FIRST) ; $status == 0 ; $status = $x->seq($key, $value, R_NEXT) ) { print "$key -> $value\n" } =end original # 連想配列の分繰り返し、 # 各キー/値の組を出力します。 $key = $value = 0 ; for ($status = $x->seq($key, $value, R_FIRST) ; $status == 0 ; $status = $x->seq($key, $value, R_NEXT) ) { print "$key -> $value\n" } undef $x ; untie %h ; =begin original that prints: =end original これは以下のように出力します: Smith -> John Wall -> Brick Wall -> Brick Wall -> Larry mouse -> mickey =begin original This time we have got all the key/value pairs, including the multiple values associated with the key C. =end original 今度はキー C に関連付けられた複数の値も含めて、全てのキー/値を 取得しました。 =begin original To make life easier when dealing with duplicate keys, B comes with a few utility methods. =end original 重複するキーの扱いをより簡単にするため、B はいくつかの ユーティリティメソッドを備えています。 =head2 The get_dup() Method (get_dup() メソッド) =begin original The C method assists in reading duplicate values from BTREE databases. The method can take the following forms: =end original C メソッドは BTREE データベースから重複した値を読み込むことを 助けます。 このメソッドは以下のような形式とることができます: =begin original $count = $x->get_dup($key) ; @list = $x->get_dup($key) ; %list = $x->get_dup($key, 1) ; =end original $count = $x->get_dup($key) ; @list = $x->get_dup($key) ; %list = $x->get_dup($key, 1) ; =begin original In a scalar context the method returns the number of values associated with the key, C<$key>. =end original スカラコンテキストでは C<$key> というキーに関連付けられた 値の数を返します。 =begin original In list context, it returns all the values which match C<$key>. Note that the values will be returned in an apparently random order. =end original リストコンテキストでは C<$key> に対応する値を全て返します。 値は見かけ上、でたらめな順番で返って来るということに注意してください。 =begin original In list context, if the second parameter is present and evaluates TRUE, the method returns an associative array. The keys of the associative array correspond to the values that matched in the BTREE and the values of the array are a count of the number of times that particular value occurred in the BTREE. =end original リストコンテキストでは、2 番目の引数があり真に評価されれば、 メソッドは連想配列を返します。 その連想配列のキーは BTREE でのマッチした 値に対応し、その配列の値はその値が BTREE に現れる回数です。 =begin original So assuming the database created above, we can use C like this: =end original これをもとに上記で作成したデータベースについて考えると、以下のように C を使うことができます: use warnings ; use strict ; use DB_File ; my ($filename, $x, %h) ; $filename = "tree" ; =begin original # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; =end original # レコードの重複を可能とします $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; my $cnt = $x->get_dup("Wall") ; print "Wall occurred $cnt times\n" ; my %hash = $x->get_dup("Wall", 1) ; print "Larry is there\n" if $hash{'Larry'} ; print "There are $hash{'Brick'} Brick Walls\n" ; my @list = sort $x->get_dup("Wall") ; print "Wall => [@list]\n" ; @list = $x->get_dup("Smith") ; print "Smith => [@list]\n" ; @list = $x->get_dup("Dog") ; print "Dog => [@list]\n" ; =begin original and it will print: =end original これは以下のように出力します: =begin original Wall occurred 3 times Larry is there There are 2 Brick Walls Wall => [Brick Brick Larry] Smith => [John] Dog => [] =end original Wall occurred 3 times Larry is there There are 2 Brick Walls Wall => [Brick Brick Larry] Smith => [John] Dog => [] =head2 The find_dup() Method (find_dup() メソッド) $status = $X->find_dup($key, $value) ; =begin original This method checks for the existence of a specific key/value pair. If the pair exists, the cursor is left pointing to the pair and the method returns 0. Otherwise the method returns a non-zero value. =end original このメソッドは、あるキー/値の組が存在するかどうかをチェックします。 もしその組があればカーソルはその組を示し、メソッドは 0 を返します。 そうでなければメソッドは 0 以外の値を返します。 =begin original Assuming the database from the previous example: =end original 前の例からのデータベースについて考えれば: use warnings ; use strict ; use DB_File ; my ($filename, $x, %h, $found) ; $filename = "tree" ; =begin original # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; =end original # レコードの重複を可能とします $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; print "Larry Wall is $found there\n" ; $found = ( $x->find_dup("Wall", "Harry") == 0 ? "" : "not") ; print "Harry Wall is $found there\n" ; undef $x ; untie %h ; =begin original prints this =end original これは以下のように出力します: Larry Wall is there Harry Wall is not there =head2 The del_dup() Method (del_dup() メソッド) $status = $X->del_dup($key, $value) ; =begin original This method deletes a specific key/value pair. It returns 0 if they exist and have been deleted successfully. Otherwise the method returns a non-zero value. =end original このメソッドは指定されたキー/値の組を削除します。 もし存在し、正常に削除できたら 0 を返します。 そうでなければ 0 以外の値を返します。 =begin original Again assuming the existence of the C database =end original 再び C データベースがあるとします。 use warnings ; use strict ; use DB_File ; my ($filename, $x, %h, $found) ; $filename = "tree" ; =begin original # Enable duplicate records $DB_BTREE->{'flags'} = R_DUP ; =end original # レコードの重複を可能とします $DB_BTREE->{'flags'} = R_DUP ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; $x->del_dup("Wall", "Larry") ; $found = ( $x->find_dup("Wall", "Larry") == 0 ? "" : "not") ; print "Larry Wall is $found there\n" ; undef $x ; untie %h ; =begin original prints this =end original これは以下のように出力します: Larry Wall is not there =head2 Matching Partial Keys (部分キーのマッチング) =begin original The BTREE interface has a feature which allows partial keys to be matched. This functionality is I available when the C method is used along with the R_CURSOR flag. =end original BTREE インターフェースはマッチさせるための部分キーを許すという 機能を持っています。 この機能は R_CURSOR フラグと一緒に C メソッドを 使ったときに I<のみ> 有効です。 $x->seq($key, $value, R_CURSOR) ; =begin original Here is the relevant quote from the dbopen man page where it defines the use of the R_CURSOR flag with seq: =end original dbopen マニュアルページから関連する seq での R_CURSOR フラグの使い方に ついて定義している部分の引用を以下に示します: =begin original Note, for the DB_BTREE access method, the returned key is not necessarily an exact match for the specified key. The returned key is the smallest key greater than or equal to the specified key, permitting partial key matches and range searches. =end original DB_BTREE アクセスメソッドについては返されるキーは必ずしも指定された キーに完全にマッチするわけではないことに注意。 返されるキーは指定されたキーより大きいか同じである 最小のキーで、部分キーマッチや範囲検索を可能としています。 =begin original In the example script below, the C sub uses this feature to find and print the first matching key/value pair given a partial key. =end original 以下の例のスクリプトでは、C サブルーチンは、この機能を使って 指定された部分キーにマッチする最初のキー/値の組を見つけ出力します。 use warnings ; use strict ; use DB_File ; use Fcntl ; my ($filename, $x, %h, $st, $key, $value) ; sub match { my $key = shift ; my $value = 0; my $orig_key = $key ; $x->seq($key, $value, R_CURSOR) ; print "$orig_key\t-> $key\t-> $value\n" ; } $filename = "tree" ; unlink $filename ; $x = tie %h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_BTREE or die "Cannot open $filename: $!\n"; =begin original # Add some key/value pairs to the file $h{'mouse'} = 'mickey' ; $h{'Wall'} = 'Larry' ; $h{'Walls'} = 'Brick' ; $h{'Smith'} = 'John' ; =end original # ファイルにいくつかのキー/値の組を追加します $h{'mouse'} = 'mickey' ; $h{'Wall'} = 'Larry' ; $h{'Walls'} = 'Brick' ; $h{'Smith'} = 'John' ; $key = $value = 0 ; print "IN ORDER\n" ; for ($st = $x->seq($key, $value, R_FIRST) ; $st == 0 ; $st = $x->seq($key, $value, R_NEXT) ) { print "$key -> $value\n" } print "\nPARTIAL MATCH\n" ; match "Wa" ; match "A" ; match "a" ; undef $x ; untie %h ; =begin original Here is the output: =end original これは以下のように出力します: IN ORDER Smith -> John Wall -> Larry Walls -> Brick mouse -> mickey PARTIAL MATCH Wa -> Wall -> Larry A -> Smith -> John a -> mouse -> mickey =head1 DB_RECNO =begin original DB_RECNO provides an interface to flat text files. Both variable and fixed length records are supported. =end original DB_RECNO はフラットなテキストファイルへのインターフェースを提供します。 可変長レコードと固定長レコードの両方をサポートします。 =begin original In order to make RECNO more compatible with Perl, the array offset for all RECNO arrays begins at 0 rather than 1 as in Berkeley DB. =end original RECNO を Perl との互換性を持たせるため、RECNO 配列のための配列オフセットは Berkeley DB での 1 ではなく 0 から始まります。 =begin original As with normal Perl arrays, a RECNO array can be accessed using negative indexes. The index -1 refers to the last element of the array, -2 the second last, and so on. Attempting to access an element before the start of the array will raise a fatal run-time error. =end original 通常の Perl 配列と同じように、RECNO 配列には負のインデックスを 使ってアクセスすることができます。 インデックス -1 は配列の最後の要素を、 -2 は後ろから 2 番目をといったように参照します。 配列の最初よりも前の要素にアクセスしようとすると 致命的なランタイムエラーを起こします。 =head2 The 'bval' Option ('bval' オプション) =begin original The operation of the bval option warrants some discussion. Here is the definition of bval from the Berkeley DB 1.85 recno manual page: =end original bval オプションの操作はいくつかの点を保証します。 以下は Berkeley DB 1.85 recno マニュアルページからの bval の定義です: =begin original The delimiting byte to be used to mark the end of a record for variable-length records, and the pad charac- ter for fixed-length records. If no value is speci- fied, newlines (``\n'') are used to mark the end of variable-length records and fixed-length records are padded with spaces. =end original 可変長レコードため、レコードの終わりをマークするために使われる 区切りバイト、そして固定長レコードのために埋められる文字。 指定されなければ、改行("\n") が可変長レコードの終わりを示すために 使われ、固定長レコードには空白が埋められます。 =begin original The second sentence is wrong. In actual fact bval will only default to C<"\n"> when the openinfo parameter in dbopen is NULL. If a non-NULL openinfo parameter is used at all, the value that happens to be in bval will be used. That means you always have to specify bval when making use of any of the options in the openinfo parameter. This documentation error will be fixed in the next release of Berkeley DB. =end original 2 番目の文は間違っています。 実際には、dbopen での openinfo パラメータが NULL であるときだけ、bval はデフォルトで C<"\n"> となります。 NULL 以外の openinfo パラメータが使われると、bval が使われるとき、 たまたまその値になってしまいます。 つまり openinfo パラメータでオプションを使用するとき には、bval を指定しなければなりません。 このドキュメントのエラーは Berkeley DB の 次のリリースで修正されるでしょう。 =begin original That clarifies the situation with regards Berkeley DB itself. What about B? Well, the behavior defined in the quote above is quite useful, so B conforms to it. =end original Berkeley DB 自身についての状況は明らかになりました。 それでは B はどうでしょう? 上記の引用で定義されている動きはとても便利です; そこで B はこれに従っています。 =begin original That means that you can specify other options (e.g. cachesize) and still have bval default to C<"\n"> for variable length records, and space for fixed length records. =end original つまり bval を可変長レコードには "C<\n"> を、固定長レコードには 空白をデフォルトにしたまま、他のオプション(例えば cachesize)を 指定することができます。 =begin original Also note that the bval option only allows you to specify a single byte as a delimeter. =end original また bval オプションは区切りとして 1 バイトだけが指定できることにも 注意してください。 =head2 A Simple Example (簡単な例) =begin original Here is a simple example that uses RECNO (if you are using a version of Perl earlier than 5.004_57 this example won't work -- see L for a workaround). =end original 以下に RECNO を使った簡単な例を示します(もし 5.004_57 よりも前の バージョンを Perl を使っていると、このサンプルは動きません -- 解決するためには L をご覧下さい)。 use warnings ; use strict ; use DB_File ; my $filename = "text" ; unlink $filename ; my @h ; tie @h, "DB_File", $filename, O_RDWR|O_CREAT, 0666, $DB_RECNO or die "Cannot open file 'text': $!\n" ; =begin original # Add a few key/value pairs to the file $h[0] = "orange" ; $h[1] = "blue" ; $h[2] = "yellow" ; =end original # いくつかのキー/値の組をファイルに加えます $h[0] = "orange" ; $h[1] = "blue" ; $h[2] = "yellow" ; push @h, "green", "black" ; my $elements = scalar @h ; print "The array contains $elements entries\n" ; my $last = pop @h ; print "popped $last\n" ; unshift @h, "white" ; my $first = shift @h ; print "shifted $first\n" ; =begin original # Check for existence of a key print "Element 1 Exists with value $h[1]\n" if $h[1] ; =end original # キーの存在をチェックします print "Element 1 Exists with value $h[1]\n" if $h[1] ; =begin original # use a negative index print "The last element is $h[-1]\n" ; print "The 2nd last element is $h[-2]\n" ; =end original # マイナスのインデックスを使います print "The last element is $h[-1]\n" ; print "The 2nd last element is $h[-2]\n" ; untie @h ; =begin original Here is the output from the script: =end original スクリプトの出力は以下のようになります: The array contains 5 entries popped black shifted white Element 1 Exists with value blue The last element is green The 2nd last element is yellow =head2 Extra RECNO Methods (特別な RECNO メソッド) =begin original If you are using a version of Perl earlier than 5.004_57, the tied array interface is quite limited. In the example script above C, C, C, C or determining the array length will not work with a tied array. =end original 5.004_57 より前のバージョンの Perl を使っているのであれば、tie された 配列のインターフェースは非常に限定されます。 上記のスクリプト例での C, C, C, C や 長さを判定することは tie された配列ではうまく機能しません。 =begin original To make the interface more useful for older versions of Perl, a number of methods are supplied with B to simulate the missing array operations. All these methods are accessed via the object returned from the tie call. =end original 古い Perl のバージョンのための、インターフェースをより使いやすくするため、 C では、失われた配列操作をシミュレートする、いくつかのメソッドが 提供されています。 これらすべてのメソッドはtie呼び出しで返される オブジェクトを介してアクセスされます。 =begin original Here are the methods: =end original 以下のメソッドがあります: =over 5 =item B<$X-Epush(list) ;> =begin original Pushes the elements of C to the end of the array. =end original 配列の最後に C の要素を追加します。 =item B<$value = $X-Epop ;> =begin original Removes and returns the last element of the array. =end original 配列の最後の要素を削除し返します。 =item B<$X-Eshift> =begin original Removes and returns the first element of the array. =end original 配列の最初の要素を削除し返します。 =item B<$X-Eunshift(list) ;> =begin original Pushes the elements of C to the start of the array. =end original 配列の先頭に C の要素を追加します。 =item B<$X-Elength> =begin original Returns the number of elements in the array. =end original 配列の要素数を返します。 =item B<$X-Esplice(offset, length, elements);> =begin original Returns a splice of the the array. =end original 配列の splice を返します。 =back =head2 Another Example (もう1つの例) =begin original Here is a more complete example that makes use of some of the methods described above. It also makes use of the API interface directly (see L). =end original 以下に、上記で説明したメソッドのいくつかを使ったもう一つ完全な例を 示します。 これは API インターフェースも直接使っています。 (L もご覧下さい)。 use warnings ; use strict ; my (@h, $H, $file, $i) ; use DB_File ; use Fcntl ; $file = "text" ; unlink $file ; $H = tie @h, "DB_File", $file, O_RDWR|O_CREAT, 0666, $DB_RECNO or die "Cannot open file $file: $!\n" ; =begin original # first create a text file to play with $h[0] = "zero" ; $h[1] = "one" ; $h[2] = "two" ; $h[3] = "three" ; $h[4] = "four" ; =end original # 最初に、扱うテキストファイルを作成します $h[0] = "zero" ; $h[1] = "one" ; $h[2] = "two" ; $h[3] = "three" ; $h[4] = "four" ; =begin original # Print the records in order. # # The length method is needed here because evaluating a tied # array in a scalar context does not return the number of # elements in the array. =end original # レコードを順番に出力します。 # # スカラコンテキストでtieされた配列を評価しても、 # 配列の要素数を返さないので、lengthメソッドが必要です。 print "\nORIGINAL\n" ; foreach $i (0 .. $H->length - 1) { print "$i: $h[$i]\n" ; } =begin original # use the push & pop methods $a = $H->pop ; $H->push("last") ; print "\nThe last record was [$a]\n" ; =end original # push と pop メソッドを使います $a = $H->pop ; $H->push("last") ; print "\nThe last record was [$a]\n" ; =begin original # and the shift & unshift methods $a = $H->shift ; $H->unshift("first") ; print "The first record was [$a]\n" ; =end original # そして shift と unshift メソッドを使います $a = $H->shift ; $H->unshift("first") ; print "The first record was [$a]\n" ; =begin original # Use the API to add a new record after record 2. $i = 2 ; $H->put($i, "Newbie", R_IAFTER) ; =end original # レコード 2 の後に新しいレコードを追加するため API を使います。 $i = 2 ; $H->put($i, "Newbie", R_IAFTER) ; =begin original # and a new record before record 1. $i = 1 ; $H->put($i, "New One", R_IBEFORE) ; =end original # そして新しいレコードをレコード 1 の前に $i = 1 ; $H->put($i, "New One", R_IBEFORE) ; =begin original # delete record 3 $H->del(3) ; =end original # レコード 3 を削除 $H->del(3) ; =begin original # now print the records in reverse order print "\nREVERSE\n" ; for ($i = $H->length - 1 ; $i >= 0 ; -- $i) { print "$i: $h[$i]\n" } =end original # 今度は逆の順番でレコードを出力します print "\nREVERSE\n" ; for ($i = $H->length - 1 ; $i >= 0 ; -- $i) { print "$i: $h[$i]\n" } =begin original # same again, but use the API functions instead print "\nREVERSE again\n" ; my ($s, $k, $v) = (0, 0, 0) ; for ($s = $H->seq($k, $v, R_LAST) ; $s == 0 ; $s = $H->seq($k, $v, R_PREV)) { print "$k: $v\n" } =end original # 同じことをもう一度。ただし代わりに API 関数を使います。 print "\nREVERSE again\n" ; my ($s, $k, $v) = (0, 0, 0) ; for ($s = $H->seq($k, $v, R_LAST) ; $s == 0 ; $s = $H->seq($k, $v, R_PREV)) { print "$k: $v\n" } undef $H ; untie @h ; =begin original and this is what it outputs: =end original これは以下のように出力します: ORIGINAL 0: zero 1: one 2: two 3: three 4: four The last record was [four] The first record was [zero] REVERSE 5: last 4: three 3: Newbie 2: one 1: New One 0: first REVERSE again 5: last 4: three 3: Newbie 2: one 1: New One 0: first =begin original Notes: =end original 注意: =over 5 =item 1. =begin original Rather than iterating through the array, C<@h> like this: =end original 以下のように配列 C<@h> 全体を繰り返すのではなく: =begin original foreach $i (@h) =end original foreach $i (@h) =begin original it is necessary to use either this: =end original 以下のようにする必要があります: =begin original foreach $i (0 .. $H->length - 1) =end original foreach $i (0 .. $H->length - 1) =begin original or this: =end original あるいは以下のようにします: =begin original for ($a = $H->get($k, $v, R_FIRST) ; $a == 0 ; $a = $H->get($k, $v, R_NEXT) ) =end original for ($a = $H->get($k, $v, R_FIRST) ; $a == 0 ; $a = $H->get($k, $v, R_NEXT) ) =item 2. =begin original Notice that both times the C method was used the record index was specified using a variable, C<$i>, rather than the literal value itself. This is because C will return the record number of the inserted line via that parameter. =end original C メソッドが使われたときは両方ともレコードインデックス にリテラル値ではなく、変数 C<$i> が使われていることに 注意してください。 これは C はパラメータによって追加された 行のレコード番号を返すためです。 =back =head1 THE API INTERFACE (API インターフェース) =begin original As well as accessing Berkeley DB using a tied hash or array, it is also possible to make direct use of most of the API functions defined in the Berkeley DB documentation. =end original tieされたハッシュや配列を使って Berkeley DB にアクセスするだけでなく、 Berkeley DB ドキュメントで定義されてる API 関数のほとんどを 直接使うこともできます。 =begin original To do this you need to store a copy of the object returned from the tie. =end original これをするためには tie から返されるオブジェクトのコピーを 取っておく必要があります。 $db = tie %hash, "DB_File", "filename" ; =begin original Once you have done that, you can access the Berkeley DB API functions as B methods directly like this: =end original 一度そうすれば、以下のように B メソッドのように Berkeley DB API 関数に直接アクセスすることができます: $db->put($key, $value, R_NOOVERWRITE) ; =begin original B If you have saved a copy of the object returned from C, the underlying database file will I be closed until both the tied variable is untied and all copies of the saved object are destroyed. =end original B<重要:> C から返されるオブジェクトのコピーを保存した場合は、 tie された変数の結び付けがはずされ(untie)、保存されたオブジェクトが 破壊されるまで、元になっているデータベースファイルはクローズ I<されません>。 use DB_File ; $db = tie %hash, "DB_File", "filename" or die "Cannot tie filename: $!" ; ... undef $db ; untie %hash ; =begin original See L for more details. =end original 詳細については L をご覧ください。 =begin original All the functions defined in L are available except for close() and dbopen() itself. The B method interface to the supported functions have been implemented to mirror the way Berkeley DB works whenever possible. In particular note that: =end original close() と dbopen() 自身を除く L で定義された全ての関数を 利用することができます。 サポートされる関数への B メソッドインターフェースは、 可能な限り Berkeley DB の方法と同じように実装されています。 特に以下の点に注意してください: =over 5 =item * =begin original The methods return a status value. All return 0 on success. All return -1 to signify an error and set C<$!> to the exact error code. The return code 1 generally (but not always) means that the key specified did not exist in the database. =end original メソッドはステータス値を返します。 成功すれば 0 を返します。 エラーを表すためには -1 を返し、厳密なエラーコードは C<$!> に設定します。 リターンコード1は(常にではありませんが)一般的には指定されたキーが データベースに存在しないことを意味します。 =begin original Other return codes are defined. See below and in the Berkeley DB documentation for details. The Berkeley DB documentation should be used as the definitive source. =end original 他にもリターンコードが定義されています。 詳細については以下の説明および Berkeley DB ドキュメントをご覧下さい。 Berkeley DB ドキュメントが決定的な情報源です。 =item * =begin original Whenever a Berkeley DB function returns data via one of its parameters, the equivalent B method does exactly the same. =end original Berkeley DB 関数がデータをパラメータの一つを介して返すときにはいつでも、 同様の B メソッドは全く同じ名前で存在します。 =item * =begin original If you are careful, it is possible to mix API calls with the tied hash/array interface in the same piece of code. Although only a few of the methods used to implement the tied interface currently make use of the cursor, you should always assume that the cursor has been changed any time the tied hash/array interface is used. As an example, this code will probably not do what you expect: =end original あなたが注意すれば、tie されたハッシュ/配列インターフェースと API を同じプログラムの中に混ぜることもできます。 tie されたインターフェースを実装するために使われるメソッドのうち ほんの少ししかカーソルを利用しませんが、tie された ハッシュ/配列インターフェースが使われたときは、 いつもカーソルが変更されていると考えなければなりません。 例えば、このコードはたぶん期待していたようには動きません: $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE or die "Cannot tie $filename: $!" ; =begin original # Get the first key/value pair and set the cursor $X->seq($key, $value, R_FIRST) ; =end original # 最初のキー/値の組を取得し、カーソルを設定します $X->seq($key, $value, R_FIRST) ; =begin original # this line will modify the cursor $count = scalar keys %x ; =end original # この行はカーソルを変更してしまいます $count = scalar keys %x ; =begin original # Get the second key/value pair. # oops, it didn't, it got the last key/value pair! $X->seq($key, $value, R_NEXT) ; =end original # 2 番目のキー/値の組を取り出します。 # あら、そうではありません。最後のキー/値の組を取り出しました! $X->seq($key, $value, R_NEXT) ; =begin original The code above can be rearranged to get around the problem, like this: =end original この問題を回避するために上記のコードを以下のように書きかえることができます: $X = tie %x, 'DB_File', $filename, O_RDWR|O_CREAT, 0777, $DB_BTREE or die "Cannot tie $filename: $!" ; =begin original # this line will modify the cursor $count = scalar keys %x ; =end original # この行はカーソルを変更してしまいます。 $count = scalar keys %x ; =begin original # Get the first key/value pair and set the cursor $X->seq($key, $value, R_FIRST) ; =end original # 最初のキー/値の組を取得し、カーソルを設定します $X->seq($key, $value, R_FIRST) ; =begin original # Get the second key/value pair. # worked this time. $X->seq($key, $value, R_NEXT) ; =end original # 2 番目のキー/値の組を取り出します。 # 今度はうまくいきました $X->seq($key, $value, R_NEXT) ; =back =begin original All the constants defined in L for use in the flags parameters in the methods defined below are also available. Refer to the Berkeley DB documentation for the precise meaning of the flags values. =end original flag パラメータで利用できるように L で定義されている全ての定数を 以下のメソッドでも使うことができます。 flags の値の正確な意味については Berkeley DB ドキュメントをご覧下さい。 =begin original Below is a list of the methods available. =end original 利用できるメソッドの一覧を以下に示します。 =over 5 =item B<$status = $X-Eget($key, $value [, $flags]) ;> =begin original Given a key (C<$key>) this method reads the value associated with it from the database. The value read from the database is returned in the C<$value> parameter. =end original キー (C<$key>) が与えられると、このメソッドはデータベースから 関連する値を読みこみます。 データベースから読みこんだ値は C<$value>パラメータに返されます。 =begin original If the key does not exist the method returns 1. =end original キーが存在しなければ、メソッドは1を返します。 =begin original No flags are currently defined for this method. =end original このメソッドについては、現在なんの flag も拒否されません。 =item B<$status = $X-Eput($key, $value [, $flags]) ;> =begin original Stores the key/value pair in the database. =end original データベースにキー/値の組みを格納します。 =begin original If you use either the R_IAFTER or R_IBEFORE flags, the C<$key> parameter will have the record number of the inserted key/value pair set. =end original R_IAFTER または R_IBEFORE フラグを使うと、C<$key> パラメータは 挿入するキー/値の組のレコード番号を持ちます。 =begin original Valid flags are R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE and R_SETCURSOR. =end original 適切な flag は R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE, R_SETCURSOR です。 =item B<$status = $X-Edel($key [, $flags]) ;> =begin original Removes all key/value pairs with key C<$key> from the database. =end original データベースからキー C<$key> をもつ全てのキー/値の組を削除します。 =begin original A return code of 1 means that the requested key was not in the database. =end original リターンコード1は要求されたキーがデータベースに存在しなかったことを 意味します。 =begin original R_CURSOR is the only valid flag at present. =end original R_CURSOR だけがいまのことろ唯一適切な flag です。 =item B<$status = $X-Efd ;> =begin original Returns the file descriptor for the underlying database. =end original 元になっているデータベースのためのファイルディスクリプタを 返します。 =begin original See L for an explanation for why you should not use C to lock your database. =end original データベースをロックするために C を使うべきではない理由の 説明については L をご覧下さい。 =item B<$status = $X-Eseq($key, $value, $flags) ;> =begin original This interface allows sequential retrieval from the database. See L for full details. =end original このインターフェースはデータベースから順番に取り出すことを 可能にします。 完全な詳細については L をご覧下さい。 =begin original Both the C<$key> and C<$value> parameters will be set to the key/value pair read from the database. =end original C<$key> と C<$value> パラメータの両方はデータベースから 読みこまれるキー/値の組に設定されます。 =begin original The flags parameter is mandatory. The valid flag values are R_CURSOR, R_FIRST, R_LAST, R_NEXT and R_PREV. =end original flags パラメータは必須です。 適切なフラグの値は R_CURSOR, R_FIRST, R_LAST, R_NEX, R_PREVです。 =item B<$status = $X-Esync([$flags]) ;> =begin original Flushes any cached buffers to disk. =end original キャッシュされたバッファをディスクにフラッシュします。 =begin original R_RECNOSYNC is the only valid flag at present. =end original 今は R_RECNOSYNC だけが適切なフラグです。 =back =head1 DBM FILTERS (DBMフィルタ) =begin original A DBM Filter is a piece of code that is be used when you I want to make the same transformation to all keys and/or values in a DBM database. =end original DBM フィルタはコードの集まりでであり、DBM データベースの中の 全てのキーと/または値に同じ変換を行いたいと I<常に> 思っている ときに使われます。 =begin original There are four methods associated with DBM Filters. All work identically, and each is used to install (or uninstall) a single DBM Filter. Each expects a single parameter, namely a reference to a sub. The only difference between them is the place that the filter is installed. =end original DBM フィルタに関連しては四つのメソッドがあります。 全て同様に機能します。 それぞれは一つの DBM フィルタをインストール (またはアンインストール)するために使われます。 各メソッドは一つのパラメータ、つまり sub へのリファレンスを期待します。 それぞれの唯一の違いはフィルタがインストールされる場所です。 =begin original To summarise: =end original まとめると以下のようになります: =over 5 =item B =begin original If a filter has been installed with this method, it will be invoked every time you write a key to a DBM database. =end original このメソッドでフィルタがインストールされると、 DBM データベースにキーを書きこむたびに、それが呼ばれます。 =item B =begin original If a filter has been installed with this method, it will be invoked every time you write a value to a DBM database. =end original このメソッドでフィルタがインストールされると、DBM データベースに 値を書きこむたびに、それが呼ばれます。 =item B =begin original If a filter has been installed with this method, it will be invoked every time you read a key from a DBM database. =end original このメソッドでフィルタがインストールされると、DBM データベースから キーを読みこむたびに、それが呼ばれます。 =item B =begin original If a filter has been installed with this method, it will be invoked every time you read a value from a DBM database. =end original このメソッドでフィルタがインストールされると、DBM データベースから 値を読みこむたびに、それが呼ばれます。 =back =begin original You can use any combination of the methods, from none, to all four. =end original 全く無しから四つ全てまで、これらを自由に組み合わせて使うことができます。 =begin original All filter methods return the existing filter, if present, or C in not. =end original 全てのフィルタメソッドは、もしあれば既存のフィルタを、 無ければ C を返します。 =begin original To delete a filter pass C to it. =end original フィルタを削除するには C を渡してください。 =head2 The Filter (フィルタ) =begin original When each filter is called by Perl, a local copy of C<$_> will contain the key or value to be filtered. Filtering is achieved by modifying the contents of C<$_>. The return code from the filter is ignored. =end original 各フィルタがPerlから呼び出されるとき、C<$_> のローカルコピーには フィルタされるキーまたは値が入ります。 フィルタリングは C<$_> の内容を 変更することにより実現されます。 フィルタからの戻り値は無視されます。 =head2 An Example -- the NULL termination problem. (例 -- NULL終わりの問題) =begin original Consider the following scenario. You have a DBM database that you need to share with a third-party C application. The C application assumes that I keys and values are NULL terminated. Unfortunately when Perl writes to DBM databases it doesn't use NULL termination, so your Perl application will have to manage NULL termination itself. When you write to the database you will have to use something like this: =end original 以下のシナリオについて考えてみてください。 サードパーティの C アプリケーションと共有する必要がある DBM データベースを持っているとします。 その C アプリケーションは I<全ての> キーと 値は NULL で終わるものと仮定しています。 不幸にも Perl が DBM データベースに書きこむとき、NULL 終わりを使いません。 そのため、あなたの Perl アプリケーションは自分自身で NULL 終わりを 管理しなければなりません。 データベースに書きこむとき、以下のような 方法をとる必要があります: $hash{"$key\0"} = "$value\0" ; =begin original Similarly the NULL needs to be taken into account when you are considering the length of existing keys/values. =end original 同様に存在するキー/値の長さを考えるとき、NULL を考慮に入れる 必要があります。 =begin original It would be much better if you could ignore the NULL terminations issue in the main application code and have a mechanism that automatically added the terminating NULL to all keys and values whenever you write to the database and have them removed when you read from the database. As I'm sure you have already guessed, this is a problem that DBM Filters can fix very easily. =end original メインのアプリケーションプログラムでの NULL 終わり問題を無視する ことができ、データベースに書きこむときにはいつでも自動的に全ての キーと値に終わりの NULL を付与し、データベースから読みこむときには、 それらを削除するような機構を持つならば、素晴らしいことです。 既におわかりかと思いますが、この問題は DBM フィルタによって とても簡単に修正することができます。 use warnings ; use strict ; use DB_File ; my %hash ; my $filename = "/tmp/filt" ; unlink $filename ; my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH or die "Cannot open $filename: $!\n" ; =begin original # Install DBM Filters $db->filter_fetch_key ( sub { s/\0$// } ) ; $db->filter_store_key ( sub { $_ .= "\0" } ) ; $db->filter_fetch_value( sub { s/\0$// } ) ; $db->filter_store_value( sub { $_ .= "\0" } ) ; =end original # DBMフィルタのインストール $db->filter_fetch_key ( sub { s/\0$// } ) ; $db->filter_store_key ( sub { $_ .= "\0" } ) ; $db->filter_fetch_value( sub { s/\0$// } ) ; $db->filter_store_value( sub { $_ .= "\0" } ) ; $hash{"abc"} = "def" ; my $a = $hash{"ABC"} ; # ... undef $db ; untie %hash ; =begin original Hopefully the contents of each of the filters should be self-explanatory. Both "fetch" filters remove the terminating NULL, and both "store" filters add a terminating NULL. =end original できるならば各フィルタの内容は自己説明的であるべきです。 両方の "fetch" フィルタが NULL 終わりを取り除き、 両方の "store" フィルタが NULL 終わりを付与します。 =head2 Another Example -- Key is a C int. (もう一つの例 -- キーが C int) =begin original Here is another real-life example. By default, whenever Perl writes to a DBM database it always writes the key and value as strings. So when you use this: =end original 実際の場面での例をもう一つ。 デフォルトでは Perl は DBM データベースに 書きこむときはいつでも、キーと値を文字列として書きこみます。 そのため以下のようにすると: $hash{12345} = "soemthing" ; =begin original the key 12345 will get stored in the DBM database as the 5 byte string "12345". If you actually want the key to be stored in the DBM database as a C int, you will have to use C when writing, and C when reading. =end original キー12345 は 5 バイトの文字列 "12345" として DBM データベースに 格納されます。 もし本当に DBM データベースに C の int でキーを 格納したいのであれば、書きこむときに C し、読みこむときに C する必要があります。 =begin original Here is a DBM Filter that does it: =end original 以下はそれをおこなう DBM フィルタです: use warnings ; use strict ; use DB_File ; my %hash ; my $filename = "/tmp/filt" ; unlink $filename ; my $db = tie %hash, 'DB_File', $filename, O_CREAT|O_RDWR, 0666, $DB_HASH or die "Cannot open $filename: $!\n" ; $db->filter_fetch_key ( sub { $_ = unpack("i", $_) } ) ; $db->filter_store_key ( sub { $_ = pack ("i", $_) } ) ; $hash{123} = "def" ; # ... undef $db ; untie %hash ; =begin original This time only two filters have been used -- we only need to manipulate the contents of the key, so it wasn't necessary to install any value filters. =end original 今回は二つのフィルタを使いました -- キーの内容を扱うことだけが必要 だったので、値のフィルタをインストールする必要がありません。 =head1 HINTS AND TIPS (ヒントと小技) =head2 Locking: The Trouble with fd (ロック: fd でのトラブル) =begin original Until version 1.72 of this module, the recommended technique for locking B databases was to flock the filehandle returned from the "fd" function. Unfortunately this technique has been shown to be fundamentally flawed (Kudos to David Harris for tracking this down). Use it at your own peril! =end original このモジュールのバージョン 1.72 まで、B データベースをロックする ための推奨されるテクニックは、"fd" 関数から返されるファイルハンドルを flock することでした。 残念ながら、このテクニックは根本的に無効である ことが明らかになりました(これを突き止めた栄誉は David Harris にあります)。 あなた自身の責任でそれを使ってください! =begin original The locking technique went like this. =end original ロックのテクニックは以下のようなものでした。 $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0666) || die "dbcreat /tmp/foo.db $!"; $fd = $db->fd; open(DB_FH, "+<&=$fd") || die "dup $!"; flock (DB_FH, LOCK_EX) || die "flock: $!"; ... $db{"Tom"} = "Jerry" ; ... flock(DB_FH, LOCK_UN); undef $db; untie %db; close(DB_FH); =begin original In simple terms, this is what happens: =end original 簡単にいえば、このようなことが起こります: =over 5 =item 1. =begin original Use "tie" to open the database. =end original データベースをオープンするため "tie" を使ってください。 =item 2. =begin original Lock the database with fd & flock. =end original fd & flock でデータベースをロックしてください。 =item 3. =begin original Read & Write to the database. =end original データベースの読み込み & 書き込み。 =item 4. =begin original Unlock and close the database. =end original データベースのロックを解除してクローズ。 =back =begin original Here is the crux of the problem. A side-effect of opening the B database in step 2 is that an initial block from the database will get read from disk and cached in memory. =end original ここに問題の急所があります。 ステップ 2 で B をオープンする副作用 としてデータベースからの先頭ブロックはディスクから読み込まれ、 メモリにキャッシュされます。 =begin original To see why this is a problem, consider what can happen when two processes, say "A" and "B", both want to update the same B database using the locking steps outlined above. Assume process "A" has already opened the database and has a write lock, but it hasn't actually updated the database yet (it has finished step 2, but not started step 3 yet). Now process "B" tries to open the same database - step 1 will succeed, but it will block on step 2 until process "A" releases the lock. The important thing to notice here is that at this point in time both processes will have cached identical initial blocks from the database. =end original この問題の理由をわかるため、二つのプロセス "A" と "B" の両方が同じ B データベースを上記のロック手順を使って更新したいときに 何が起きるのかを考えてみましょう。 プロセス "A" が既にデータベースをオープンし、 書込ロックを持っているけれども、まだデータベースを実際には 更新していないとします(ステップ2まで終わっていても、まだ ステップ 3 を開始していません)。 そこでプロセス "B" が同じデータベースを オープンしようとします - ステップ 1 は成功します。 しかしプロセス "A" が ロックを解除するまでステップ 2 でブロックされます。 ここで気をつけなければならない重要なことは、この時点で両方のプロセスが データベースからのキャッシュされた同じ先頭ブロックを持っていることです。 =begin original Now process "A" updates the database and happens to change some of the data held in the initial buffer. Process "A" terminates, flushing all cached data to disk and releasing the database lock. At this point the database on disk will correctly reflect the changes made by process "A". =end original そしてプロセス "A" がデータベースを更新し、たまたま先頭バッファの中の データをいくらか変更したとします。 プロセス "A" が終了し、全てのキャッシュされたデータをディスクに フラッシュし、データベースロックを解除します。 この時点で、ディスク上のデータベースは プロセス "A" によって行われた変更を正しく反映しています。 =begin original With the lock released, process "B" can now continue. It also updates the database and unfortunately it too modifies the data that was in its initial buffer. Once that data gets flushed to disk it will overwrite some/all of the changes process "A" made to the database. =end original ロックが解除されると、プロセス "B" が処理を続けることができます。 それもデータベースを更新し、それも残念なことに先頭バッファにある データを変更したとします。 データがディスクにフラッシュされると、プロセス "A" がデータベースに 対して行った、一部/全ての変更を上書きしてしまいます。 =begin original The result of this scenario is at best a database that doesn't contain what you expect. At worst the database will corrupt. =end original このシナリオの結果は、最善でもデータベースには、あなたが予期している ものが入っていません。 悪ければデータベースがおかしくなっていまいます。 =begin original The above won't happen every time competing process update the same B database, but it does illustrate why the technique should not be used. =end original 上記のことは競合するプロセスが同じ B データベースを更新する 度に発生するわけではありません。 しかしなぜそのテクニックを使うべきで ないかは明らかにしています。 =head2 Safe ways to lock a database (データベースをロックする安全な方法) =begin original Starting with version 2.x, Berkeley DB has internal support for locking. The companion module to this one, B, provides an interface to this locking functionality. If you are serious about locking Berkeley DB databases, I strongly recommend using B. =end original version 2.x から、Berkeley DB は内部でロックをサポートしています。 これに親密な関係がある、B は、このロック機能への インターフェースを提供しています。 Berkeley DB データベースをロックすることに真剣であれば、 B を使うことを強く推奨します。 =begin original If using B isn't an option, there are a number of modules available on CPAN that can be used to implement locking. Each one implements locking differently and has different goals in mind. It is therefore worth knowing the difference, so that you can pick the right one for your application. Here are the three locking wrappers: =end original もし B を使うことが選択になければ、ロックを実装するために 使うことが出来る、いくつかのモジュールを CPAN から取得することができます。 それぞれは異なる方法でロックを実装し、異なるゴールを想定しています。 このため、あなたのアプリケーションにあったものを選べるように、 その違いを知ることには価値があります。 以下に三つのロックを行うラッパーを示します: =over 5 =item B =begin original A B wrapper which creates copies of the database file for read access, so that you have a kind of a multiversioning concurrent read system. However, updates are still serial. Use for databases where reads may be lengthy and consistency problems may occur. =end original マルチバージョン化された並行読み込みアクセスの一種を実現するため、 読み込みアクセスのためのデータベースファイルのコピーを作成する B ラッパー。 しかし更新はシリアルです。 読み込みが長く、一貫性の問題が起きるかもしれないデータベースに 使ってください。 =item B =begin original A B wrapper that has the ability to lock and unlock the database while it is being used. Avoids the tie-before-flock problem by simply re-tie-ing the database when you get or drop a lock. Because of the flexibility in dropping and re-acquiring the lock in the middle of a session, this can be massaged into a system that will work with long updates and/or reads if the application follows the hints in the POD documentation. =end original それが使われている間、データベースをロックしアンロックする能力を 持つ B ラッパー。 ロックを取得したり、はずすとき、データベースを 再びtieすることにより、flock の前の tie 問題を避けます。 セッションの途中でのロックを解除し、再び取得するときの柔軟性のため、 アプリケーションが POD ドキュメントにあるヒントに従えば、 長い更新そして/あるいは読み込みを行うシステムに当てはめることができます。 =item B =begin original An extremely lightweight B wrapper that simply flocks a lockfile before tie-ing the database and drops the lock after the untie. Allows one to use the same lockfile for multiple databases to avoid deadlock problems, if desired. Use for databases where updates are reads are quick and simple flock locking semantics are enough. =end original データベースをtieする前にロックファイルを単純に flock し、 untieの後にロックをはずす、非常に軽い B ラッパー。 デッドロック問題を回避するため、そうしたければ複数のデータベースに 同じロックファイルを使うことを可能にしています。 更新と読み込みが速く、単純な flock ロックのセマンティクで十分で あるデータベースで利用してください。 =back =head2 Sharing Databases With C Applications (Cアプリケーションとのデータベースの共有) =begin original There is no technical reason why a Berkeley DB database cannot be shared by both a Perl and a C application. =end original Berkeley DB データベースを Perl と C アプリケーションとで共有できないという 技術的な理由は何もありません。 =begin original The vast majority of problems that are reported in this area boil down to the fact that C strings are NULL terminated, whilst Perl strings are not. See L for a generic way to work around this problem. =end original ここで報告されている非常に大きな問題は Perl 文字列はそうでないのに、 C 文字列が NULL 終わりであるということです。 この問題を回避する一般的な方法については L をご覧下さい。 =begin original Here is a real example. Netscape 2.0 keeps a record of the locations you visit along with the time you last visited them in a DB_HASH database. This is usually stored in the file F<~/.netscape/history.db>. The key field in the database is the location string and the value field is the time the location was last visited stored as a 4 byte binary value. =end original 実際の例を以下に示します。 Netscape 2.0 は DB_HASH データベースに、あなたが訪れた場所(location)を、 あなたが最後にそこを訪れた時間とを一緒にレコードにして保存しています。 これは通常、ファイルF<~/.netscape/history.db> に格納されます。 そのデータベースのキーフィールドは場所(location)の文字列であり、 値のフィールドは最後に訪れた時刻が4バイトのバイナリ値として 格納されます。 =begin original If you haven't already guessed, the location string is stored with a terminating NULL. This means you need to be careful when accessing the database. =end original つまり場所の文字列は NULL 付きで格納されます。 データベースにアクセスするときにはこれに気をつけなければなりません。 =begin original Here is a snippet of code that is loosely based on Tom Christiansen's I script (available from your nearest CPAN archive in F). =end original 以下に部分的なプログラムを示します。 これはTom Christiansenの I スクリプトを不正確ながら ベースにしています (これはあなたに最も近いCPANアーカイブの F で取得することができます)。 use warnings ; use strict ; use DB_File ; use Fcntl ; my ($dotdir, $HISTORY, %hist_db, $href, $binary_time, $date) ; $dotdir = $ENV{HOME} || $ENV{LOGNAME}; $HISTORY = "$dotdir/.netscape/history.db"; tie %hist_db, 'DB_File', $HISTORY or die "Cannot open $HISTORY: $!\n" ;; =begin original # Dump the complete database while ( ($href, $binary_time) = each %hist_db ) { =end original # データベース全体をダンプ while ( ($href, $binary_time) = each %hist_db ) { =begin original # remove the terminating NULL $href =~ s/\x00$// ; =end original # 末尾の NULL を削除 $href =~ s/\x00$// ; =begin original # convert the binary time into a user friendly string $date = localtime unpack("V", $binary_time); print "$date $href\n" ; } =end original # バイナリの time をユーザフレントリな文字列に変換する $date = localtime unpack("V", $binary_time); print "$date $href\n" ; } =begin original # check for the existence of a specific key # remember to add the NULL if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) { $date = localtime unpack("V", $binary_time) ; print "Last visited mox.perl.com on $date\n" ; } else { print "Never visited mox.perl.com\n" } =end original # 特定のキーが存在するかをチェック # NULL を付けるのを忘れないで下さい if ( $binary_time = $hist_db{"http://mox.perl.com/\x00"} ) { $date = localtime unpack("V", $binary_time) ; print "Last visited mox.perl.com on $date\n" ; } else { print "Never visited mox.perl.com\n" } untie %hist_db ; =head2 The untie() Gotcha (untie() がしでかすこと) =begin original If you make use of the Berkeley DB API, it is I strongly recommended that you read L. =end original Berkeley DB API を使うのであれば、L を読むことを I<非常に> 強くお勧めします。 =begin original Even if you don't currently make use of the API interface, it is still worth reading it. =end original もし今のところは API インターフェースを使わないのであっても、 読む価値はあります。 =begin original Here is an example which illustrates the problem from a B perspective: =end original B の見地から問題を示す例を以下に示します: use DB_File ; use Fcntl ; my %x ; my $X ; $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_TRUNC or die "Cannot tie first time: $!" ; $x{123} = 456 ; untie %x ; tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT or die "Cannot tie second time: $!" ; untie %x ; =begin original When run, the script will produce this error message: =end original 実行すると、このスクリプトは以下のエラーメッセージを出します: Cannot tie second time: Invalid argument at bad.file line 14. =begin original Although the error message above refers to the second tie() statement in the script, the source of the problem is really with the untie() statement that precedes it. =end original 上記のエラーメッセージではスプリプトでの2 番目の tie() ステートメントを 指しているにもかかわらず、この問題の原因は本当はその前にある untie() ステートメントにあります。 =begin original Having read L you will probably have already guessed that the error is caused by the extra copy of the tied object stored in C<$X>. If you haven't, then the problem boils down to the fact that the B destructor, DESTROY, will not be called until I references to the tied object are destroyed. Both the tied variable, C<%x>, and C<$X> above hold a reference to the object. The call to untie() will destroy the first, but C<$X> still holds a valid reference, so the destructor will not get called and the database file F will remain open. The fact that Berkeley DB then reports the attempt to open a database that is already open via the catch-all "Invalid argument" doesn't help. =end original L を読んであれば既にお分かりのように、エラーは C<$X> に 格納された tie されたオブジェクトの余分な複製によって起こされています。 読んでいなければ、要するに問題は tie されているオブジェクトへの I<全ての> リファレンスが破壊されなければ、B デストラクタ DESTROY が呼ばれないということにあります。 上記のtieされた変数 C<%X> と C<$X> は両方 ともオブジェクトへのリファレンスを持っています。 untie() を呼び出すと最初のものは破壊されますが、しかし C<$X> はまだ適切なリファレンスを持っており、 そのためデストラクタは呼ばれず、F はオープンされたままです。 事実 Berkeley DB は、すでにオープンしているデータベースを 開こうとする とcatch-all な"Invalid argument"(不適切な引数)を 報告しますが、何の助けにもなりません。 =begin original If you run the script with the C<-w> flag the error message becomes: =end original このスクリプトを C<-w> フラグを付けて実行すると、以下のような エラーメッセージになります: untie attempted while 1 inner references still exist at bad.file line 12. Cannot tie second time: Invalid argument at bad.file line 14. =begin original which pinpoints the real problem. Finally the script can now be modified to fix the original problem by destroying the API object before the untie: =end original これは本当の問題を指しています。 最終的には API オブジェクトを untie の前に 破壊することにより元の問題を修正するように変更することができます: ... $x{123} = 456 ; undef $X ; untie %x ; $X = tie %x, 'DB_File', 'tst.fil' , O_RDWR|O_CREAT ... =head1 COMMON QUESTIONS (よくある質問) =head2 Why is there Perl source in my database? (私のデータベースに Perl ソースが入っているのはなぜですか?) =begin original If you look at the contents of a database file created by DB_File, there can sometimes be part of a Perl script included in it. =end original DB_File によって作成されたデータベースの中身を見ると、その中に Perl スクリプトの一部が入っていることがあります。 =begin original This happens because Berkeley DB uses dynamic memory to allocate buffers which will subsequently be written to the database file. Being dynamic, the memory could have been used for anything before DB malloced it. As Berkeley DB doesn't clear the memory once it has been allocated, the unused portions will contain random junk. In the case where a Perl script gets written to the database, the random junk will correspond to an area of dynamic memory that happened to be used during the compilation of the script. =end original これは Berkeley DB が、後でデータベースファイルに書きこまれるバッファを 取るために動的メモリを使っているためです。 動的であるために、メモリは DB が malloc する前に 使われていたままになります。 Berkeley DB はアロケートされたメモリをクリアしないので、 使われない部分にはデタラメなゴミが入っています。 Perl スクリプトがデータベースに書き込まれている場合、 そのデタラメなゴミが、スクリプトをコンパイルするとき、たまたま使われた 動的メモリの領域に対応していたのでしょう。 =begin original Unless you don't like the possibility of there being part of your Perl scripts embedded in a database file, this is nothing to worry about. =end original Perl スクリプトの一部だけでもデータベースファイル埋め込まれるかもしれないと いうことが嫌でなければ、何も心配することはありません。 =head2 How do I store complex data structures with DB_File? (DB_File に複雑なデータ構造を格納するにはどうすればいいですか?) =begin original Although B cannot do this directly, there is a module which can layer transparently over B to accomplish this feat. =end original B は直接これをできませんが、この機能を実現するため B の 上に透過的に重ねることのできるモジュールがあります。 =begin original Check out the MLDBM module, available on CPAN in the directory F. =end original CPAN の F ディレクトリから取得できる MLDBM モジュールを試してみてください。 =head2 What does "Invalid Argument" mean? ("Invalid Argument" ってどういう意味ですか?) =begin original You will get this error message when one of the parameters in the C call is wrong. Unfortunately there are quite a few parameters to get wrong, so it can be difficult to figure out which one it is. =end original C の呼び出しでパラメータの一つが間違っていると、このエラーメッセージを 取得します。 残念ながらパラメータが間違うことはあまりないので、 それが難なのかを発見することは難しいかもしれません。 =begin original Here are a couple of possibilities: =end original 以下にいくつかの可能性をしめします: =over 5 =item 1. =begin original Attempting to reopen a database without closing it. =end original データベースをクローズなしに再オープンしようとした。 =item 2. =begin original Using the O_WRONLY flag. =end original O_WRONLY フラグを使っている。 =back =head2 What does "Bareword 'DB_File' not allowed" mean? ("Bareword 'DB_File' not allowed"ってどういう意味ですか?) =begin original You will encounter this particular error message when you have the C pragma (or the full strict pragma) in your script. Consider this script: =end original この特定のエラーメッセージは、スクリプトの中に C プラグマ (あるいはすべての strict プラグマ)があるときに発生します。 以下のスクリプトについて考えてみてください: use warnings ; use strict ; use DB_File ; my %x ; tie %x, DB_File, "filename" ; =begin original Running it produces the error in question: =end original これを実行すると質問のエラーを起こします: Bareword "DB_File" not allowed while "strict subs" in use =begin original To get around the error, place the word C in either single or double quotes, like this: =end original このエラーを回避するには、以下のように C という単語をシングル またはダブルクォートの中に入れてください: tie %x, "DB_File", "filename" ; =begin original Although it might seem like a real pain, it is really worth the effort of having a C in all your scripts. =end original これはかなりの苦痛に見えますが、C をあなたの全てのスクリプトに 入れようとすることは本当に価値のあることです。 =head1 REFERENCES (参考文献) =begin original Articles that are either about B or make use of it. =end original B やその使い方についての記事は以下の通り。 =over 5 =item 1. I, Tim Kientzle (tkientzle@ddj.com), Dr. Dobb's Journal, Issue 295, January 1999, pp 34-41 =back =head1 HISTORY =begin original Moved to the Changes file. =end original Changes ファイルに移動しました。 =head1 BUGS =begin original Some older versions of Berkeley DB had problems with fixed length records using the RECNO file format. This problem has been fixed since version 1.85 of Berkeley DB. =end original 以前のいくつかの Berkeley DB は、RECNO ファイルフォーマットを使った 固定長レコードで問題がありました。 この問題は Berkeley DB の バージョン 1.85 から修正されています。 =begin original I am sure there are bugs in the code. If you do find any, or can suggest any enhancements, I would welcome your comments. =end original このプログラムにバグがあると思っています。 何か見つけたら、あるいは拡張についてなにか提案できるのであれば、 コメントをお待ちしています。 =head1 AVAILABILITY (可用性) =begin original B comes with the standard Perl source distribution. Look in the directory F. Given the amount of time between releases of Perl the version that ships with Perl is quite likely to be out of date, so the most recent version can always be found on CPAN (see L for details), in the directory F. =end original B は標準の Perl source ディストリビューションと一緒に入ります。 F をご覧下さい。 Perl といっしょに出されたバージョンの リリースからの時間のために古くなっているかもしれません。 そこで最新のバージョンは常に CPAN(詳細については L をご覧下さい)のディレクトリ F で 取得することができます。 =begin original This version of B will work with either version 1.x, 2.x or 3.x of Berkeley DB, but is limited to the functionality provided by version 1. =end original このバージョンの B は Berkeley DB の 1.x, 2.x, 3.x のいずれでも 動きます。 しかしバージョン 1 によって提供されている機能に限定されます。 =begin original The official web site for Berkeley DB is F. All versions of Berkeley DB are available there. =end original Berkeley DB の公式ウェブサイトは F です。 そこではすべてのバージョンの Berkeley DB を取得することができます。 =begin original Alternatively, Berkeley DB version 1 is available at your nearest CPAN archive in F. =end original あるいは、Berkeley DB バージョン 1 は最寄りの CPAN アーカイブでの F で取得できます。 =begin original If you are running IRIX, then get Berkeley DB version 1 from F. It has the patches necessary to compile properly on IRIX 5.3. =end original IRIX を使っているのであれば、Berkeley DB バージョン 1 を F で取得することができます。 IRIX 5.3 で適切にコンパイルするために必要なパッチが入っています。 =head1 COPYRIGHT Copyright (c) 1995-2002 Paul Marquess. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =begin original Although B is covered by the Perl license, the library it makes use of, namely Berkeley DB, is not. Berkeley DB has its own copyright and its own license. Please take the time to read it. =end original B は Perl ライセンスによってカバーされますが、これが使用する ライブラリ、つまり Berkeley DB はそうではありません。 Berkeley DB はそれ自身の著作権と独自のライセンスを持っています。 それを読んでください。 =begin original Here are are few words taken from the Berkeley DB FAQ (at F) regarding the license: =end original Berkeley DB FAQ (F) からライセンスについての 一部を示します: =begin original Do I have to license DB to use it in Perl scripts? =end original Perl スクリプトで使うために DB をライセンスする必要がありますか? =begin original No. The Berkeley DB license requires that software that uses Berkeley DB be freely redistributable. In the case of Perl, that software is Perl, and not your scripts. Any Perl scripts that you write are your property, including scripts that make use of Berkeley DB. Neither the Perl license nor the Berkeley DB license place any restriction on what you may do with them. =end original いいえ。 Berkeley DB ライセンスは Berkeley DB を利用するソフトウェアは、 自由に再配布可能であることを必要とします。 Perl の場合、つまりソフトウェアは Perl であり、あなたの スクリプトではありません。 あなたが書いた全ての Perl スクリプトは Berkeley DB を使ったものも 含めて、あなたの資産です。 Perl ライセンスも Berkeley DB ライセンスも あなたがそれらを使ってできることを何ら制限しません。 =begin original If you are in any doubt about the license situation, contact either the Berkeley DB authors or the author of DB_File. See L<"AUTHOR"> for details. =end original もしライセンスの状況に疑問があれば、Berkeley DB の作者あるいは DB_File の 作者にコンタクトしてください。 下記の L<"AUTHOR"> をご覧ください。 =head1 SEE ALSO L, L, L, L, L, L =head1 AUTHOR =begin original The DB_File interface was written by Paul Marquess EPaul.Marquess@btinternet.comE. Questions about the DB system itself may be addressed to Edb@sleepycat.com. =end original DB_File インターフェースは Paul Marquess EPaul.Marquess@btinternet.comE によって作成されました。 DB システムそのものについての疑問は Edb@sleepycat.com にお願いします。 =cut