FreeBSD の LIBTP (db ライブラリ) のサンプルプログラム

OS レベルの Unix でファイルにアクセスする方法としては、

  1. read()/write() によるシーケンシャルアクセス
  2. lseek() と read()/write() によるランダムアクセス
の二つがありますが、 アプリケーションレベルのランダムアクセスでは、ほとんどの場合、lseek() の実行前に検索キーからデータ格納位置を求める作業が必要で、 この対応をインデックスファイルに格納し、 それを使って検索キー(search key)からレコード格納位置をすばやく求める システムを用意しておく必要があります。

Unix V7, System III 時代には利用者が自分でこのためのツール (注1) を書いていましたが、 現在では BSD Unix の時代に生まれた

LIBTP: Portable, Modular Transactions for UNIX

が FreeBSD などに標準で入っていて、 特殊な場合以外は自作の必要がなくなりました。 (注2)

ただ、 dbopen(3), btree(3), hash(3), mpool(3), recno(3) といったマニュアルだけだと、 わかりにくいと思いますので、 簡単なサンプルプログラムを用意してみました。

このサンプルプログラムは、下記形式の実用的なレコード構造を前提にしています。

  キー データ
  ..
すなわち、レコードセパレータ(record separator)が改行文字、 フィールドセパレータ(field separator)が空白文字で、 キーはレコードの先頭フィールドです。

使い方は次のとおりです。


コマンド       create - レコード登録
構文           create [オプション] [データベース]
オプション     -c                  # 新しいデータベースを作成
例             create -c stock     # 新しい stock.db を作成
               create stock        # 既存の stock データベースにレコードを追加
-c を指定すると、同じ名前のデータベースがあれば全データを削除し、なければ新
しいデータベースを作成したうえで、標準入力から読み取ったレコードを追加して
ゆきます。-c の指定がなければ、既存のデータベースに標準入力から読み取ったレ
コードを追加します。データベースの指定を省略すると test、データベースファイ
ルの拡張子は .db になります。

コマンド       seq - シーケンシャルアクセス
構文           seq [オプション] [データベース]
オプション     なし
例             seq stock        # stock.db のレコードをシーケンシャル表示
指定されたデータベースのレコードをシーケンシャルに表示します。データベース
の拡張子 .db は省略します。

コマンド       rand - ランダムアクセス
構文           rand [オプション] [データベース]
オプション     なし
例             rand stock        # stock データベースのランダムアクセス
指定されたデータベースをオープンし、標準入力から読み取った検索キーのレコー
ゆきます。-c の指定がなければ、既存のデータベースに標準入力から読み取ったレ
ドを表示します。データベースの拡張子 .db は省略します。

コマンド       del - レコード削除録
構文           del [オプション] [データベース]
オプション     なし
例             del stock        # 既存の stock データベースからレコードを削除
指定されたデータベースから、標準入力から読み取ったレコードを削除します。デー
タベースの指定を省略すると test、データベースの拡張子 .db は省略します。

注1 - キーの高速検索

検索キーとデータ格納位置の対を先頭から順次みてゆく方法だと時間がかかりますし、 無駄が多いですから、通常は下記のような方法を使います。

アルゴリズムの文献には必ずこれらの解説がありますので、 詳細は専門書をご欄いただくとして、 最も用途の広い手法がB-treeですから、 このプログラム例ではB-treeを使いますが、 LIBTPではhashなど、いくつかの手法が選択できるようになっています。

自動倉庫とか固定棚の置場所のように検索キーが論理的に限られている場合は、 キーの値を直接データ格納位置に変換する関数を作ることができますから、 こういった検索アルゴリズム自体が不要になることもあります。

注2 - FreeBSD-8.4Berkeley DB

FreeBSD-8.4 の場合は Berkeley DB version 1.85 が使われていて、 ソースコードは

  /usr/src/lib/libc/db
ドキュメントは
 /usr/src/lib/libc/db/docs
にあります。

著者による解説は http://www.aosabook.org/en/bdb.html を御覧ください。