제3장 MultipleRM 프로그램 예제

내용 목차

3.1. Oracle과 Tibero 사용
3.1.1. 프로그램 예제
3.1.2. 환경설정 및 컴파일
3.2. Oracle과 Oracle 사용
3.2.1. 프로그램 예제
3.2.2. 환경설정 및 컴파일

본 장에서는 TCS에서 MultipleRM 프로그램 예제와 환경설정, 컴파일을 위한 Makefile의 예제에 대해서 설명한다.

3.1. Oracle과 Tibero 사용

서버 라이브러리를 이용하여 TCS에서 Oracle과 Tibero를 사용할 수 있다. 본 절에서는 Oracle과 Tibero를 사용하는 프로그램의 예제와 환경설정, 컴파일을 위한 Makefile의 예제를 설명한다.

3.1.1. 프로그램 예제

다음은 Oracle과 Tibero를 함께 사용하는 TCS 예제 프로그램이다. Embedded SQL을 이용하여 서버를 작성하고 각 데이터베이스 벤더에서 제공하는 프리 컴파일러로 컴파일하여 구성할 수 있는 프로그램 예제이다.

서비스 수행

다음은 서비스를 수행하는 프로그램의 소스이다.

#include <stdio.h>
#include <usrinc/atmi.h>

extern int oracle_call(TPSVCINFO *msg);
extern int tibero_call(TPSVCINFO *msg);

MDB_SVC1(TPSVCINFO *msg)
{
    int ret;
    int fail = 0;

    ret = oracle_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    ret = tibero_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    if ( fail ) {
        tpreturn(TPFAIL,0,(char *)msg->data, msg->len,0);
    }

    tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len,0);
}       

Oracle 호출 함수

다음은 Oracle을 호출하는 함수를 사용한 프로그램의 예제이다.

#include <stdio.h>
#include <usrinc/atmi.h>
#include <usrinc/tx.h>

EXEC SQL include sqlca.h;

EXEC SQL begin declare section;
    char h_addr[100];
EXEC SQL end declare section;

int oracle_call(TPSVCINFO *msg)
{
    int     i;

    strcpy(h_addr, msg->data);

    EXEC SQL INSERT
        INTO account( account_id, address, phone )
        VALUES ( tmax_seq.nextval,:h_addr, '007-1234' );

    if ( sqlca.sqlcode != 0 ){
        printf( "insert failed sqlcode = %d\n",sqlca.sqlcode );
        tpreturn( TPFAIL, -1, NULL, 0, 0 );
    }

    printf("ORACLE insert Success\n");

    return 0;
}

Tibero 호출 함수

다음은 Tibero를 호출하는 함수를 사용한 프로그램의 예제이다.

#include <stdio.h> 
#include <string.h> 
#include <usrinc/atmi.h>

EXEC SQL include sqlca.h;

EXEC SQL begin declare section;
    char h_addr[100];
EXEC SQL end declare section;

int tibero_call(TPSVCINFO *msg)
{
    strcpy(h_addr, msg->data);

    EXEC SQL INSERT
        INTO account( account_id, address, phone )
        VALUES ( tmax_seq.nextval,:h_addr, '007-1234' );

    if ( sqlca.sqlcode != 0 ){
        printf( "tibero insert failed sqlcode = %d\n",sqlca.sqlcode );
        tpreturn( TPFAIL, -1, NULL, 0, 0 );
    }

    printf("TIBERO insert Success\n");

    return 0;
}

3.1.2. 환경설정 및 컴파일

Oracle과 Tibero를 사용하는 MultipleRM의 환경설정 및 컴파일 예제를 설명한다.

환경설정

다음은 MultipleRM 서버의 환경설정 파일의 예제이다.

*DOMAIN
domain        SHMKEY   = 81522, MAXUSER = 10000,
              MINCLH   = 1, MAXCLH = 1,
              TPORTNO  = 11500,  BLOCKTIME = 30, 
              MAXSACALL = 1024, MAXCACALL = 1024,
              MAXMTMAX = 3, MAXSTMAX = 10

*NODE
node1         TMAXDIR  = "/home/tmax",
              APPDIR   = "/home/tmax/appbin",
              PATHDIR  = "/home/tmax/path",
              TLOGDIR  = "/home/tmax/log/tlog",
              ULOGDIR  = "/home/tmax/log/ulog",
              SLOGDIR  = "/home/tmax/log/slog"

*SVRGROUP
svg_s1        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX+Acc=P/scott/tiger+SesTm=60",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX

svg_s2      NODENAME = node1,
              DBNAME = TIBERO,
              OPENINFO ="TIBERO_XA:user=scott,pwd=tiger, sestm=60,db=TMAX",
              TMSNAME = tms_tbr,
              SVGTYPE = STMAX

Makefile

Makefile 내의 LIBS(TMAX라이브러리)에 반드시 -lnodb를 포함해야 한다.

다음은 32bit Linux에서 MultipleRM 서버 프로그램을 컴파일하기 위한 Makefile의 예제이다.

