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

Counter[counter]

JAPANESE

Introduction

tyserv is DBMS for UNIX-like systems.
tyserv use Typhoon Relational Database Management System v1.11.0 as core engine.
tyserv provide following feature.
  1. access from network by socket interface.
  2. logging journal for rollback and rollforward.
  3. exclusive locking mechanism.
  4. transaction mechanism.
  5. rollforward utility.
  6. access control by libwrap, /etc/hosts.allow, /etc/hosts.deny.
  7. user authentication by /home/tyserv/tyserv/etc/passwd.

and here is BBS for tyserv. use it in a carefree :-)

If you like old but simple database programming environments like COBOL+VSAM(KSDS) or C+C-ISAM, you will like tyserv too ;-)

download

Install

  1. add user `tyserv' to /etc/passwd
  2. mkdir /home/tyserv; chown tyserv.users /home/tyserv
  3. login as tyserv
  4. extract tyserv-2.4
  5. add ${HOME}/typhoon/bin, ${HOME}/tyserv/bin into PATH
    ex. (/home/tyserv/.profile etc)
  6. re-login as tyserv
  7. install typhoon-1.11.0
  8. generate database definition(typhoondb.dbd) from database definition language(typhoondb.ddl). this definition include sample table(smp1, smp2).
  9. create import command file and export command file.
  10. make tyserv (you need libwrap).
  11. copy rc.tyserv into right directory.
  12. edit boot script to execute tyserv at boot time.
      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. edit config file(/home/tyserv/rundir1/conf/tyserv.conf), if you need.
  14. reboot system.
  15. login as tyserv.
  16. execute sample script for perl, if you want.
  17. execute sample script for OpenCOBOL, if you want.
  18. ready to production run.
  19. transaction tool in batch mode (tytran.sh)

parameters in config file(/home/tyserv/rundir1/conf/tyserv.conf)

how to access tyserv

it's simple that write command into socket port which tyserv open, and get result from same port. so you can access tyserv from all programming language which support socket interface.

access library(tyserv/sample/perl/tyserv.pl) is ready for perl.
c interface(tyserv/sample/open-cobol/tycob.c) is ready for OpenCOBOL.
see tyserv/sample/perl/*, tyserv/sample/open-cobol/* to use tyserv.pl or tycob.c.

command token is separated by TAB(0x09).

see tyserv/doc/*, tyserv/sample/perl/*.pl to get more information.

sample access to tyserv by 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.

sample to use tyserv.pl from perl.

#! /usr/bin/perl
#---------------------------------------------------------
# socket communication library
use IO::Socket;
#
# tyserv access library
require 'tyserv.pl';
#---------------------------------------------------------
# user name
$user = "manager";
#
# password
$passwd = "manager";
#
# host name
$host = "localhost";
#
# port number
$port = 20000;
#---------------------------------------------------------
# get socket handle
$handle = IO::Socket::INET->new(Proto     => "tcp",
                                PeerAddr  => $host,
                                PeerPort  => $port);
#
# set autoflush socket
$handle->autoflush(1); # so output gets there right away
#---------------------------------------------------------
# update transaction start
($sts1, $sts2) = &ty_start_tran($handle, $user, $passwd);
#---------------------------------------------------------
# initialize record
%rec = ();
#
# set record
$rec{id} = "9999";
$rec{name} = "Mr. X";
$rec{salary} = 900000;
#
# insert record
($sts1, $sts2) = &ty_put($handle, "smp1", \%rec);
#---------------------------------------------------------
# initialize record
%rec = ();
#
# get record
($sts1, $sts2, %rec) = &ty_get($handle, "smp1", "pkey", "eq", ["9999"]);
#---------------------------------------------------------
# update salary B-)
$rec{salary} *= 10;
#
# update record
($sts1, $sts2) = &ty_update($handle, "smp1", ["9999"], \%rec);
#---------------------------------------------------------
# delete recoed
($sts1, $sts2) = &ty_delete($handle, "smp1", ["9999"]);
#---------------------------------------------------------
# terminate transaction
($sts1, $sts2) = &ty_end_tran($handle);
#---------------------------------------------------------
#
exit 0;

sample to use tyserv.pl from cgi

sample to use access interface(tycob.c) from OpenCOBOL.

       IDENTIFICATION   DIVISION.
       PROGRAM-ID.      sample1.
       ENVIRONMENT      DIVISION.
      *------------------------------------------
      * work definition
      *------------------------------------------
       WORKING-STORAGE  SECTION.
      *------------------------------------------
      * constant value
      *------------------------------------------
       01 C-NULL        PIC X(1) VALUE LOW-VALUE.
       01 C-TAB         PIC X(1) VALUE X'09'.
      *------------------------------------------
      * work variable
      *------------------------------------------
      *
      * sock_* interface
      *
       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_* interface
      *
       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 start
      *------------------------------------------
       PROCEDURE        DIVISION.
      *
       MAIN-EN.
      *
      * socket open
      *
         CALL 'sock_open' USING HOST PORT FD-SOCK.
      *
      * start update transaction
      *
         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.
      *
      * insert record
      *
         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.
      *
      * get record
      *
         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.
      *
      * update salary B-)
      *
         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.
      *
      * update record
      *
         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.
      *
      * delete record
      *
         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.
      *
      * terminate transaction
      *
         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.
      *
      * socket close
      *
         CALL 'sock_close' USING FD-SOCK.
       MAIN-EX.
         STOP RUN.
      *------------------------------------------
      * all terminate
      *------------------------------------------

notice of programming

status code

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

database definition language(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 }

explain

 1 start database definition
   database database_name {

   o database_name must be `typhoondb'.

 2 base data file definition
   data file "file_name" contains table_name;

   o file_name must be `table_name' + `.dat'

 3 primary key data file definition
   key  file "file_name" contains table_name.table_name_pkey;

   o primary key must be unique in table
   o file_name must be `table_name.pk'

 4 alternate key data file definition
   key  file "file_name" contains table_name.table_name_skey(seq number);

   o alternate key can be multiple
   o file_name must be `table_name' + `.s' + `seq number'
   o seq number must be from 1 by 1 at each alternate key

 5 start table definition
   record table_name {

 6 column definition
 7 column definition
 8 column definition
   char column_name[length + 1];

   o only `char' can be specified

 9 primary key definition
   primary key table_name_pkey { colmun_name sequence[, colmun_name sequence] ... };

   o primary key must be unique in table
   o primary key must point a record uniquely
   o sequence must be `asc' or `desc'

