예제
본 장에서는 서비스 프로그램, 전역 트랜잭션 프로그램 등 예제 프로그램과 설명을 기술한다.
1. 서비스 프로그램
다음은 서비스 프로그램 작성 과정이다.
1.1. 예제 프로그램
다음은 서비스 프로그램의 예제이다.
예제 프로그램에서 설명하는 서비스는 XA 서버 그룹에 속한 서버로서 Tmax의 AUTOTRAN 기능을 이용하므로, 반드시 Tmax 환경 파일에서 해당 서비스에 대해서 “AUTOTRAN=Y” 설정이 필요하다. |
<$TMAXDIR/sample/cobserver/carrayauto.pco>
****************************************************** * XA 이면서 CARRAY 버퍼를 사용하는 서비스 * ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. CARRAYAUTO. AUTHOR. TMAX DEVELOPMENT. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. FILE SECTION. WORKING-STORAGE SECTION. ****************************************************** * TMAX ATMI 함수를 위한 definitions ****************************************************** 01 TPSVCRET-REC. COPY TPSVCRET. * 01 TPTYPE-REC. COPY TPTYPE. * 01 TPSTATUS-REC. COPY TPSTATUS. * 01 TPSVCDEF-REC. COPY TPSVCDEF. * 01 TX-RETURN-STATUS. COPY TXSTATUS. ****************************************************** * Log message definitions ****************************************************** 01 LOGMSG. 05 LOGMSG-SVC PIC X(16). 05 FILLE PIC X(3) VALUES " : ". 05 LOGMSG-TEXT PIC X(80). 01 LOGMSG-LEN PIC S9(9) COMP-5. ****************************************************** * User defined data records ****************************************************** 01 RECV-STRING PIC X(100). 01 SEND-STRING PIC X(100). ****************************************************** * 사용자 정의 ORACLE Host변수 선언 ****************************************************** EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 S-SRC. 05 S-TEMP PIC X(10) VARYING. EXEC SQL END DECLARE SECTION END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. LINKAGE SECTION. * PROCEDURE DIVISION. * 000-MAIN. PERFORM 100-SVCSTART THRU 100-EXIT. PERFORM 200-DBINSERT THRU 200-EXIT. PERFORM 900-TPRETURNSCS THRU 900-TPRETURNSCS-X. 000-EXIT. ****************************************************** * 클라이언트로부터 전송된 데이터를 수신 ****************************************************** 100-SVCSTART. MOVE LENGTH OF RECV-STRING TO LEN. CALL "TPSVCSTART" USING TPSVCDEF-REC TPTYPE-REC RECV-STRING TPSTATUS-REC. IF NOT TPOK MOVE "TPSVCSTART Fail" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. IF TPTRUNCATE MOVE "Received data was truncated" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. DISPLAY "------------------------------------------------". MOVE SERVICE-NAME TO LOGMSG-SVC. MOVE "서비스 시작 " TO LOGMSG-TEXT. PERFORM 800-USERLOG. 100-EXIT. 200-DBINSERT. MOVE RECV-STRING(1:LEN) TO S-TEMP-ARR. MOVE LENGTH OF S-TEMP-ARR TO S-TEMP-LEN. * DB INSERT처리 EXEC SQL INSERT INTO TEMP (NAME,SAL) VALUES (RTRIM(:S-TEMP),150) END-EXEC. IF SQLCODE NOT = 0 PERFORM 800-SQLERROR PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. STRING "Inserted data : " S-TEMP-ARR DELIMITED BY SIZE INTO LOGMSG-TEXT. PERFORM 800-USERLOG. MOVE "성공적 처리" TO SEND-STRING. 200-EXIT. 800-SQLERROR. * LOG메시지 내용을 구성하여 로깅처리 STRING "800-SQLERROR : " SQLERRMC DELIMITED BY SIZE INTO LOGMSG-TEXT. MOVE SQLCODE TO APPL-CODE. ****************************************************** * Write out a log err messages ****************************************************** 800-USERLOG. DISPLAY LOGMSG. ****************************************************** * 성공적으로 서비스가 종료 ****************************************************** 900-TPRETURNSCS. MOVE "서비스가 성공적으로 끝났음" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPSUCCESS TO TRUE. MOVE LENGTH OF SEND-STRING TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-STRING. 900-TPRETURNSCS-X. ****************************************************** * 비정상적으로 서비스가 종료 ****************************************************** 900-TPRETURNFAIL. MOVE "서비스가 비정상적으로 처리" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPFAIL TO TRUE. MOVE "처리불가 " TO SEND-STRING. MOVE LENGTH OF SEND-STRING TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-STRING. 900-TPRETURNFAIL-X.
다음은 각 단계별 세부 설명이다.
-
서비스명을 설정한다. 서비스 호출자가 TPCALL에서 사용할 서비스명은 PROGRAM-ID에서 정의한다.
PROGRAM-ID. CARRAYAUTO.
-
버퍼를 정의한다.
클라이언트와 데이터 송수신에 사용되는 버퍼를 정의한다. 서비스 호출자와 데이터를 주고받을 때 사용할 버퍼를 정의한다.
****************************************************** * User defined data records ****************************************************** 01 RECV-STRING PIC X(100). 01 SEND-STRING PIC X(100).
-
서비스를 시작한다. 서비스를 시작하면서 서비스 호출자가 보낸 데이터를 "버퍼 정의"에서 정의한 버퍼에 받아낸다.
예제에서는 RECV-STRING에 서비스호출자가 전송한 데이터가 저장된다. 어떤 에러가 발생하면 “IF NOT TPOK“에서 검사될 것이며, 서비스 호출자가 보낸 데이터보다 버퍼(RECV-STRING)의 사이즈가 작으면 TPTRUNCATE 에러가 발생한다.
MOVE LENGTH OF RECV-STRING TO LEN. CALL "TPSVCSTART" USING TPSVCDEF-REC TPTYPE-REC RECV-STRING TPSTATUS-REC. IF NOT TPOK MOVE "TPSVCSTART Fail" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. IF TPTRUNCATE MOVE "Received data was truncated" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF.
-
성공적으로 서비스를 종료한다.
SET TPSUCCESS TO TRUE. MOVE LENGTH OF SEND-STRING TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-STRING.
-
로직의 에러로 실패를 반환한다.
비즈니스 로직의 완료 후에 서비스호출자에게 응답을 주기 위해서는 TPRETURN을 사용한다. 서비스 수행이 실패한 경우에는 TPFAIL을 이용한다. TPFAIL을 이용하여 TPRETURN하는 경우에는 서비스 호출자는 에러 코드로 C 언어에서는 tperrno=11(TPESVCFAIL), COBOL 언어에서는 TP-STATUS=11(TPESVCFAIL)을 반환받는다.
SET TPFAIL TO TRUE. MOVE "처리불가 " TO SEND-STRING. MOVE LENGTH OF SEND-STRING TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-STRING.
1.2. Makefile
사용자가 작성한 서비스 프로그램과 Tmax에서 제공하는 라이브러리, DB 벤더에서 제공하는 라이브러리들이 묶어서 하나의 실행 파일을 만든다.
다음은 실행 파일을 생성하는 과정이다.
-
*.pco → *.cob
ProCOBOL 프로그램을 precompile한다.
-
*.cob → *.o
COBOL 프로그램을 compile하여 오브젝트 파일 생성한다.
-
*.o + *.a → 실행 파일
Tmax에서 제공하는 라이브러리, DB 벤더에서 제공하는 라이브러리를 link해서 실행 파일을 생성한다.
COBOL로 작성한 서비스가 한 개이면서 하나의 서버가 하나의 서비스로 이루어지는 경우에는 위의 3단계를 한 개의 Makefile에서 처리한다. 그러나 일반적으로 한 개의 서버에는 여러 개의 서비스가 존재하게 된다. 즉, *.pco → .cob, *.cob → *.o 의 단계는 각 서비스별로 이루어져야 하고, *.o + 라이브러리 파일들을 묶어서 서버를 만드는 과정은 1회만 수행된다.
*.pco → *.o는 셸 프로그램에서 처리하고, 실행 파일을 만드는 과정은 Makefile에서 처리한다.
$ cat carray_xa.sh echo "-------------> carrayauto.pco" procob18 sqlcheck=full userid=scott/tiger mode=ansi release_cursor=no hold_cursor=yes maxliteral=160 ireclen=132 iname=carrayauto.pco cob -C IBMCOMP -C NESTCALL -cx carrayauto.cob echo "-------------> carraynauto.pco" procob18 sqlcheck=full userid=scott/tiger mode=ansi release_cursor=no hold_cursor=yes maxliteral=160 ireclen=132 iname=carraynauto.pco cob -C IBMCOMP -C NESTCALL -cx carraynauto.cob
다음은 각 단계에 대한 설명이다.
-
COBOL object 파일을 셸에서 생성한다.
sh carray_xa.sh -------------> carrayauto.pco Pro*COBOL: Release 1.8.76.0.0 - Production on Wed May 7 23:43:42 2003 (c) Copyright 2001 Oracle Corporation. All rights reserved. System default option values taken from: /database/ora9/precomp/admin/pcccob.cfg Precompiling carrayauto.pco -------------> carraynauto.pco Pro*COBOL: Release 1.8.76.0.0 - Production on Wed May 7 23:43:42 2003 (c) Copyright 2001 Oracle Corporation. All rights reserved. System default option values taken from: /database/ora9/precomp/admin/pcccob.cfg Precompiling carraynauto.pco
-
procob18 또는 cob의 compile option은 운영체제별로 달라지므로 확인 후 작업한다. procob18에서 사용하는 option은 $ORACLE_HOME/precomp/demo/procob/demo_procob.mk 파일을 참고한다.
-
carray_xa.sh에는 carrayauto.pco, carraynauto.pco를 pre-compile, compile 과정을 거치므로, 예제 프로그램에서 carrayauto.pco, carraynauto.pco가 모두 필요하다.
-
-
실행 파일을 만들기 위한 Makefile을 생성한다.
#Makefile TARGET = carray_xa -----(1) TMAXCBLSTUB = cblstub -----(2) TMAXCBLSTUBOBJ = $(TMAXCBLSTUB).o COBOBJS = carrayauto.o carraynauto.o -----(3) OBJS = $(TMAXCBLSTUBOBJ) $(SDLOBJ) $(SVCTOBJ) SVCTOBJ = $(TARGET)_svctab.o SDLOBJ = $(TMAXDIR)/lib/sdl.o CFLAGS = -O -q32 -g -D_CBL_MODULE -I$(TMAXDIR) -I$(TMAXDIR)/usrinc LDFLAGS = -brtl COBFLAGS= -C IBMCOMP -C NESTCALL APPDIR = $(TMAXDIR)/appbin SVCTDIR = $(TMAXDIR)/svct LIBDIR = $(TMAXDIR)/lib LIBS = -loras -lcbls -----(4) ORALIBD = $(ORACLE_HOME)/lib32 ORALIBS = $(ORACLE_HOME)/precomp/lib32/cobsqlintf.o -lclntsh -lld -lm `cat $(ORACLE_HOME)/lib32/sysliblist` -lm -lc_r -lpthreads # .SUFFIXES : .c .c.o: $(CC) $(CFLAGS) -c $< # server compile # $(TARGET): $(OBJS) cob -Q "-brtl" $(COBFLAGS) -g -o $(TARGET) -L$(LIBDIR) -L$(ORALIBD) $(OBJS) $(COBOBJS) $(LIBS) $(ORALIBS) mv -f $(TARGET) $(APPDIR)/. rm -f $(TARGET).o $(SVCTOBJ) $(TMAXCBLSTUBOBJ) $(COBOBJS) $(TMAXCBLSTUBOBJ): cc $(CFLAGS) $(LDFLAGS) -c $(TMAXDIR)/cobinc/$(TMAXCBLSTUB).c $(SVCTOBJ):$(SVCTDIR)/$(TARGET)_svctab.c cc $(CFLAGS) -c $(SVCTDIR)/$(TARGET)_svctab.c ################################################ clean: -rm -f $(OBJS) core $(TARGET) $(TARGET).lis $(TARGET).cob
항목 설명 (1) TARGET
서버(실행 파일)명을 설정한다.
(2) TMAXCBLSTUB
Tmax에서 제공하는 stub 파일명을 설정한다.
(3) COBOBJS
COBOL로 작성한 서비스의 오브젝트 파일명을 설정한다.
(4) LIBS
Tmax에서 제공하는 라이브러리 파일명을 설정한다.
2. FDL 버퍼 사용 프로그램
COBOL 서비스 프로그램에서 FDL 버퍼를 직접 사용할 수 없기 때문에 구조체 구조와의 상호변환 작업이 요구된다. 그리고 FDL 버퍼와 뷰(필드와 구조체를 매핑시킨 파일)를 이용하기 위해서는 사전 작업이 필요하다.
cobolsanple.tar의 압축을 해제하면 뷰 예제는 ucblinc 디렉터리에 viewdemo.v 파일이고, FDL 예제는 fdldemo.f 파일이다.
Fdl : $TMAXDIR/ucblinc/fdldemo.f View : $TMAXDIR/ucblinc/viewdemo.v
2.1. FDL 생성
클라이언트 또는 서버에서 사용할 FIELD 정보들을 생성한다.
<fdldemo.f>
# name number type flags comments # string type FDL_S1 1001 string - - FDL_S2 1002 string - - # integer type FDL_I1 2001 int - - FDL_I2 2002 int - - # long type FDL_L1 3001 long - - FDL_L2 3002 long - - # float type FDL_F1 4001 float - - FDL_F2 4002 float - -
output으로 생성된 tmax.fdl 파일은 환경변수에 지정한 $FDLFILE에 지정된 디렉터리에 위치시킨다.
cobolsample.tar 파일을 이용하는 경우에는 $TMAXDIR/ucblinc 디렉터리에 fdldemo.f 파일이 생성되므로, 이 디렉터리에서 fdlc 작업을 수행하여 $FDLFILE에 $TMAXDIR/ucblinc가 지정되도록 한다.
$fdlc –c –i fdldemo.f –o tmax.fdl
필드 버퍼 사용에 관련된 자세한 정보는 Tmax 안내서 중에 Tmax FDL Reference Guide를 참고한다. |
2.2. 뷰 파일 생성
COBOL에서는 필드 버퍼를 사용할 수 없기 때문에 뷰(구조체)를 생성하여 요청자로부터 전달된(또는 전달할) 필드 버퍼의 내용을 특정 함수를 이용하여 변환할 때 사용한다.
<viewdemo.v>
VIEW viewdemo #type cname Fldkey count flag size null string sdata1 FDL_S1 1 - 20 "@@" string sdata2 FDL_S2 5 - 20 "@@" int idata1 FDL_I1 1 - - 0 int idata2 FDL_I2 5 - - 0 long ldata1 FDL_L1 1 - - 0 long ldata2 FDL_L2 5 - - 0 float fdata1 FDL_F1 1 - - 0 float fdata2 FDL_F2 5 - - 0 double ddata1 FDL_D1 1 - - 0 double ddata2 FDL_D2 5 - - 0 END
output으로 생성된 tmax.sdl 파일은 환경변수에 지정한 $SDLFILE에 정의한 디렉터리에 위치시킨다.
cobolsample.tar 파일을 이용하는 경우에는 $TMAXDIR/ucblinc 디렉터리에 viewdemo.v 파일이 생성되므로 이 디렉터리에서 sdlc 작업을 수행하여 $SDLFILE에 $TMAXDIR/ucblinc가 지정되도록 한다.
$cd $TMAXDIR/ucblinc $ sdlc -c -v viewdemo.v -o tmax.sdl $ ls -l -rw-r-xr-- 1 tmax dba 382 Apr 28 17:27 viewdemo.v* -rw-r--r-- 1 tmax dba 976 May 7 18:17 tmax.sdl
2.3. COBOL용 뷰 파일 생성
COBOL용 뷰 파일을 생성한다.
$ sdlc -C -v viewdemo.v $ls -l total 48 total 48 drwxr-xr-x 2 tmax dba 512 Apr 30 14:48./ drwxr-xr-x 7 tmax dba 512 Apr 14 11:50 ../ -rw-r--r-- 1 tmax dba 671 Apr 30 14:48 VIEWDEMO.cbl -rw-r-xr-- 1 tmax dba 382 Apr 28 17:27 viewdemo.v*
<VIEWDEMO.cbl>
* VIEWNAME: "viewdemo" 05 SDATA1 PIC X(20). 05 SDATA2 OCCURS 5 TIMES PIC X(20). 05 IDATA1 PIC S9(9) USAGE IS COMP-5. 05 IDATA2 OCCURS 5 TIMES PIC S9(9) USAGE IS COMP-5. 05 LDATA1 PIC S9(9) USAGE IS COMP-5. 05 LDATA2 OCCURS 5 TIMES PIC S9(9) USAGE IS COMP-5. 05 FDATA1 USAGE IS COMP-1. 05 FDATA2 OCCURS 5 TIMES USAGE IS COMP-1. 05 DDATA1 USAGE IS COMP-2. 05 DDATA2 OCCURS 5 TIMES USAGE IS COMP-2.
이 파일은 COBOL에서 COPY 명령어를 통해서 소스 내에서 이용되어야 하므로, $COBCPY에 지정된 디렉터리에 위치시킨다. cobolsample.tar 파일을 이용하는 경우에는 $TMAXIDIR/ucblinc 디렉터리에 이 파일이 위치하게 된다.
관리의 효율성을 위해서 Tmax에서 제공하는 COBOL용 헤더 파일과 분리하여 다른 디렉터리에 저장하는 것을 권장한다. |
"export COBCPY=$TMAXDIR/cobinc:$TMAXDIR/ucblinc"로 환경을 설정하고, 사용자가 생성한 뷰 파일들은 $TMAXDIR/ucblinc에 저장한다.
$TMAXDIR/ucblinc에는 아래의 파일들이 저장된다.
$ ls -l -rw-r--r-- 1 tmax dba 671 May 7 18:17 VIEWDEMO.cbl -rwxr-xr-- 1 tmax dba 381 Apr 30 15:10 fdldemo.f* -rw-r--r-- 1 tmax dba 755 May 6 23:59 fdldemo_fdl.h -rw-r--r-- 1 tmax dba 3852 May 6 23:59 tmax.fdl -rw-r--r-- 1 tmax dba 976 May 7 20:13 tmax.sdl -rw-r--r-- 1 tmax dba 996 May 7 00:56 viewdemo.sdl -rw-r-xr-- 1 tmax dba 385 May 7 18:17 viewdemo.v* -rw-r--r-- 1 tmax dba 574 May 7 20:13 viewdemo_sdl.h -rw-r--r-- 1 tmax dba 571 Apr 30 14:53 viewdemo_sdl.h
2.4. 예제 프로그램
다음은 필드 버퍼를 이용하여 서비스 프로그램을 작성하는 예제이다.
<$TMAXDIR/sample/cobserver/fdlins.pco>
****************************************************** * FDL 버퍼를 사용하는 서비스 ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. FDLINS. AUTHOR. TMAX DEVELOPMENT. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. FILE SECTION. WORKING-STORAGE SECTION. ****************************************************** * TMAX ATMI 함수를 위한 definitions ****************************************************** 01 TPSVCRET-REC. COPY TPSVCRET. * 01 TPTYPE-REC. COPY TPTYPE. * 01 TPSTATUS-REC. COPY TPSTATUS. * 01 TPSVCDEF-REC. COPY TPSVCDEF. * 01 FML-REC. COPY FMLINFO. ****************************************************** * Log message definitions ****************************************************** 01 LOGMSG. 05 LOGMSG-SVC PIC X(16). 05 FILLER PIC X(3) VALUES " : ". 05 LOGMSG-TEXT PIC X(50). 01 LOGMSG-LEN PIC S9(9) COMP-5. ****************************************************** * User defined data records ****************************************************** 01 RECV-BUFFER. 03 RECV-ALIGN pic S9(9) COMP-5. 03 RECV-DATA pic x(1000). 01 SEND-BUFFER. 03 SEND-ALIGN pic S9(9) COMP-5. 03 SEND-DATA pic x(1000). 01 VIEWDEMO. COPY VIEWDEMO. LINKAGE SECTION. * PROCEDURE DIVISION. * 000-MAIN. PERFORM 100-SVCSTART THRU 100-EXIT. PERFORM 200-FDL2VIEW THRU 200-EXIT. PERFORM 300-VIEW2FDL THRU 300-EXIT. PERFORM 900-TPRETURNSCS THRU 900-TPRETURNSCS-X. 000-EXIT. ****************************************************** * 클라이언트로부터 전송된 데이터를 수신 ****************************************************** 100-SVCSTART. MOVE LENGTH OF RECV-BUFFER TO LEN. CALL "TPSVCSTART" USING TPSVCDEF-REC TPTYPE-REC RECV-BUFFER TPSTATUS-REC. IF NOT TPOK MOVE "TPSVCSTART Fail" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. IF TPTRUNCATE MOVE "Received data was truncated" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. DISPLAY "------------------------------------------------". MOVE SERVICE-NAME TO LOGMSG-SVC. MOVE "서비스 시작 " TO LOGMSG-TEXT. PERFORM 800-USERLOG. 100-EXIT. ****************************************************** * FIELD 버퍼의 내용을 struct로 이동 ****************************************************** 200-FDL2VIEW. * viewname, FML-LENGTH 를 반드시 지정해야 한다. MOVE "viewdemo" TO VIEWNAME. MOVE LEN TO FML-LENGTH. * FIELD buffer의 데이터를 COBOL structure로 넘김 CALL "FVFTOS" USING RECV-BUFFER VIEWDEMO FML-REC. IF NOT FOK MOVE "FVFTOS FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. 200-EXIT. ****************************************************** * struct의 내용을 FIELD 버퍼로 이동 ****************************************************** 300-VIEW2FDL. * FML-LENGTH 를 반드시 사용해야 한다. MOVE LENGTH OF SEND-BUFFER TO FML-LENGTH. CALL "FINIT" USING SEND-BUFFER FML-REC. IF NOT FOK MOVE "FINIT FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. MOVE "TEST STRING" TO SDATA1. MOVE "TEST STRING1" TO SDATA2(1). MOVE "TEST STRING2" TO SDATA2(2). MOVE "TEST STRING3" TO SDATA2(3). compute idata1 = idata1 + 10. compute idata2(1) = idata2(1) + 10. compute idata2(2) = idata2(2) + 10. compute idata2(3) = idata2(3) + 10. compute idata2(4) = idata2(4) + 10. compute ldata1 = ldata1 + 10. compute ldata2(1) = ldata2(1) + 10. compute ldata2(2) = ldata2(2) + 10. compute ldata2(3) = ldata2(3) + 10. compute ldata2(4) = ldata2(4) + 10. compute fdata1 = fdata1 + 10. compute fdata2(1) = fdata2(1) + 10. compute fdata2(2) = fdata2(2) + 10. compute fdata2(3) = fdata2(3) + 10. compute fdata2(4) = fdata2(4) + 10. compute ddata1 = ddata1 + 10. compute ddata2(1) = ddata2(1) + 10. compute ddata2(2) = ddata2(2) + 10. compute ddata2(3) = ddata2(3) + 10. compute ddata2(4) = ddata2(4) + 10. * COBOL structure의 데이터를 FDL buffer 로 넘김 MOVE "viewdemo" TO VIEWNAME. SET FUPDATE TO TRUE. CALL "FVSTOF" USING SEND-BUFFER VIEWDEMO FML-REC. IF NOT FOK MOVE "FVSTOF FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. 300-EXIT. ****************************************************** * Write out a log err messages ****************************************************** 800-USERLOG. DISPLAY LOGMSG. ****************************************************** * 성공적으로 서비스가 종료 ****************************************************** 900-TPRETURNSCS. MOVE "서비스가 성공적으로 끝났음" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPSUCCESS TO TRUE. MOVE LENGTH OF SEND-BUFFER TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-BUFFER. 900-TPRETURNSCS-X. ****************************************************** * 비정상적으로 서비스가 종료 ****************************************************** 900-TPRETURNFAIL. MOVE "서비스가 비정상적으로 처리" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPFAIL TO TRUE. MOVE "처리불가 " TO SDATA1. MOVE LENGTH OF SEND-BUFFER TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-BUFFER. 900-TPRETURNFAIL-X.
다음은 각 단계에 대한 설명이다.
-
필드를 선언한다.
RECV-BUFFER/SEND-BUFFER는 서비스 호출자로부터 전송된 데이터를 받거나 보낼 때 사용하는 버퍼이고 VIEWDEMO는 필드 버퍼와 뷰를 상호 전환할 때 사용하는 구조체이다.
01 FML-REC. COPY FMLINFO. ****************************************************** * User defined data records ****************************************************** 01 RECV-BUFFER. 03 RECV-ALIGN pic S9(9) COMP-5. 03 RECV-DATA pic x(1000). 01 SEND-BUFFER. 03 SEND-ALIGN pic S9(9) COMP-5. 03 SEND-DATA pic x(1000). 01 VIEWDEMO. COPY VIEWDEMO. * VIEWFILE: "viewdemo.v" * VIEWNAME: "viewdemo" * * 05 SDATA1 PIC X(20). * 05 SDATA2 OCCURS 5 TIMES PIC X(20) * 05 IDATA1 PIC S9(9) USAGE IS COMP-5. * 05 IDATA2 OCCURS 10 TIMES PIC S9(9) USAGE IS COMP-5. * 05 LDATA1 PIC S9(9) USAGE IS COMP-5. * 05 LDATA2 OCCURS 5 TIMES PIC S9(9) USAGE IS COMP-5. * 05 FDATA1 USAGE IS COMP-1. * 05 FDATA2 OCCURS 10 TIMES USAGE IS COMP-1. * 05 DDATA1 USAGE IS COMP-2. * 05 DDATA2 OCCURS 10 TIMES USAGE IS COMP-2.
-
클라이언트로부터 필드 버퍼를 전달받는다.
서비스 호출자로부터 전송된 데이터를 받기위해서는 반드시 서비스가 시작될 때 가장 처음에 TPSVCSTART를 수행해야만 한다.
****************************************************** * 클라이언트로부터 전송된 데이터를 수신 ****************************************************** 100-SVCSTART. MOVE LENGTH OF RECV-BUFFER TO LEN. CALL "TPSVCSTART" USING TPSVCDEF-REC TPTYPE-REC RECV-BUFFER TPSTATUS-REC. IF NOT TPOK MOVE "TPSVCSTART Fail" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. IF TPTRUNCATE MOVE "Received data was truncated" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. DISPLAY "------------------------------------------------". MOVE SERVICE-NAME TO LOGMSG-SVC. MOVE "서비스 시작 " TO LOGMSG-TEXT. PERFORM 800-USERLOG. 100-EXIT.
-
FIELD 버퍼를 구조체로 변환한다.
서비스 호출자로부터 전송받은 필드 버퍼의 데이터를 COBOL에서 사용할 구조체로 변환할 때 사용한다. 서비스 호출자가 필드 버퍼에 보낸 데이터가 FVFTOS를 통하여 COBOL의 구조체에 저장된다. array를 사용할 때 전송된 데이터 갯수가 array 개수에 모자라는 경우에는 뷰 파일에서 정의한 기본값이 채워진다.
****************************************************** * FIELD 버퍼의 내용을 구조체로 이동 ****************************************************** 200-FDL2VIEW. * viewname, FML-LENGTH를 반드시 지정해야 한다. MOVE "viewdemo" TO VIEWNAME. MOVE LEN TO FML-LENGTH. * FIELD buffer의 데이터를 COBOL structure로 넘김 CALL "FVFTOS" USING RECV-BUFFER VIEWDEMO FML-REC. IF NOT FOK MOVE "FVFTOS FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. 200-EXIT.
-
COBOL 소스에서 비즈니스 로직을 수행할 데이터를 조작한다.
MOVE "TEST STRING" TO SDATA1. MOVE "TEST STRING1" TO SDATA2(1). MOVE "TEST STRING2" TO SDATA2(2). MOVE "TEST STRING3" TO SDATA2(3). …… compute ddata1 = ddata1 + 10. compute ddata2(1) = ddata2(1) + 10. compute ddata2(2) = ddata2(2) + 10. compute ddata2(3) = ddata2(3) + 10. compute ddata2(4) = ddata2(4) + 10.
-
전송할 때 사용할 필드 버퍼 생성한다.
서비스 호출자에게 데이터를 전송할 때 사용할 버퍼는 받은 버퍼를 그대로 사용해도 되고, 새로운 버퍼를 생성하여 사용해도 된다. 새로운 버퍼를 사용하는 경우에는 FINIT을 사용한다.
****************************************************** * struct의 내용을 FIELD 버퍼로 이동 ****************************************************** 300-VIEW2FDL. * FML-LENGTH 를 반드시 사용해야 한다. MOVE LENGTH OF SEND-BUFFER TO FML-LENGTH. CALL "FINIT" USING SEND-BUFFER FML-REC. IF NOT FOK MOVE "FINIT FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF.
-
구조체를 필드 버퍼로 변환한다.
서비스 호출자에게 필드 타입의 데이터를 전송하기 위해서 COBOL에서 사용한 구조체 데이터를 필드 타입의 데이터로 변환한다.
MOVE "viewdemo" TO VIEWNAME. SET FUPDATE TO TRUE. CALL "FVSTOF" USING SEND-BUFFER VIEWDEMO FML-REC. IF NOT FOK MOVE "FVSTOF FAILED " TO LOGMSG-TEXT DISPLAY "FML-STATUS : " FML-STATUS PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. 300-EXIT.
-
클라이언트로 데이터 전송한다.
서비스가 정상적으로 수행된 경우에는 TPRETURN할 때 TUSUCCESS 값을 이용해야 한다.
****************************************************** * 성공적으로 서비스가 종료 ****************************************************** 900-TPRETURNSCS. MOVE "서비스가 성공적으로 끝났음" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPSUCCESS TO TRUE. MOVE LENGTH OF SEND-BUFFER TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-BUFFER. 900-TPRETURNSCS-X.
서비스가 비정상적으로 수행된 경우에는 TPRETURN할 때 TUFAIL 값을 이용해야 한다.
****************************************************** * 비정상적으로 서비스가 종료 ****************************************************** 900-TPRETURNFAIL. MOVE "서비스가 비정상적으로 처리" TO LOGMSG-TEXT. PERFORM 800-USERLOG. SET TPFAIL TO TRUE. MOVE "처리불가 " TO SDATA1. MOVE LENGTH OF SEND-BUFFER TO LEN. COPY TPRETURN REPLACING DATA-REC BY SEND-BUFFER. 900-TPRETURNFAIL-X.
2.5. 서비스 호출 테스트
tmd 유틸리티를 이용하여 클라이언트 프로그램의 작성없이 서비스를 호출한다.
$ cd TMAXDIR/sample/cobclient $ tmd -i tmd_FDLINS fkey = 469763049, fname = FDL_S1, type = string, value = TEST STRING fkey = 469763050, fname = FDL_S2, type = string, value = TEST STRING1 fkey = 469763050, fname = FDL_S2, type = string, value = TEST STRING2 fkey = 469763050, fname = FDL_S2, type = string, value = TEST STRING3 fkey = 201328593, fname = FDL_I1, type = int, value = 20 fkey = 201328594, fname = FDL_I2, type = int, value = 30 fkey = 201328594, fname = FDL_I2, type = int, value = 10 fkey = 201328594, fname = FDL_I2, type = int, value = 10 fkey = 201328594, fname = FDL_I2, type = int, value = 10 fkey = 268438457, fname = FDL_L1, type = long, value = 10010 fkey = 268438458, fname = FDL_L2, type = long, value = 100010 fkey = 268438458, fname = FDL_L2, type = long, value = 200010 fkey = 268438458, fname = FDL_L2, type = long, value = 300010 fkey = 268438458, fname = FDL_L2, type = long, value = 10 fkey = 335548321, fname = FDL_F1, type = float, value = 20.123451 fkey = 335548322, fname = FDL_F2, type = float, value = 30.123449 fkey = 335548322, fname = FDL_F2, type = float, value = 10.000000 fkey = 335548322, fname = FDL_F2, type = float, value = 10.000000 fkey = 335548322, fname = FDL_F2, type = float, value = 10.000000 fkey = 402658185, fname = FDL_D1, type = double, value = 100010.123450 fkey = 402658186, fname = FDL_D2, type = double, value = 200010.123450 fkey = 402658186, fname = FDL_D2, type = double, value = 10.000000 fkey = 402658186, fname = FDL_D2, type = double, value = 10.000000 fkey = 402658186, fname = FDL_D2, type = double, value = 10.000000
Tmax 환경 파일을 읽지 않으므로 사용자 프로파일에 저장된 TMAX_HOST_PORT, TMAX_HOST_ADDR, FDLFILE의 값을 확인한다. |
3. 전역 트랜잭션 프로그램
3.1. 예제 프로그램
다음은 전역 트랜잭션을 사용하는 서비스 프로그램에 대한 예제이이다.
<$TMAXDIR/sample/cobserver/carraynauto.pco>
****************************************************** * XA 이면서 CARRAY 버퍼를 사용하는 서비스 * ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. CARRAYNAUTO. …… WORKING-STORAGE SECTION. ****************************************************** * TMAX ATMI 함수를 위한 definitions ****************************************************** 01 TPSVCRET-REC. COPY TPSVCRET. * 01 TPTYPE-REC. COPY TPTYPE. * 01 TPSTATUS-REC. COPY TPSTATUS. * 01 TPSVCDEF-REC. COPY TPSVCDEF. * 01 TX-RETURN-STATUS. COPY TXSTATUS. …… PROCEDURE DIVISION. 000-MAIN. PERFORM 100-SVCSTART THRU 100-EXIT. PERFORM 200-DBINSERT THRU 200-EXIT. PERFORM 900-TPRETURNSCS THRU 900-TPRETURNSCS-X. 000-EXIT. 200-DBINSERT. MOVE RECV-STRING(1:LEN) TO S-TEMP-ARR. MOVE LENGTH OF S-TEMP-ARR TO S-TEMP-LEN. CALL "TXBEGIN" USING TX-RETURN-STATUS. IF NOT TPOK MOVE "FAIL TO TXBEGIN" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. * DB INSERT처리 EXEC SQL INSERT INTO TEMP (NAME,SAL) VALUES (RTRIM(:S-TEMP),150) END-EXEC. IF SQLCODE NOT = 0 PERFORM 800-SQLERROR PERFORM 800-USERLOG CALL "TXROLLBACK" USING TX-RETURN-STATUS IF NOT TPOK MOVE "txrollback ERROR " TO LOGMSG-TEXT PERFORM 800-USERLOG END-IF PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. CALL "TXCOMMIT" USING TX-RETURN-STATUS. IF NOT TPOK MOVE "TXCOMMIT ERROR" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. STRING "Inserted data : " S-TEMP-ARR DELIMITED BY SIZE INTO LOGMSG-TEXT. PERFORM 800-USERLOG. MOVE "성공적 처리" TO SEND-STRING. 200-EXIT.
다음은 각 단계별 설명이다.
-
전역 트랜잭션을 시작한다.
CALL "TXBEGIN" USING TX-RETURN-STATUS. IF NOT TPOK MOVE "FAIL TO TXBEGIN" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF.
-
전역 트랜잭션의 성공을 처리한다.
CALL "TXCOMMIT" USING TX-RETURN-STATUS. IF NOT TPOK MOVE "TXCOMMIT ERROR" TO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF.
-
전역 트랜잭션을 취소한다.
CALL "TXROLLBACK" USING TX-RETURN-STATUS IF NOT TPOK MOVE "txrollback ERROR " TO LOGMSG-TEXT PERFORM 800-USERLOG END-IF.
명시적 트랜잭션을 시작하는 서비스는 Tmax 환경 파일에서 "AUTOTRAN=N"(Tmax3.8.9 이후, default)으로 반드시 설정되어 있어야 한다. Tmax 환경 파일에 "AUTOTRAN=Y"로 설정되어 있으면, 서비스를 시작하면서 자동으로 전역 트랜잭션을 시작하게 되므로 서비스에서 명시적으로 TXBEGIN을 사용할 때 TPEPROTO 에러를 반환받게 된다.
"AUTOTRAN=N"으로 설정된 경우도 클라이언트에서 명시적 트랜잭션을 시작하고, 서비스에서도 명시적 트랜잭션을 시작하게되면 서비스에서 수행한 TXBEGIN은 TPEPROTO 에러를 반환받으므로 주의한다. |
4. TPSVRINIT/TPSVRDONE 사용
4.1. TPSVRINIT
TPSVRINIT는 Tmax 서버를 초기화하는 함수이다. 최초에 Tmax 서버가 기동할 때 1회만 수행된다. 일반적으로 Non-xa 서버 그룹에 속하는 서버들이 DB와 연결하는 로직을 수행한다. tpsvrinit.pco라는 이름으로 cobolsample.tar에 포함되어 있고, 컴파일 과정(.o를 생성)을 거쳐서 서버 프로그램 object와 함께 link된다.
<$TMAXDIR/sample/cobserver/tpsvrinit.pco>
****************************************************** * NXA 서버에서 DB(Resource Manager)와 연결을 맺는 용도로 사용 ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. TPSVRINIT. AUTHOR. TMAX DEVELOPMENT. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. FILE SECTION. WORKING-STORAGE SECTION. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 USERNAME PIC X(10) VARYING. 01 PASSWD PIC X(10) VARYING. EXEC SQL END DECLARE SECTION END-EXEC. EXEC SQL INCLUDE SQLCA END-EXEC. LINKAGE SECTION. 01 CMD-LINE. 05 ARGC PIC 9(4) COMP-5. 05 ARGV. 10 ARGS PIC X OCCURS 0 TO 9999 DEPENDING ON ARGC. 01 SERVER-INIT-STATUS. COPY TPSTATUS. * PROCEDURE DIVISION USING CMD-LINE SERVER-INIT-STATUS. * 000-TPSVRINIT-START. ****************************************************** * DB error check ****************************************************** EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. DISPLAY "ARGC : " ARGC, " ARGV: " ARGV. ****************************************************** * DB connect ****************************************************** MOVE "SCOTT" TO USERNAME-ARR. MOVE 5 TO USERNAME-LEN. MOVE "TIGER" TO PASSWD-ARR. MOVE 5 TO PASSWD-LEN. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWD END-EXEC. DISPLAY "CONNECTED TO ORACLE as User : " USERNAME-ARR. SET TPOK IN SERVER-INIT-STATUS TO TRUE. EXIT PROGRAM. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED:". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. SET TPEINVAL IN SERVER-INIT-STATUS TO TRUE. EXIT PROGRAM.
4.2. TPSVRDONE
TPSVRDONE는 Tmax 서버를 종료하는 함수이다. Tmax 서버가 종료될 때 최후에 1회만 수행된다. 일반적으로 Non-XA 서버 그룹에 속하는 서버들이 DB연결을 해제하는 로직을 수행한다. tpsvrdone.pco라는 이름으로 cobolsample.tar에 포함되어 있고, 컴파일 과정(.o를 생성)을 거쳐서 서버 프로그램 object와 함께 link된다.
<$TMAXDIR/sample/cobserver/tpsvrdone.pco>
****************************************************** * NXA 서버에서 DB(Resource Manager)와 연결을 해제하는 용도로 사용 ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. TPSVRDONE. AUTHOR. TMAX DEVELOPMENT. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. FILE SECTION. WORKING-STORAGE SECTION. 01 SERVER-DONE-STATUS. COPY TPSTATUS. EXEC SQL INCLUDE SQLCA END-EXEC. * PROCEDURE DIVISION . * 000-TPSVRDONE-START. ****************************************************** * DB error check ****************************************************** EXEC SQL WHENEVER SQLERROR DO PERFORM SQL-ERROR END-EXEC. ****************************************************** * DB disconnect ****************************************************** EXEC SQL COMMIT WORK RELEASE END-EXEC. DISPLAY " ". DISPLAY "DISCONNECTED TO ORACLE ". SET TPOK IN SERVER-DONE-STATUS TO TRUE. EXIT PROGRAM. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY "ORACLE ERROR DETECTED :". DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. SET TPEINVAL IN SERVER-DONE-STATUS TO TRUE. EXIT PROGRAM.
5. 서비스에서 서비스 호출 프로그램
5.1. 예제 프로그램
다음은 서비스에서 서비스 호출하는 프로그램에 대한 예제이다.
< $TMAXDIR/sample/cobserver/svctpcall.pco >
****************************************************** * DB이용하지 않으면서 CARRAY 버퍼를 사용하는 서비스 * ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. SVCTPCALL. AUTHOR. TMAX DEVELOPMENT. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. FILE SECTION. WORKING-STORAGE SECTION. ****************************************************** * TMAX ATMI 함수를 위한 definitions ****************************************************** 01 TPSVCRET-REC. COPY TPSVCRET. * 01 TPTYPE-REC. COPY TPTYPE. * 01 TPSTATUS-REC. COPY TPSTATUS. * 01 TPSVCDEF-REC. COPY TPSVCDEF. ****************************************************** * Log message definitions ****************************************************** 01 LOGMSG. 05 LOGMSG-SVC PIC X(16). 05 FILLER PIC X(3) VALUES " : ". 05 LOGMSG-TEXT PIC X(50). 01 LOGMSG-LEN PIC S9(9) COMP-5. ****************************************************** * User defined data records ****************************************************** 01 RECV-STRING PIC X(100). 01 SEND-STRING PIC X(100). 77 NUM-TPSTATUS PIC 99. PROCEDURE DIVISION. * 000-MAIN. PERFORM 100-SVCSTART THRU 100-EXIT. PERFORM 200-TPCALL THRU 200-EXIT. PERFORM 900-TPRETURNSCS THRU 900-TPRETURNSCS-X. ****************************************************** * 클라이언트로부터 전송된 데이터를 수신 ****************************************************** 100-SVCSTART. …… 100-EXIT. ********************************************************** * tpcall in service ********************************************************** 200-TPCALL. MOVE "CARRAYNXA" TO SERVICE-NAME. MOVE LENGTH OF SEND-STRING TO LEN IN TPTYPE-REC. CALL "TPCALL" USING TPSVCDEF-REC TPTYPE-REC RECV-STRING TPTYPE-REC SEND-STRING TPSTATUS-REC . IF NOT TPOK MOVE "Service failed" TO LOGMSG-TEXT MOVE TP-STATUS TO NUM-TPSTATUS STRING "TPCALL call failed : " NUM-TPSTATUS DELIMITED BY SIZE INTO LOGMSG-TEXT PERFORM 800-USERLOG PERFORM 900-TPRETURNFAIL THRU 900-TPRETURNFAIL-X END-IF. 200-EXIT. ****************************************************** * Write out a log err messages ****************************************************** 800-USERLOG. DISPLAY LOGMSG. ****************************************************** * 성공적으로 서비스가 종료 ****************************************************** 900-TPRETURNSCS. …… 900-TPRETURNSCS-X. ****************************************************** * 비정상적으로 서비스가 종료 ****************************************************** 900-TPRETURNFAIL. …… 900-TPRETURNFAIL-X.
서비스 호출자는 Tmax 클라이언트 또는 서비스가 될 수 있다. Tmax 서비스에서도 또 다른 Tmax 서비스를 호출할 수 있다는 의미이다.
위의 예제처럼 또 다른 서비스를 호출하기 위해서는 TPCALL에서 주고받는 버퍼를 사용해야 한다.
MOVE "CARRAYNXA" TO SERVICE-NAME. MOVE LENGTH OF SEND-STRING TO LEN IN TPTYPE-REC. CALL "TPCALL" USING TPSVCDEF-REC TPTYPE-REC RECV-STRING TPTYPE-REC SEND-STRING TPSTATUS-REC