# Oracle Env
ORALIBDIR = /home/OraHome1/lib/
ORALIB = -lclntsh `cat /home/OraHome1/lib/ldflags`   `cat /home/OraHome1/lib/sysliblist` -ldl -lm

# Tibero Env
TBRLIB = -ltbxa -ltbertl
TBRLIBDIR = $(TB_HOME)/client/lib
TBRINCDIR = $(TB_HOME)/client/include

$ Server build
TARGET  = $(COMP_TARGET)
APOBJS  = $(TARGET).o
AP_ORA_OBJS = $(TARGET)_ora.o
AP_TBR_OBJS = $(TARGET)_tbr.o
NSDLOBJ = $(TMAXDIR)/lib/sdl.o

LIBS    = -lnsl -lsvr -lnodb

OBJS    = $(AP_ORA_OBJS) $(AP_TBR_OBJS) $(SVCTOBJ) $(APOBJS)
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR)

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
TMAXLIBDIR  = $(TMAXDIR)/lib

#
.SUFFIXES : .c

.c.o:
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $<
    
#
# server compile
#
all: $(TARGET)


$(TARGET):$(OBJS)
    echo $(OBJS)
    $(CC) $(CFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(TBRLIBDIR) -L$(ORALIBDIR) $(ORALIB) $(TBRLIB) $(OBJS) $(LIBS) $(NSDLOBJ)
    mv $(TARGET) $(APPDIR)/.
    rm -f $(OBJS)

$(AP_ORA_OBJS):
    echo $(OBJS)
    proc iname=$(TARGET)_ora.pc include=$(TMAXDIR)
    $(CC) $(CFLAGS) -c $(TARGET)_ora.c

$(AP_TBR_OBJS):
    echo $(OBJS)
    tbpc iname=$(TARGET)_tbr.tbc include=$(TMAXDIR)
    $(CC) $(CFLAGS) -I$(TBRINCDIR) -c $(TARGET)_tbr.c

$(APOBJS):
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $(TARGET).c

$(SVCTOBJ):
    echo $(OBJS)
    cp -f $(SVCTDIR)/$(TARGET)_svctab.c .
    touch ./$(TARGET)_svctab.c
    $(CC) $(CFLAGS) -c ./$(TARGET)_svctab.c

#
clean:
    -rm -f *.o core $(TARGET) $(TARGET).lis

참고

운영체제에 따라 Makefile 내용은 다를 수 있다.

3.2. Oracle과 Oracle 사용

서버 라이브러리를 이용하여 TCS에서 Oracle과 Oracle을 사용할 수 있다. 본 절에서는 Oracle과 Oracle을 사용하는 프로그램의 예제와 환경설정, 컴파일을 위한 Makefile의 예제를 설명한다.

3.2.1. 프로그램 예제

다음은 2개의 RM이 모두 Oracle이지만 인스턴스가 다른 경우에 한 서버에서 처리하는 예제이다.

같은 Oracle 클라이언트 라이브러리를 사용하기 때문에 사용자 코드에서 쿼리를 수행할 경우 어떤 인스턴트를 수행할지는 사용자가 지정해야 한다. 이를 위해서 Oracle에서는 xa_open의 경우 사용자 코드에서 xaoSvcCtx, xaoEnv 등의 OCI 함수를 이용하여 해당하는 인스턴트 커넥션을 얻어와서 지정할 수 있다.

서비스 수행

다음은 서비스를 수행하는 프로그램의 소스이다.

#include <stdio.h>
#include <usrinc/atmi.h>

extern int oracle_call(TPSVCINFO *msg);

MDB_SVC2(TPSVCINFO *msg)
{
    int ret;
    int fail = 0;

    ret = oracle_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    if ( fail ) {
        tpreturn(TPFAIL,0,(char *)msg->data, msg->len,0);
    }

    tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len,0);
}       

Oracle 호출 함수

다음은 Oracle을 호출하는 함수를 사용하는 프로그램의 예제이다.

#include <stdio.h>
#include <usrinc/atmi.h>
#include <usrinc/tx.h>
#include <oci.h>

static void checkerr(errhp, status)
OCIError *errhp;
sword status;
{
    text errbuf[512];
    sb4 errcode;

    switch (status)
    {
        case OCI_SUCCESS:
            break;
        case OCI_SUCCESS_WITH_INFO:
            break;
        case OCI_NEED_DATA:
            break;
        case OCI_NO_DATA:
            break;
        case OCI_ERROR:  /* get the error back and display on the screen */
            (void) OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
                                errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
            (void) printf("Error - %s\n", errbuf);
            break;
        case OCI_INVALID_HANDLE:
            break;
        case OCI_STILL_EXECUTING:
            break;
        case OCI_CONTINUE:
            break;
        default:
            break;
    }
}

