> For the complete documentation index, see [llms.txt](https://docs.tibero.com/tibero-manuals/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tibero.com/tibero-manuals/tibero_7.2.5./7.2.5.manuals/tibero-development-guide/appendix-b.example-of-integrating-with-tuxedo.md).

# Appendix B. Tibero와 Tuxedo 연동 예제

Tibero와 Tuxedo 연동 예제 프로그램의 전체 소스 코드와 각종 스크립트를 설명합니다.

## tb\_tux.env

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

```
# 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
```

## tb\_tux.conf.m

다음은 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
```

## tmax32.fld

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

```
#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	-
```

## trans\_fml32.tbc

다음은 서버 프로그램 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);
}
```

## builds.sh

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

```
#### 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.c

다음은 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.c

다음은 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();
```

## buildc.sh

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

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

## create\_table.sql

다음은 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)
);
~
```

## run.sh

다음은 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
```
