Appendix B. Tibero와 Tuxedo 연동 예제

내용 목차

B.1. tb_tux.env
B.2. tb_tux.conf.m
B.3. tmax32.fld
B.4. trans_fml32.tbc
B.5. builds.sh
B.6. insert.c
B.7. select.c
B.8. buildc.sh
B.9. create_table.sql
B.10. run.sh

본 장에서는 Tibero와 Tuxedo 연동 예제 프로그램의 전체 소스 코드와 각종 스크립트를 설명한다.

다음은 시스템 환경변수 설정 파일이다.

# for tibero
export TB_HOME=/path/to/tibero
export TB_SID=tibero
export PATH=$TB_HOME/bin:$TB_HOME/client/bin:$TB_HOME/scripts:$PATH
export LD_LIBRARY_PATH=$TB_HOME/client/lib:$TB_HOME/lib:$LD_LIBRARY_PATH
export LIBPATH=$TB_HOME/client/lib:$TB_HOME/lib:$LIBPATH

# for tuxedo
export TUXDIR=/path/to/tuxedo
export JAVA_HOME=$TUXDIR/jre
export JVMLIBS=$JAVA_HOME/lib/amd64/server:$JAVA_HOME/jre/bin
export PATH=$TUXDIR/bin:$JAVA_HOME/bin:$PATH
export COBCPY=:$TUXDIR/cobinclude; export COBCPY
export COBOPT="-C ANS85 -C ALIGN=8 -C NOIBMCOMP -C TRUNC=ANSI -C OSEXT=cbl"
export SHLIB_PATH=$TUXDIR/lib:$JVMLIBS:$SHLIB_PATH
export LIBPATH=$TUXDIR/lib:$JVMLIBS:$LIBPATH
export LD_LIBRARY_PATH=$TUXDIR/lib:$JVMLIBS:$LD_LIBRARY_PATH
export WEBJAVADIR=$TUXDIR/udataobj/webgui/java
export TUXCONFIG=/path/to/tuxedo/tuxconf
export FLDTBLDIR32=/path/to/tuxedo
export FIELDTBLS32=tmax32.fld
export TLOGDEVICE=/path/to/tuxedo/TLOG
export ULOGPFX=/path/to/tuxedo/ULOG

다음은 Tuxedo 환경설정 파일이다.

*RESOURCES
IPCKEY          68300

DOMAINID        tbrdomain
MASTER          tbrtest
MAXACCESSERS    10
MAXSERVERS      5
MAXSERVICES     20
MODEL           SHM
LDBAL           N

*MACHINES
DEFAULT:
                TUXDIR="/data1/apmqam/oracle/tuxedo/tuxedo10gR3"
                APPDIR="/data1/apmqam/tibero_tuxedo_test"
                TUXCONFIG="/data1/apmqam/tibero_tuxedo_test/tuxconf"
                TLOGDEVICE="/data1/apmqam/tibero_tuxedo_test/TLOG"

tmaxi4          LMID=tbrtest

*GROUPS
TBXA            LMID=tbrtest GRPNO=1
                TMSNAME=tms_tibero
                OPENINFO="TIBERO_XA:TIBERO_XA:user=sys,pwd=tibero,
                          sestm=60,db=tibero"

*SERVERS
DEFAULT:
                CLOPT="-A -r"

trans_fml32     SRVGRP=TBXA  SRVID=1

*SERVICES
SELECT_FML32
INSERT_FML32

다음은 필드 테이블 파일이다.

#name           number          type            flag    comment
OUTPUT          302             string          0       -
EMPNO           901             long            0       -
ENAME           902             string          0       -
JOB             903             string          0       -
MGR             904             long            0       -
SAL             905             float           0       -
COMM            906             float           0       -
DEPTNO          907             long            0       -

다음은 서버 프로그램 tbESQL/C 파일이다.

#include <stdio.h>
#include <atmi.h>
#include <userlog.h>
#include <Uunix.h>
#include <fml32.h>
#include "fml32.fld.h"
#include <tx.h>
#include "sqlca.h"

EXEC SQL include SQLCA.H;

EXEC SQL begin declare section;
    int h_empno;
    char h_ename[10];
    char h_job[10];
EXEC SQL end declare section;

