내용 목차
본 장에서는 TCS에서 MultipleRM 프로그램 예제와 환경설정, 컴파일을 위한 Makefile의 예제에 대해서 설명한다.
서버 라이브러리를 이용하여 TCS에서 Oracle과 Tibero를 사용할 수 있다. 본 절에서는 Oracle과 Tibero를 사용하는 프로그램의 예제와 환경설정, 컴파일을 위한 Makefile의 예제를 설명한다.
다음은 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을 호출하는 함수를 사용한 프로그램의 예제이다.
#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를 호출하는 함수를 사용한 프로그램의 예제이다.
#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; }
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 내의 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 내용은 다를 수 있다.
서버 라이브러리를 이용하여 TCS에서 Oracle과 Oracle을 사용할 수 있다. 본 절에서는 Oracle과 Oracle을 사용하는 프로그램의 예제와 환경설정, 컴파일을 위한 Makefile의 예제를 설명한다.
다음은 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을 호출하는 함수를 사용하는 프로그램의 예제이다.
#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; }
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의 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 내용은 다를 수 있다.