10 alternate key definition
   alternate key table_name_skey(seq number) { colmun_name sequence[, colmun_name sequence] ... };

   o alternate key can be multiple
   o alternate key can point multiple records
   o seq number must be from 1 by 1 at each alternate key

11 end of table definition
   }

12 end of database definition
   }

import script(tyimp)

export script(tyexp)

re-generation tyserv

run command script(rc.tyserv)

tyserv is executed in background automatically

rollforward utility(tyrecover.sh)

multi server

unit of exclusive lock is entire database(typhoondb) in tyserv. it's very big unit :-(. but if you run tyserv in multi server mode, this unit will be subdivided.

tysearch

tysearch is invoked from shell and search record from database. tysearch call typoon library directly, so tysearch can run without tyserv running. but tysearch run out of transaction management of tyserv.
$ tysearch -h  <-- show help
usage : tysearch table start_count rec_count key_name key_value ...
environment value : TYPHOON_DIR

$ tysearch smp1 1 3 pkey 0003
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

tytran.sh perform transaction in batch mode from shell. tytran.sh run in transaction management of tyserv, so tytran.sh must run with tyserv running.
$ tytran.sh -h  <-- show help
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
#
# comment here
#
START_TRAN	USER	USER
GET	smp1	pkey	eq	0001
UPDATE	smp1	0001	salary=9999999
COMMIT
END_TRAN

$ tytran.sh <trancmd.txt

for Cygwin

use typhoon-1.11.0.cygwin.patch instead of typhoon-1.11.0.patch to patch typhoon-1.11.0 and use Makefile.cygwin instead of Makefile to make tyserv.

for FreeBSD

use typhoon-1.11.0.FreeBSD.patch instead of typhoon-1.11.0.patch to to patch typhoon-1.11.0 and add `-lcompat' to LIBS in Makefile.

TODO & BUGS

information of typhoon-1.11.0


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