예제

본 장에서는 서비스 프로그램, 전역 트랜잭션 프로그램 등 예제 프로그램과 설명을 기술한다.

1. 서비스 프로그램

다음은 서비스 프로그램 작성 과정이다.

image

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.

다음은 각 단계별 세부 설명이다.

  1. 서비스명을 설정한다. 서비스 호출자가 TPCALL에서 사용할 서비스명은 PROGRAM-ID에서 정의한다.

    PROGRAM-ID. CARRAYAUTO.
  2. 버퍼를 정의한다.

    클라이언트와 데이터 송수신에 사용되는 버퍼를 정의한다. 서비스 호출자와 데이터를 주고받을 때 사용할 버퍼를 정의한다.

    ******************************************************
    * User defined data records
    ******************************************************
     01 RECV-STRING            PIC X(100).
             01 SEND-STRING            PIC X(100).
  3. 서비스를 시작한다. 서비스를 시작하면서 서비스 호출자가 보낸 데이터를 "버퍼 정의"에서 정의한 버퍼에 받아낸다.

    예제에서는 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.
  4. 성공적으로 서비스를 종료한다.

        SET TPSUCCESS TO TRUE.
        MOVE LENGTH OF SEND-STRING TO LEN.
        COPY TPRETURN REPLACING
        DATA-REC BY SEND-STRING.
  5. 로직의 에러로 실패를 반환한다.

    비즈니스 로직의 완료 후에 서비스호출자에게 응답을 주기 위해서는 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 벤더에서 제공하는 라이브러리들이 묶어서 하나의 실행 파일을 만든다.

다음은 실행 파일을 생성하는 과정이다.

image

  1. *.pco → *.cob

    ProCOBOL 프로그램을 precompile한다.

  2. *.cob → *.o

    COBOL 프로그램을 compile하여 오브젝트 파일 생성한다.

  3. *.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

다음은 각 단계에 대한 설명이다.

  1. 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
    1. procob18 또는 cob의 compile option은 운영체제별로 달라지므로 확인 후 작업한다. procob18에서 사용하는 option은 $ORACLE_HOME/precomp/demo/procob/demo_procob.mk 파일을 참고한다.

    2. carray_xa.sh에는 carrayauto.pco, carraynauto.pco를 pre-compile, compile 과정을 거치므로, 예제 프로그램에서 carrayauto.pco, carraynauto.pco가 모두 필요하다.

  2. 실행 파일을 만들기 위한 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에서 제공하는 라이브러리 파일명을 설정한다.

1.3. 서비스 컴파일 및 기동

Makefile의 생성이 완료되면 컴파일한다.

$ make -f carray_xa.mk

컴파일된 서버 프로그램을 기동한다.

$ tmboot -s carray_xa

1.4. 서비스 호출 테스트

tmd 유틸리티를 이용하여 클라이언트 프로그램의 작성없이 서비스를 테스트한다.

$TMAXDIR/cobclient 디렉터리에 포함되어 있는 tmd_CARRAYAUTO 파일을 이용하여 CARRAYAUTO 서비스를 테스트한다.

$ cd $TMAXDIR/cobclient
$ tmd -i t md_CARRAYAUTO
output: 성공적 처리

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.

다음은 각 단계에 대한 설명이다.

  1. 필드를 선언한다.

    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.
  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.
  3. 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.
  4. 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.
  5. 전송할 때 사용할 필드 버퍼 생성한다.

    서비스 호출자에게 데이터를 전송할 때 사용할 버퍼는 받은 버퍼를 그대로 사용해도 되고, 새로운 버퍼를 생성하여 사용해도 된다. 새로운 버퍼를 사용하는 경우에는 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.
  6. 구조체를 필드 버퍼로 변환한다.

    서비스 호출자에게 필드 타입의 데이터를 전송하기 위해서 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.
  7. 클라이언트로 데이터 전송한다.

    서비스가 정상적으로 수행된 경우에는 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.

다음은 각 단계별 설명이다.

  1. 전역 트랜잭션을 시작한다.

         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.
  2. 전역 트랜잭션의 성공을 처리한다.

         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.
  3. 전역 트랜잭션을 취소한다.

         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 에러를 반환받으므로 주의한다.

3.2. 서비스 컴파일 및 기동

서비스를 컴파일한다.

$ sh carray_xa.sh
$ make –f carray_xa.mk

컴파일된 서비스를 기동한다.

$ tmboot –s carray_xa

3.3. 서비스 호출 테스트

서비스 호출을 테스트한다.

$ cd $TMAXDIR/sample/cobclient
$ tmd -i t md_CARRAYNAUTO
output: 성공적 처리

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.

4.3. 서비스 컴파일 및 기동

서비스를 컴파일한다.

$ sh carray_nxa.sh
$ make -f carray_nxa.mk

컴파일 후 서버 carray_nxa를 기동한다.

$ tmboot -s carray_nxa

userlog 파일인 $TMAXDIR/log/ulog/carray_nxa.out로 서버의 동작을 확인할 수 있다.

ARGC : 00023 ARGV: carray_nxa scott tiger CONNECTED TO ORACLE as User : SCOTT

4.4. 서비스 호출 테스트

서비스 호출을 테스트한다.

$ cd $TMAXDIR/sample/cobclient
$ tmd -i tmd_CARRAYNXA
output: 성공적 처리 from CARRAYNXA

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

5.2. 서비스 컴파일 및 기동

서비스를 컴파일한다.

$ make -f svctpcall.mk

컴파일된 서비스를 기동한다.

$ tmboot -s svctpcall

5.3. 서비스 호출 테스트

서비스 호출을 테스트한다.

$ cd $TMAXDIR/sample/cobclient
$ tmd -i tmd_SVCTPCALL
output: 성공적 처리 from CARRAYNXA