void INSERT_FML32(rqst)
TPSVCINFO *rqst;
{
    FBFR32 *sndbuf;
    char msgbuf[256];
    FLDLEN32 flen;
    XID *xid;
    TXINFO info;
    char xidstring[1000];
    char str[100];

    int i;

    sndbuf = (FBFR32 *)rqst->data;

    tx_info(&info);
    xid = &(info.xid);

    memset( xidstring, 0x00, 1000);

    for( i = 0 ; i < xid->gtrid_length+xid->bqual_length ; i++ )
    {
        sprintf(xidstring+strlen(xidstring),"%0x\0",xid->data[i]);
    }

    Fprint32(sndbuf);
    memset( &h_empno, 0x00, sizeof ( h_empno ) );
    memset( h_ename, 0x00, sizeof ( h_ename ) );
    memset( h_job, 0x00, sizeof ( h_job ) );

    Fget32(sndbuf, EMPNO, 0, (char *)&h_empno, &flen);
    Fget32(sndbuf, ENAME, 0, (char *)h_ename, &flen);
    Fget32(sndbuf, JOB, 0, (char *)h_job, &flen);

    printf("SVR: EMPNO %d ENAME %s JOB %s\n", h_empno, h_ename, h_job);
    printf("SVR: INSERT_FML32 XID:%d.%d. %0x.%s - %s\n\n",
            xid->gtrid_length, xid->bqual_length,
            xid->formatID, xidstring, h_ename);

    EXEC SQL INSERT
    INTO emp( empno, ename, job )
    VALUES ( :h_empno, :h_ename, :h_job );

    if ( sqlca.sqlcode != 0 ){
        sprintf(msgbuf, "insert fail: sqlcode = %d(%s)\n",
                        sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        Fchg32(sndbuf, OUTPUT, 0, msgbuf, 0);
        tpreturn(TPFAIL, -1, (char *)sndbuf, 0, 0);
    }

    strcpy(msgbuf, "insert success!" );
    Fchg32(sndbuf, OUTPUT, 0, msgbuf, 0);
    tpreturn(TPSUCCESS, 0, rqst->data, strlen(rqst->data), 0);
}

void SELECT_FML32(rqst)
TPSVCINFO *rqst;
{
    FBFR32 *sndbuf;
    char msgbuf[256];
    FLDLEN32 flen;

    sndbuf = (FBFR32 *)rqst->data;
    Fprint32(sndbuf);
    Fget32(sndbuf, EMPNO, 0, (char *)&h_empno, &flen);

    EXEC SQL SELECT NVL(ename,' '), NVL(job,' ')
    INTO :h_ename,:h_job
    FROM emp
    WHERE empno = :h_empno;

    if ( sqlca.sqlcode != 0 ){
        sprintf(msgbuf, "select failed sqlcode = %d(%s)\n",
                        sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        Fchg32(sndbuf, OUTPUT, 0, msgbuf, 0);
        tpreturn(TPFAIL, -1, (char *)sndbuf, 0, 0);
    }

    printf("#### %d \n", h_empno);
    Fchg32(sndbuf, ENAME, 0,(char *)h_ename, 0);
    Fchg32(sndbuf, JOB, 0, (char *)h_job, 0);
    Fchg32(sndbuf, EMPNO, 0, (char *)&h_empno, 0);

    strcpy(msgbuf, "select success!" );
    Fchg32(sndbuf, OUTPUT, 0, msgbuf, 0);

    Fprint32(sndbuf);
    tpreturn(TPSUCCESS, 0,(char *)sndbuf, sizeof(sndbuf), 0);
}

다음은 서버 프로그램 빌드 스크립트이다.

#### transaction server precompile ####
PRECOMP=$TB_HOME/client/bin/tbpc
PRECOMPFLAGS="UNSAFE_NULL=YES"
LIB=$TB_HOME/client/lib
INC=$TB_HOME/client/include
CFLAGS="-ltbcli -ltbxa -lm -lrt -lpthread -ltbertl -g "
CC=gcc
rm -f trans_fml32.c
$PRECOMP INCLUDE=$TUXDIR/include UNSAFE_NULL=YES INCLUDE=$INC 
$PRECOMPFLAGS ONAME=trans_fml32.c trans_fml32.tbc

#### transaction server build ####
buildserver -o trans_fml32 -v -f trans_fml32.c -s INSERT_FML32,SELECT_FML32 -r 
TIBERO_XA

다음은 INSERT 클라이언트 프로그램 파일이다.

#include <stdio.h>
#include <atmi.h>
#include <fml32.h>
#include <string.h>
#include "fml32.fld.h"

struct temp_str{
        int   empno;
        char  ename[11];
        char  job[10];
};
typedef struct temp_str *str;

main(argc, argv)
char *argv[];
{
    FBFR32 *sendbuf;
    FBFR32 *recvbuf;
    long recvlen = 0;
    int ret;
    str tmpbuf;
    char msgbuf[30];
    FLDLEN32 flen;

    tmpbuf = malloc(sizeof(struct temp_str));

    if (tpinit((TPINIT *) NULL) == -1) {
        fprintf(stderr, "Tpinit failed\n");
        exit(1);
    }

    if((sendbuf = (FBFR32 *) tpalloc("FML32", NULL, 0)) == NULL) {
        fprintf(stderr,"Error allocating send buffer\n");
        tpterm();
        exit(1);
    }

    if((recvbuf = (FBFR32 *) tpalloc("FML32", NULL, 0)) == NULL) {
        fprintf(stderr,"Error allocating receive buffer\n");
        tpfree((char *)sendbuf);
        tpterm();
        exit(1);
    }

    tmpbuf = malloc(sizeof(struct temp_str));

    printf("\n******************************************\n");
    printf( "|  Employee Number : " ); scanf ( "%d", &tmpbuf->empno );
    printf( "|  Employee Name   : " ); scanf ( "%s", tmpbuf->ename );
    printf( "|  Employee Job    : " ); scanf ( "%s", tmpbuf->job );
    printf("******************************************\n\n");

    tpbegin(10, 0);
    Fchg32(sendbuf,EMPNO,0,(char *)&tmpbuf->empno,0);
    Fchg32(sendbuf,ENAME,0,(char *)tmpbuf->ename,0);
    Fchg32(sendbuf,JOB,0,(char *)tmpbuf->job,0);

    ret = tpcall("INSERT_FML32", (char *)sendbuf, 0, (char **)&recvbuf,
                 &recvlen, (long)0);
    if(ret == -1) {
        fprintf(stderr, "tperrno = %d (%s) \n", tperrno, tpstrerror(tperrno));
        tpfree((char *)sendbuf);
        tpfree((char *)recvbuf);
        tpterm();
        exit(1);
    }

    flen = sizeof( msgbuf );
    Fget32(recvbuf, OUTPUT, 0, (char *)msgbuf, &flen);
    printf("%s\n", msgbuf);

    tpcommit(0);

    free(tmpbuf);
    tpfree((char *)sendbuf);
    tpterm();
}

다음은 SELECT 클라이언트 프로그램 파일이다.

#include <stdio.h>
#include <atmi.h> 
#include <fml32.h>
#include <string.h>
#include "fml32.fld.h"

main(argc, argv)
char *argv[];
{
    FBFR32 *sendbuf;
    FBFR32 *recvbuf;
    long recvlen;
    int ret;
    int empno;
    FLDLEN32 flen;
    int h_empno;
    char h_ename[10];
    char h_job[10];
    char msgbuf[256];

    if (tpinit((TPINIT *) NULL) == -1) {
        fprintf(stderr, "Tpinit failed\n");
        exit(1);
    }

    if((sendbuf = (FBFR32 *) tpalloc("FML32", NULL, 0)) == NULL) {
        fprintf(stderr,"Error allocating send buffer\n");
        tpterm();
        exit(1);
    }

    if((recvbuf = (FBFR32 *) tpalloc("FML32", NULL, 0)) == NULL) {
        fprintf(stderr,"Error allocating receive buffer\n");
        tpfree((char *)sendbuf);
        tpterm();
        exit(1);
    }

    printf("\n******************************************\n");
    printf( "|  Employee Number : " ); scanf ( "%d", &empno );
    printf("******************************************\n\n");

    Fchg32(sendbuf,EMPNO,0,(char *)&empno,0);

    ret = tpcall("SELECT_FML32", (char *)sendbuf, 0, (char **)&recvbuf,
                 &recvlen, (long)0);
    if(ret == -1) {
        fprintf(stderr, "tperrno = %d (%s)\n", tperrno, tpstrerror(tperrno));
        flen = sizeof( msgbuf );
        Fget32(recvbuf, OUTPUT, 0, (char *)msgbuf, &flen);
        printf("error msg: %s\n", msgbuf);
        tpfree((char *)sendbuf);
        tpfree((char *)recvbuf);
        tpterm();
        exit(1);
    }

    flen = sizeof(msgbuf);
    Fget32(recvbuf, OUTPUT, 0, (char *)msgbuf, &flen);
    printf("%s\n", msgbuf);

    flen = sizeof(&h_empno);
    Fget32(recvbuf, EMPNO, 0, (char *)&h_empno, &flen);
    printf("EMPNO; %d \n", h_empno);
    flen = sizeof(h_ename);
    Fget32(recvbuf, ENAME, 0, (char *)h_ename, &flen);
    printf("ENAME: %s \n", h_ename);
    flen = sizeof(h_job);
    Fget32(recvbuf, JOB, 0, (char *)h_job, &flen);
    printf("JOB: %s \n", h_job);

    tpfree((char *)recvbuf);
    tpfree((char *)sendbuf);
    tpterm();
}
~

다음은 클라이언트 프로그램 빌드 스크립트이다.

buildclient -o insert -v -f insert.c
buildclient -o select -v -f select.c

다음은 SELECT 클라이언트 프로그램 파일이다.

drop table emp;
CREATE TABLE emp (
    empno           NUMBER,
    ename           VARCHAR2(10),
    job             VARCHAR2(9),
    mgr             NUMBER(4),
    hiredate        DATE,
    sal             NUMBER(7,2),
    comm            NUMBER(7,2),
    deptno          NUMBER(2)
);
~

다음은 Tuxedo 시스템 기동 스크립트이다.

#!/bin/sh

tmshutdown -y
rm ULOG* > /dev/null 2>&1
rm xa* > /dev/null 2>&1

tmloadcf -y tb_tux.conf.m
rm /data1/apmqam/tibero_tuxedo_test/TLOG* > /dev/null 2>&1
rm /data1/apmqam/tibero_tuxedo_test/ULOG* > /dev/null 2>&1

tmadmin -c << EOF
crdl -z /data1/apmqam/tibero_tuxedo_test/TLOG -b 1000
q
EOF

tmboot -y