int
oracle_call(TPSVCINFO *msg)
{
    int     i;
    OCIEnv *envhp;
    OCIServer *srvhp;
    OCIError *errhp;
    OCISvcCtx *svchp;
    OCISession *usrhp;
    OCIStmt *stmthp;
    dvoid *tmp;
    char *sql = {"INSERT "
        "INTO hahehiho_account( account_id, address, phone ) "
        "VALUES ( skt_seq.nextval,'asdf', '007-1234' )"};

    char *sql2 = {"INSERT "
        "INTO hahehiho_account( account_id, address, phone ) "
        "VALUES ( skt_seq.nextval,'fdsa', '700-1234' )"};

    svchp = xaoSvcCtx("A");
    envhp = xaoEnv("A");
    printf("oracle call A octxt[%d]\n", svchp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp,
                           (ub4) OCI_HTYPE_ERROR,
                           52, (dvoid **) &tmp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
               (ub4) OCI_HTYPE_STMT, 50, (dvoid **) &tmp);

    checkerr(errhp, OCIStmtPrepare(stmthp, errhp,(text *)sql, (ub4)strlen(sql), 
            (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));

    checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
            (OCISnapshot *) NULL, (OCISnapshot *) NULL,
            (ub4) OCI_DEFAULT));

    svchp = xaoSvcCtx("B");
    envhp = xaoEnv("B");
    printf("oracle call B octxt[%d]\n", svchp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp,
                           (ub4) OCI_HTYPE_ERROR,
                           52, (dvoid **) &tmp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
               (ub4) OCI_HTYPE_STMT, 50, (dvoid **) &tmp);

    checkerr(errhp, OCIStmtPrepare(stmthp, errhp,(text *)sql2, (ub4)strlen(sql2),
            (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));


    checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
            (OCISnapshot *) NULL, (OCISnapshot *) NULL,
            (ub4) OCI_DEFAULT));


    return 0;
}

3.2.2. 환경설정 및 컴파일

Oracle과 Oracle을 사용하는 MultipleRM의 환경설정 및 컴파일 예제를 설명한다.

환경설정

다음은 MultipleRM 서버의 환경설정 파일의 예제이다.

*DOMAIN
domain        SHMKEY   = 81522, MAXUSER = 10000,
              MINCLH   = 1, MAXCLH = 1,
              TPORTNO  = 11500,  BLOCKTIME = 30, 
              MAXSACALL = 1024, MAXCACALL = 1024,
              MAXMTMAX = 3, MAXSTMAX = 10

*NODE
node1         TMAXDIR  = "/home/tmax",
              APPDIR   = "/home/tmax/appbin",
              PATHDIR  = "/home/tmax/path",
              TLOGDIR  = "/home/tmax/log/tlog",
              ULOGDIR  = "/home/tmax/log/ulog",
              SLOGDIR  = "/home/tmax/log/slog"

*SVRGROUP
svg_s1        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX1+Acc=P/scott/tiger+SesTm=60+DB=A",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX,
              RMID = 0

svg_s2        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX2+Acc=P/scott/tiger+SesTm=60+DB=B",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX,
              RMID = 1

svgm1         NODENAME = node1,
              SVGLIST = "svg_s2,svg_s1",
              SVGTYPE = MTMAX

*SERVER
sample SVGNAME = svgm1, LOGLVL = DEBUG4

*SERVICE
MDB_SVC2 SVRNAME = sample

Makefile

Makefile의 TMAXLIBS에 반드시 -lnodb를 포함해야 한다. 다음은 32bit Linux에서 MultipleRM 서버 프로그램을 컴파일하기 위한 Makefile의 예이다.

# Oracle Env
ORALIBDIR = /home/OraHome1/lib/
ORALIB = -lclntsh `cat /home/OraHome1/lib/ldflags`   `cat /home/OraHome1/lib/sysliblist` -ldl -lm

LIBS    = -lnsl -lsvrmrm

OBJS    = $(AP_ORA_OBJS) $(AP_TBR_OBJS) $(SVCTOBJ) $(APOBJS)
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR)

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svctTARGET  = $(COMP_TARGET)
APOBJS  = $(TARGET).o
AP_ORA_OBJS = $(TARGET)_ora.o
NSDLOBJ = $(TMAXDIR)/lib/sdl.o

LIBS    = -lnsl -lsvr -lnodb

OBJS    = $(AP_ORA_OBJS) $(SVCTOBJ) $(APOBJS) 
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR) -I$(ORACLE_HOME)/include -I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
TMAXLIBDIR  = $(TMAXDIR)/lib

#
.SUFFIXES : .c

.c.o:
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $<

#
# server compile
#
all: $(TARGET)


$(TARGET):$(OBJS)
    $(CC) $(CFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(ORALIBDIR) $(ORALIB)  $(OBJS) $(LIBS) $(NSDLOBJ)
    mv $(TARGET) $(APPDIR)/.
    rm -f $(OBJS)

$(AP_ORA_OBJS):
    $(CC) $(CFLAGS) -c $(TARGET)_ora.c

$(APOBJS):
    $(CC) $(CFLAGS) -c $(TARGET).c

$(SVCTOBJ): 
    echo $(OBJS)
    cp -f $(SVCTDIR)/$(TARGET)_svctab.c .
    touch ./$(TARGET)_svctab.c 
    $(CC) $(CFLAGS) -c ./$(TARGET)_svctab.c

#
clean:
    -rm -f *.o core $(TARGET) $(TARGET).lis

참고

운영체제에 따라 Makefile 내용은 다를 수 있다.