tyserv-2.4 -- DBMS for UNIX-like systems(Linux,FreeBSD,Cygwin etc)

参照回数[counter]

ENGLISH?

紹介

tyserv はUNIX系OSで利用することを念頭に開発しているデータベースマ ネージャです。tyserv はその基本エンジン部分に Typhoon Relational Database Management System v1.11.0 を使用しています。tyserv の提供する主な機能は以下のものです。
  1. ソケットインターフェースを利用したネットワーク越しのアクセス機能
  2. 障害に備えたジャーナルファイル(ロールバック、リカバリ)取得機能
  3. 排他制御機能
  4. トランザクション機能
  5. DB復旧機能(リカバリジャーナルによる)
  6. IPアドレスによるアクセス制限機能(/etc/hosts.allow, /etc/hosts.denyによる)
  7. ユーザ認証によるアクセス制限機能(/home/tyserv/tyserv/etc/passwdによる)

また、 専用掲示板 を用意しましたので、こちらのほうもご利用ください。

作者の思い(^^;

現時点で既に「Apache + PHP + PostgreSQL」みたいな、かゆいところに手の届く 気持良く便利な「まごの手」があるのになぜあえてこのような物を作ってるのか?...。

「まごの手」は確かに便利な物なんですが、たまには「直接手で」掻きむしる あの感覚も忘れたくない、そんな事ってないですか?、いやあって欲しい...。

という訳で、いまだに「COBOL + VSAM(or VSAS)索引順編成」、「 C + C-ISAM」 等の言葉に反応してしまうそこのあなたにこそ「tyserv」は有るのです。あっ、 でもそれ以外の人もつかってね...。

ダウンロード

インストール

  1. システムにユーザ tyserv を追加する
  2. ユーザ tyserv 用にホームディレクトリ /home/tyserv を作成する
  3. tyserv でログインする
  4. tyserv-2.4 を展開する
  5. PATH に ${HOME}/typhoon/bin, ${HOME}/tyserv/bin を追加する
    ex. (/home/tyserv/.profile etc)
  6. ユーザ tyserv で再度ログインする(上記の設定を有効にする)
  7. typhoon-1.11.0 をインストールする
  8. データベース定義ファイル(typhoondb.ddl)からデータベース定義 (typhoondb.dbd)を生成する。この定義にはサンプルのテーブル(smp1,smp2) の定義が含まれる。
  9. インポートコマンドファイル、エクスポートコマンドファイルを作成する
  10. データベースサーバ本体の tyserv を生成する(あらかじめ libwrap を インストールしておいて下さい)
  11. 起動スクリプト rc.tyserv を適切なディレクトリへコピーする
  12. ブート時に起動スクリプトが動くように設定する
      ex. (/etc/rc.d/rc.local etc)
          if [ -x /etc/rc.d/rc.tyserv ]; then
              . /etc/rc.d/rc.tyserv -d /home/tyserv/rundir1
          fi
      
  13. 必要に応じてコンフィグファイル /home/tyserv/rundir1/conf/tyserv.conf を編集する
  14. システムをリブートする
  15. ユーザ tyserv でログインする
  16. サンプルスクリプトを動かして動作確認を行う(perl版)
  17. サンプルスクリプトを動かして動作確認を行う(open-cobol版)
  18. 本番運用に備えて
  19. トランザクションのバッチ実行ツール(tytran.sh)インストール

コンフィグファイル(/home/tyserv/rundir1/conf/tyserv.conf)のパラメータ

tyserv へのアクセス方法

tyserv の開いているソケットポートにコマンドを書き込んで、同一ポートから 結果を読み取ることでアクセスを行います。よって、ソケット通信をサポート する全ての言語から tyserv へのアクセスを行うことが出来るはずです。簡単 な話し telnet でアクセス出来ます(実用的かは別にして(^^;)。

また、perl用のアクセスライブラリ tyserv/sample/perl/tyserv.pl 及び open-cobol用インターフェース tyserv/sample/open-cobol/tycob.c を用意してます。 使い方は tyserv/sample/perl 及び tyserv/sample/open-cobol 以下のプログラ ムを参照して下さい。

各コマンドのトークンの区切り文字はタブ(0x09)です。

さらなる情報は tyserv/doc/*, tyserv/sample/perl/*.pl を参照して下さい。

tyserv への telnet でのアクセス例

$ telnet localhost 20000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
start_tran	user	user				<-Input
OK	TRANSACTION START				<-Response
put	smp1	id=1111	name=Taro	salary=150000	<-Input
OK	INSERTED					<-Response
put	smp1	id=2222	name=Jiro	salary=200000	<-Input
OK	INSERTED					<-Response
put	smp1	id=3333	name=Goro	salary=250000	<-Input
OK	INSERTED					<-Response
commit							<-Input
OK      COMMITED					<-Response
get	smp1	pkey	eq	1111			<-Input
OK	FOUND	id=1111	name=Taro	salary=150000	<-Response
getnext	smp1	pkey					<-Input
OK	FOUND	id=2222	name=Jiro	salary=200000	<-Response
getnext	smp1	pkey					<-Input
OK	FOUND	id=3333	name=Goro	salary=250000	<-Response
update	smp1	2222	name=Jirorin			<-Input
OK	UPDATED						<-Response
get	smp1	pkey	eq	2222			<-Input
OK	FOUND	id=2222	name=Jirorin	salary=200000	<-Response
delete	smp1	2222					<-Input
OK	DELETED						<-Response
get	smp1	pkey	eq	2222			<-Input
NG	NOTFOUND					<-Response
rollback						<-Input
OK	ROLLBACKED					<-Response
get	smp1	pkey	eq	2222			<-Input
OK	FOUND	id=2222	name=Jiro	salary=200000	<-Response
end_tran						<-Input
OK	TRANSACTION END					<-Response
Connection closed by foreign host.

perl用アクセスライブラリ(tyserv.pl)利用例

tyservへのアクセス部分だけに焦点をしぼったコーディング例ですので エラー対応のコーディングは一切省いています。御了承下さい。
#! /usr/bin/perl
#---------------------------------------------------------
# ソケット通信ライブラリ読み込み
use IO::Socket;
#
# tyservアクセスライブラリ読み込み
require 'tyserv.pl';
#---------------------------------------------------------
# ユーザ名設定
$user = "manager";
#
# パスワード設定
$passwd = "manager";
#
# ホスト名設定
$host = "localhost";
#
# ポート番号設定
$port = 20000;
#---------------------------------------------------------
# ソケットハンドル取得
$handle = IO::Socket::INET->new(Proto     => "tcp",
                                PeerAddr  => $host,
                                PeerPort  => $port);
#
# ソケットハンドルの自動フラッシュ設定
$handle->autoflush(1); # so output gets there right away
#---------------------------------------------------------
# 更新トランザクション開始
($sts1, $sts2) = &ty_start_tran($handle, $user, $passwd);
#---------------------------------------------------------
# レコード内容初期化
%rec = ();
#
# レコード内容設定
$rec{id} = "9999";
$rec{name} = "Mr. X";
$rec{salary} = 900000;
#
# レコード書き込み
($sts1, $sts2) = &ty_put($handle, "smp1", \%rec);
#---------------------------------------------------------
# レコード内容初期化
%rec = ();
#
# レコード読み込み
($sts1, $sts2, %rec) = &ty_get($handle, "smp1", "pkey", "eq", ["9999"]);
#---------------------------------------------------------
# レコード項目更新
$rec{salary} *= 10;
#
# レコード更新
($sts1, $sts2) = &ty_update($handle, "smp1", ["9999"], \%rec);
#---------------------------------------------------------
# レコード削除
($sts1, $sts2) = &ty_delete($handle, "smp1", ["9999"]);
#---------------------------------------------------------
# トランザクション終了
($sts1, $sts2) = &ty_end_tran($handle);
#---------------------------------------------------------
# プログラム終了
exit 0;

perl用アクセスライブラリ(tyserv.pl)利用例(2)

open-cobol用アクセスインターフェース(tycob.c)利用例

tyservへのアクセス部分だけに焦点をしぼったコーディング例ですのでエラ ー対応のコーディングは一切省いています。御了承下さい。
       IDENTIFICATION   DIVISION.
       PROGRAM-ID.      sample1.
       ENVIRONMENT      DIVISION.
      *------------------------------------------
      * 作業領域定義
      *------------------------------------------
       WORKING-STORAGE  SECTION.
      *------------------------------------------
      * 定数定義
      *------------------------------------------
       01 C-NULL        PIC X(1) VALUE LOW-VALUE.
       01 C-TAB         PIC X(1) VALUE X'09'.
      *------------------------------------------
      * ワーク定義
      *------------------------------------------
      *
      * sock_* 関係インターフェース項目
      *
       01 HOST.
          02 FILLER     PIC X(9) VALUE 'localhost'.
          02 FILLER     PIC X(1) VALUE LOW-VALUE.
       01 PORT.
          02 FILLER     PIC X(5) VALUE '20000'.
          02 FILLER     PIC X(1) VALUE LOW-VALUE.
       01 FD-SOCK.
          02 FILLER     PIC X(5) VALUE SPACE.
          02 FILLER     PIC X(1) VALUE LOW-VALUE.
       01 SEND-DATA.
          02 FILLER     PIC X(1024) VALUE SPACE.
          02 FILLER     PIC X(1) VALUE LOW-VALUE.
       01 RECV-DATA.
          02 FILLER     PIC X(1024) VALUE SPACE.
          02 FILLER     PIC X(1) VALUE LOW-VALUE.
      *
      * get_* 関係インターフェース項目
      *
       01 STAT1         PIC X(2) VALUE SPACE.
       01 STAT2         PIC X(1024) VALUE SPACE.
       01 G-ID          PIC X(4).
       01 G-NAME        PIC X(20).
       01 G-SALARY      PIC 9(7).
      *------------------------------------------
      * 処理開始
      *------------------------------------------
       PROCEDURE        DIVISION.
      *
       MAIN-EN.
      *
      * ソケットオープン
      *
         CALL 'sock_open' USING HOST PORT FD-SOCK.
      *
      * 更新モードトランザクション開始
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'start_tran' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'user' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'user' DELIMITED BY SIZE
                C-NULL DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * 挿入
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'put' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'smp1' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'id=9999' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'name=Mr. X' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'salary=0900000' DELIMITED BY SIZE
                C-NULL DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * 検索
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'get' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'smp1' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'pkey' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'eq' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                '9999' DELIMITED BY SIZE
                C-NULL DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * 項目(SALARY)を更新
      *
         INITIALIZE G-ID G-NAME G-SALARY.
         CALL 'get_value' USING RECV-DATA 'id' G-ID.
         CALL 'get_value' USING RECV-DATA 'name' G-NAME.
         CALL 'get_value' USING RECV-DATA 'salary' G-SALARY.
         COMPUTE G-SALARY = G-SALARY * 10.
      *
      * 更新
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'update' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'smp1' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                G-ID DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'salary=' DELIMITED BY SIZE
                G-SALARY DELIMITED BY SIZE
                C-NULL DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * 削除
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'delete' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                'smp1' DELIMITED BY SIZE
                C-TAB DELIMITED BY SIZE
                '9999' DELIMITED BY SIZE
                C-NULL DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * トランザクション終了
      *
         INITIALIZE SEND-DATA RECV-DATA STAT1 STAT2.
         STRING 'end_tran' DELIMITED BY SIZE
                INTO SEND-DATA.
         CALL 'sock_send_recv' USING FD-SOCK SEND-DATA RECV-DATA.
         CALL 'get_status' USING RECV-DATA STAT1 STAT2.
      *
      * ソケットクローズ
      *
         CALL 'sock_close' USING FD-SOCK.
       MAIN-EX.
         STOP RUN.
      *------------------------------------------
      * 処理終了
      *------------------------------------------

プログラミングの注意点

アクセス状態コード

STS1STS2
OKCOMMITED
OKCOMMITED BUT RECOVERY JOURNAL OVERFLOW
OKDELETED
OKFOUND
OKINSERTED
OKNORMAL SHUTDOWN
OKROLLBACKED
OKSWAPRVJ TO full_path_of_recovery_journal
OKTRANSACTION ABORT, ROLLBACKED
OKTRANSACTION END
OKTRANSACTION END BUT RECOVERY JOURNAL OVERFLOW
OKTRANSACTION START
OKUPDATED
NGACCESS DENIED(ip address)
NGCAN NOT OPEN DATABASE db_status=xxxx
NGCAN NOT READ SOCKET
NGDUPLICATE
NGNO RECOVERY JOURNAL
NGNO ROLLBACK JOURNAL
NGNOT GRANTED
NGNOTFOUND
NGRECOVERY JOURNAL OVERFLOW
NGREQUIRE START_TRAN OR START_TRAN_NJ OR START_TRANM
NGROLLBACK JOURNAL OVERFLOW
NGSOCKET READ ERROR
NGSOCKET READ ERROR, ROLLBACKED
NGSTATUS=xxxx
NGUNKNOWN CONDITION
NGUNKNOWN FUNCTION
NGUNKNOWN ITEM
NGUNKNOWN KEY
NGUNKNOWN RECORD

データベース定義(typhoondb.ddl)の掟

 1 database typhoondb {
 2     data file "smp1.dat"   contains  smp1;
 3     key  file "smp1.pk"    contains  smp1.smp1_pkey;
 4     key  file "smp1.s1"    contains  smp1.smp1_skey1;
 5     record smp1 {
 6         char id[4 + 1];
 7         char name[20 + 1];
 8         char salary[7 + 1];
 9         primary   key smp1_pkey  { id asc };
10         alternate key smp1_skey1 { name asc, id asc };
11     }
12 }

解説

 1 データベース定義の開始文
   database データベース名 {

   o データベース名は「typhoondb」に限る

 2 データ格納ファイル指定文
   data file "ファイル名" contains テーブル名;

   o ファイル名は「テーブル名.dat」に限る

 3 主キー格納ファイル指定文
   key  file "ファイル名" contains テーブル名.テーブル名_pkey;

   o 主キーはテーブルに1個のみ存在できる
   o ファイル名は「テーブル名.pk」に限る

 4 副キー格納ファイル指定文
   key  file "ファイル名" contains テーブル名.テーブル名_skey連番;

   o 副キーはテーブルに複数個存在できる
   o ファイル名は「テーブル名.s連番」に限る
   o 連番は1から順に副キー毎に符番する

 5 テーブル定義開始文
   record テーブル名 {

 6 項目定義文
 7 項目定義文
 8 項目定義文
   char 項目名[項目長 + 1];

   o 属性は「char」のみ指定できる

 9 主キー定義文
   primary key テーブル名_pkey { 項目名 並び順[, 項目名 並び順] ... };

   o 主キーはテーブルに1個のみ存在できる
   o 主キーはレコードをユニークに特定できる項目で構成しなければならない
   o 並び順は昇順の場合は「asc」、降順の場合は「desc」

10 副キー定義文
   alternate key テーブル名_skey連番 { 項目名 並び順[, 項目名 並び順] ... };

   o 副キーはテーブルに複数個存在できる
   o 副キーは重複を許す。但し、重複キーを持つレコードの並び順が不定なのは
    不安なので(^^;、主キーの構成項目を末尾に追加することを推奨します
   o 連番は1から順に副キー毎に符番する

11 テーブル定義の終了
   }

12 データベース定義の終了
   }

インポートスクリプト(tyimp)の利用例

エクスポートスクリプト(tyexp)の利用例

tyserv 再生成

起動スクリプト(rc.tyserv)

サーバは自動的にバックグラウンドで実行されます。

データベース復旧ツール(tyrecover.sh)

マルチサーバ構成

tyservは排他の単位がデータベースなので、排他モードの トランザクション実行時に全てのテーブルに排他がかかります。 これは、一つの tyserv プロセスが全てのクライアントからの更 新トランザクションを受け付け、処理することで共有そのものを 避ける方法で排他制御を行っている(というか行わずにすましてる というか...)為にしかたのないことです(^^;。

そこでtyserv-2.xではデータベースに含まれるテーブルを幾つかのグループ に分けて、そのグループ毎に別々のサーバを起動することで排他の 粒度を細かくできるように拡張を行いました。

tysearch(検索コマンド)実行例

シェルから検索するためのコマンドを提供します。本コマンドは直接 データベースをアクセスするので、サーバが起動していなくても使用 できますが、当然トランザクション管理の範囲外で動作しますので、 その点御理解頂いた上で利用して下さい。
$ tysearch -h  <-- ヘルプの表示
usage : tysearch table start_count rec_count key_name key_value ...
environment value : TYPHOON_DIR

$ tysearch smp1 1 3 pkey 0003  <-- テーブルsmp1のpkeyが0003以上のレコードに位置付け、1件目から3レコードをstdoutに出力する
OK      FOUND   id=0003 name=Kiyoshi Sakamoto   salary=0510000
OK      FOUND   id=0004 name=Masaharu Sawada    salary=0470000
OK      FOUND   id=0005 name=Masahiko Ito       salary=0300000
$

tytran.sh(トランザクションバッチ実行ツール)実行例

シェルからトランザクションを実行するためのツールを提供します。本コマンド はトランザクション管理の範囲内で動作しますので、サーバ起動中でないと実行 出来ません。また、バッチ処理という性質上、長時間のデータ更新の場合データ ベースを排他的に占有する時間も長くなるので、必要に応じてEND_TRANを発行し てトランザクションを分割し、小まめに排他を開放することをお勧めします。

本コマンドはユーザ tyserv 以外でも実行できます。

$ tytran.sh -h  <-- ヘルプの表示
usage : tytran.sh [-s server|--server server] [-p port|--port port] [-n|--ngexit] [-v|--verbose]
 execute transaction in batch mode
 option : -s server       connect to server. default localhost.
          -p port         connect to port. default 20000.
          -n, --ngexit    exit when NG status
          -v, --verbose   verbose mode

$ vi trancmd.txt
#
# 先頭が `#' はコメント行
#
START_TRAN	USER	USER
GET	smp1	pkey	eq	0001
UPDATE	smp1	0001	salary=9999999
COMMIT
END_TRAN

$ tytran.sh <trancmd.txt

Cygwin 対応

typhoon-1.11.0.patch の代わりに typhoon-1.11.0.cygwin.patch を利用する 事でMS-Windows上のCygwin環境でtyservを利用することが出来ます。 その際には、tyservのmakeにはMakefile.cygwinを利用して下さい。 また、本パッチを当てることでtyphoon-1.11.0が本来持ってる排他制御機能は 無効になるので注意して下さい。

特に、既にtyphoon-1.11.0を利用したアプリケーションを作成されてる場合は 本パッチの利用は避けられたほうが良いでしょう。

FreeBSD 対応

typhoon-1.11.0.patch の代わりに typhoon-1.11.0.FreeBSD.patch を利用する 事でFreeBSD環境でtyservを利用することが出来ます。その際には、tyservの Makefile中のLIBSマクロに -lcompat を追加してください。

TODO & BUGS

typhoon-1.11.0の情報


Masahiko Ito <m-ito@mbox.kyoto-inet.or.jp>