UCS 사용 예제
UCS는 업무 특성에 따라 다양하게 프로그램화하여 사용한다. 본 장에서는 실제 UCS가 사용될 때 다양한 방법으로 프로그램화된 예제를 보여준다.
1. 프로그램 비정상 종료 관리
다음은 비정상 종료 프로그램(core)이 발생했을 때 해당 core 파일을 특정 디렉터리로 이동시키고 연결된 클라이언트에게 비정상 종료 프로그램의 정보를 전달하는 예제이다.
<ucs_svr1.c >
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <dirent.h> #include <fcntl.h> #include <usrinc/atmi.h> char _file_path[100]; int _cliid[10]; int tpsvrint(int argc, char *argv[]) { return 0; } int tpsvrdone() { return 0; } int usermain(int argc, char *argv[]) { int iRet, i; char core_file[50]; char server_name[50]; char cur_time[20]; char *str; /* init cliid */ for (i=0; i<10; i++) _cliid[i] = -1; strcpy(_file_path, argv[1]); sprintf(core_file, "%s/core", _file_path); while(1) { tpschedule(5); iRet = checkCoreFile(); if (iRet == 1) { iRet = getCoreName(core_file, server_name); iRet = getCurrentTime(cur_time); iRet = moveCoreFile(core_file, server_name, cur_time); str = (char *)tpalloc("STRING", NULL, 0); sprintf(str, "%s program core !!", server_name); for (i=0; i<10; i++) { if (_cliid[i] < 0) continue; iRet = tpsendtocli(_cliid[i], str, strlen(str), 0); if (iRet == -1) { printf("client close connect !!\n"); _cliid[i] = -1; } } for (i=0; i<10; i++) printf("cliid = %d - %d\n", i, _cliid[i]); tpfree(str); } } } int checkCoreFile() { char server_name[50]; char core_file[100]; struct dirent *dirent; DIR *dp; dp = opendir(_file_path); if (dp == NULL) { printf("%s directory is not found !\n", _file_path); return -1; } for (dirent = readdir(dp); dirent != NULL; dirent = readdir(dp)) { if ( (strlen(dirent->d_name) == 4) && (strncmp(dirent->d_name, "core", 4) == 0)) { closedir(dp); return 1; } } closedir(dp); return -1; } int getCoreName(char *filename, char *server) { int fd, cnt, i; char buf[6000]; fd = open(filename, O_RDONLY); #ifdef _HP cnt = read(fd, buf, 144); #endif #ifdef _SUN cnt = read(fd, buf, 132); #endif #ifdef _IBM cnt = read(fd, buf, 1759); #endif cnt = read(fd, buf, 1760); while(1) { cnt = read(fd, buf, 1); if (cnt != 1) return -1; *server++ = buf[0]; if (buf[0] == 0) break; } close(fd); } int getCurrentTime(char *cur_time) { struct tm *tm; time_t tnow; time(&tnow); tm = localtime(&tnow); sprintf(cur_time, "%04d%02d%02d%02d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } int moveCoreFile(char *core, char *server, char *time) { char cmd[100]; char file_name[50]; printf("server = [%s]\n", server); sprintf(file_name, "core_%s_%s", server, time); sprintf(cmd, "mv %s %s/%s", core, _file_path, file_name); system(cmd); return 0; } CONN_TERM(TPSVCINFO *msg) { int i; char *stdata; stdata = (char *)msg->data; for (i=0; i<10; i++) { if (_cliid[i] >= 0) continue; _cliid[i] = tpgetclid(); printf("connect client %d = %d\n", i, _cliid[i]); break; } tpreturn(TPSUCCESS, 0, (char *)stdata, 0, 0); }
2. 소켓을 이용한 비동기 통신 프로그램
다음은 클라이언트에서 들어오는 소켓을 수락하고, 수락한 소켓에서 들어오는 요청을 tpacall한 후에 그 결과를 다시 클라이언트에 전송하는 예제이다.
<ucs_svr2.c> usermain()
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <usrinc/atmi.h> #include <usrinc/ucs.h> #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif #define CLIENT_PORT 9345 #define HOST_ADDR "61.33.32.107" #define MAX_BUFFER_LEN 4096 /* ----------------------- global variable --------------------------- */ int client_fd = -1; char ip_addr[30]; int portno; extern int _cur_clhfd; /* ----------------------- service initial -------------------------- */ tpsvrinit(int argc, char *argv[]) { sleep(5); parse_args(argc, argv); client_fd = network_connect(ip_addr, portno); if (client_fd > 0) tpsetfd(client_fd); printf("ucs_sample:client_fd = %d\n", client_fd); printf("ucs_sample: _cur_clhfd(1) = %d\n", _cur_clhfd); } tpsvrdone() { if (client_fd > 0) { tpclrfd(client_fd); close(client_fd); } } /* ----------------------- main ------------------------------------- */ int usermain(int argc, char *argv[]) { int n; /* never return */ while(1) { if (client_fd < 0) { client_fd = network_connect(ip_addr, portno); if (client_fd > 0) tpsetfd(client_fd); else { tpschedule(5); continue; } } printf("ucs_sample:client_fd = %d\n", client_fd); printf("ucs_sample: _cur_clhfd(1) = %d\n", _cur_clhfd); if ((n = tpschedule(0)) < 0) { sleep(1); continue; } printf("ucs_sample: _cur_clhfd(2) = %d\n", _cur_clhfd); if (tpissetfd(client_fd)) { if ((n = request_from_client(client_fd)) < 0) { tpclrfd(client_fd); close(client_fd); client_fd = -1; } } } } /* ----------------------- command argument ------------------------- */ int parse_args(int argc, char *argv[]) { int c; portno = -1; memset(ip_addr, 0x00, sizeof(ip_addr)); opterr = 0; /* don't want getopt() writing to stderr */ while ((c = getopt(argc, argv, "i:p:")) != EOF) { switch (c) { case 'p': /* port */ portno = atoi(optarg); break; case 'i': /* ip-addr */ strcpy(ip_addr, optarg); break; case '?': printf("unrecognized option: -%c", optopt); } } /* default value: portno, shared memory key */ if (portno <= 0) { portno = CLIENT_PORT; printf("no PORT is set: assumed %d\n", portno); } if (ip_addr[0] == 0x00) { strcpy(ip_addr, HOST_ADDR); printf("no IP-ADDR is set: assumed %s\n", ip_addr); } return 1; } /* ----------------------- client request --------------------------- */ int request_from_client(int fd) { int n, len; char *ptr, buffer[MAX_BUFFER_LEN]; /* read header */ memset(buffer, 0x00, sizeof(buffer)); n = socket_read(fd, buffer, 4); if (n <= 0) return -1; len = atoi(buffer); printf("ucs_sample:length : %d\n", len); /* read data */ n = socket_read(fd, &buffer[4], len); if (n <= 0) { return -1; } sleep(3); len += 4; n = socket_write(fd, buffer, len); printf("ucs_sample:socket write : n=%d\n", n); return n; } /* ------------------- client connect for TCP/IP ------------------ */ int network_connect(char *host, int port) { struct sockaddr_in serv_addr; unsigned long inaddr; struct hostent *hp; int i, fd; memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); /* First try to convert the host name as a dotted-decimal number. * Only if that fails do we call gethostbyname(). */ if ((inaddr = inet_addr(host)) != INADDR_NONE) { /* it's dotted-decimal */ memcpy((char *) &serv_addr.sin_addr, (char *) &inaddr, sizeof(inaddr)); } else { if ((hp = gethostbyname(host)) == NULL) { printf("host name error: %s\n", host); return(-1); } memcpy((char *) &serv_addr.sin_addr, hp->h_addr, hp->h_length); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("can't open stream socket\n"); return -1; } if (connect(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) >= 0) return fd; close(fd); return -1; } /* ------------------- data read ---------------------------------- */ int socket_read(int fd, char *ptr, int nbytes) { int nleft, nread; char *ptr2; ptr2 = (char *)ptr; nleft = nbytes; while (nleft > 0) { nread = recv(fd, ptr, nleft, 0); if (nread < 0) { if (errno == EINTR) continue; else if (errno == EWOULDBLOCK) return (nbytes - nleft); return(nread); /* error, return < 0 */ } else if (nread == 0) break; /* EOF */ nleft -= nread; ptr += nread; } return (nbytes - nleft); /* return >= 0 */ } /* ------------------- data write --------------------------------- */ int socket_write(int fd, char *ptr, int nbytes) { int nleft, nwritten; nleft = nbytes; while (nleft > 0) { nwritten = send(fd, ptr, nleft, 0); if (nwritten <= 0) return(nwritten); /* error */ nleft -= nwritten; ptr += nwritten; } return(nbytes - nleft); }
3. RQ를 사용한 프로그램
다음은 Fail 큐에 쌓인 데이터를 dequeue하여 다시 호출하는 프로그램 예제이다.
<ucs_svr3.c>
#include <sys/types.h> /* required for some of our prototypes */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> #include <usrinc/atmi.h> #include <usrinc/tmaxapi.h> #define MAX_BUF_SZ 10000 #define SZ 100 #define QUEFILE "rq1" #define QUESERVICE "+fail" int usermain(int argc, char*argv[]) { char svc[XATMI_SERVICE_NAME_LENGTH]; long len, n; int try, iFailCnt; char *ptr; char QueFile[SZ]; char QueService[SZ]; strcpy(QueFile, QUEFILE); strcpy(QueService, QUESERVICE); ptr = (char *)tpalloc("CARRAY", NULL, MAX_BUF_SZ); while (1) { /* Endless Loop */ tpschedule(10); /* Sleep 10 seconds */ n = 0; try = 0; iFailCnt = tpqstat(QueFile, TMAX_FAIL_QUEUE); while( (n >= 0) && (try++ < iFailCnt ) ) { n = tpdeq(QueFile, QueService, &ptr, &len, TPRQS ); if (n < 0 ) { if (tperrno == TPEMATCH) /* Fail Q empty */ ; else printf("tpdeq fail[%s]\n", tpstrerror(tperrno)); continue; } n = tpextsvcname((char*)ptr, svc); if (n < 0) { printf("tpextsvcname fail![%s]\n", tpstrerror(tperrno)); continue; } n = tpenq(QueFile, svc, (char*)ptr, len, TPRQS); if (n < 0) { printf("tpenq fail![%s]\n", tpstrerror(tperrno)); continue; } } } return 1; }
4. 클라이언트 대 서버 프로그램
다음은 서버 프로그램에서 루프를 수행하다가 클라이언트에서 LOGIN 서비스를 요청하면 UCS가 응답을 보내주는 예제이다.
설정 파일
*DOMAIN tmax1 SHMKEY =79970, MINCLH=1, MAXCLH=3, TPORTNO=8844, BLOCKTIME=120 *NODE tmaxs2 TMAXDIR = "/user/jaya/tmax3511", APPDIR = "/user/jaya/tmax3511/appbin", PATHDIR = "/user/jaya/tmax3511/path", TLOGDIR = "/user/jaya/tmax3511/log/tlog", ULOGDIR = "/user/jaya/tmax3511/log/ulog", SLOGDIR = "/user/jaya/tmax3511/log/slog" *SVRGROUP tmaxs2_nx NODENAME = "tmaxs2" *SERVER ucs_server SVGNAME = tmaxs2_nx, SVRTYPE = UCS *SERVICE LOGIN SVRNAME = ucs_server
클라이언트 프로그램
다음은 클라이언트 프로그램의 수행과정에 대한 설명이다.
-
클라이언트 프로그램은 실행하면 tpstart()를 하고 LOGIN이라는 서비스를 tpcall()하여, UCS 프로세스에 서비스를 요청한다.
-
클라이언트 프로그램에 설정된 tpsetunsol_flag(TPUNSOL_POLL);은 서버 프로세스에서 보내는 메시지를 받겠다는 의미이다.
-
클라이언트 프로그램은 서버 프로세스에서 sndbuf에 담아 보낸 "Client Registration Success"라는 메시지를 rcvbuf에서 받아 출력한다.
printf("After tpcall() received Message from server:%s\n", rcvbuf);
-
클라이언트에서 요청이 있으면 서버 프로세스의 loop count가 증가하고, count가 증가하면서 서버 프로세스의 for loop에서 sndbuf에 담아보낸 "Success tpsendtocli [0]" 메시지가 마찬가지로 클라이언트에서도 while loop에서 loop count가 증가하면서 출력된다.
while(1) { tpgetunsol(UNSOL_TPSENDTOCLI, &rcvbuf, &rcvlen, TPBLOCK); printf("Loop Count : %d\n", RecvCnt); if(rcvlen > 0) { printf("Counter : %d #[Received Data from Server : %s]\n", RecvCnt, rcvbuf); RecvCnt ++; } }
다음은 클라이언트 프로그램의 예제이다.
#include <stdio.h> #include <usrinc/atmi.h> #include <usrinc/ucs.h> main(int argc, char *argv[]) { char *sndbuf; char *rcvbuf; long rcvlen; int RecvCnt = 0; if(tpstart((TPSTART_T *)NULL) == -1) { error processing… } tpsetunsol_flag(TPUNSOL_POLL); if((sndbuf = (char *)tpalloc("CARRAY", NULL, 1024)) == NULL) { error processing… } if((rcvbuf = (char *)tpalloc("CARRAY", NULL, 1024)) == NULL) { error processing… } if(tpcall("LOGIN", sndbuf, 1024, &rcvbuf, &rcvlen, 0) == -1) { error processing… } printf("After tpcall() received Message from server:%s\n", rcvbuf); while(1) { tpgetunsol(UNSOL_TPSENDTOCLI, &rcvbuf, &rcvlen, TPBLOCK); printf("Loop Count : %d\n", RecvCnt); if(rcvlen > 0) { printf("Counter : %d #[Received Data from Server : %s]\n", RecvCnt, rcvbuf); RecvCnt ++; } if (RecvCnt == 10) break; } tpfree((char *)sndbuf); tpfree((char *)rcvbuf); tpend(); }
클라이언트 프로그램 예제의 결과는 다음과 같다.
tmaxs2:/user/jaya/tmax3511/sample/client>ucs_client After tpcall() received Message from server:Client Registration Success Loop Count : 0 Counter : 0 #[Received Data from Server : Success tpsendtocli [0]] Loop Count : 1 Counter : 1 #[Received Data from Server : Success tpsendtocli [1]] Loop Count : 2 Counter : 2 #[Received Data from Server : Success tpsendtocli [2]] Loop Count : 3 Counter : 3 #[Received Data from Server : Success tpsendtocli [3]] Loop Count : 4 Counter : 4 #[Received Data from Server : Success tpsendtocli [4]]
서버 프로그램
다음은 서버 프로그램의 수행과정에 대한 설명이다.
-
서버 프로그램은 Tmax가 기동된 후부터 5초를 sleep하고 클라이언트에서 요청이 있을 때까지 "loop execute…0"을 출력하며 계속 무한 루프를 한다.
sleep(5); printf ("loop execute... %d\n", count);
무한 루프를 하다가 while loop의 마지막 줄에 있는 jobs = tpschedule(-1); 부분에서 클라이언트에서 보낸 요청이 있는지 확인하고, 요청이 없으면 다시 루프하지만 요청이 있을 때에는 그 요청을 받아들이게 된다.
client_id[num_cli] = tpgetclid(); printf("client id(clid) = %d\n", client_id[num_cli]); num_cli++;
-
저장된 클라이언트의 ID 값으로 while loop의 for loop에서는 count 수가 증가하고 그 증가되는 값을 sndbuf에 담아 tpsendtocli() 함수를 사용하여 클라이언트에 서비스를 수행한다.
for (i = 0; i < num_cli; i++) { sprintf(sndbuf, "Success tpsendtocli [%d]", count++); /* 클라이언트 ID를 참조하여 고객에게 데이터를 보내는 부분 */ tpsendtocli (client_id[i], sndbuf, 1024, 0); }
-
sndbuf에 클라이언트가 등록되었다는 메시지를 담아 tpreturn() 한다.
sprintf(sndbuf, "Client Registration Success"); tpreturn(TPSUCCESS, 0, (char *)sndbuf, 1000, 0);
다음은 서버 프로그램의 예제이다.
#include <stdio.h> #include <usrinc/atmi.h> #include <usrinc/ucs.h> #define MAX_CLI 100 int num_cli; int client_id[MAX_CLI]; int count; tpsvrinit(int argc, char *argv[]) { num_cli = 0; count = 0; printf("UCS Type Server tpsvrinit() is call\n"); } /* Tmax의 UCS 모드에서 main과 같은 부분 */ int usermain(int argc, char *argv[]) { int jobs; int i; int ret; char *sndbuf; static int count = 0; printf("usermain start\n"); sndbuf = (char *)tpalloc("CARRAY", NULL, 1024); while(1) { sleep(5); printf ("loop execute... %d\n", count); for (i = 0; i < num_cli; i++) { sprintf(sndbuf, "Success tpsendtocli [%d]", count++); /* 클라이언트 ID를 참조하여 고객에게 데이터를 보내는 부분 */ tpsendtocli (client_id[i], sndbuf, 1024, 0); } jobs = tpschedule(-1); /* while 마지막에 반드시 있어야 함 */ } } LOGIN(TPSVCINFO *msg) { char *sndbuf; int clid; int ret; int i; sndbuf = (char *)tpalloc("CARRAY", NULL, 1024); if (num_cli < MAX_CLI) { /* 클라이언트의 ID 값을 보관하는 부분 */ client_id[num_cli] = tpgetclid(); printf("client id(clid) = %d\n", client_id[num_cli]); num_cli++; } sprintf(sndbuf, "Client Registration Success"); tpreturn(TPSUCCESS, 0, (char *)sndbuf, 1000, 0); } tpsvrdone() { }
결과
서버 프로그램 예제의 결과는 다음과 같다.
usermain start UCS Type Server tpsvrinit() is call usermain start loop execute... 0 loop execute... 0 loop execute... 0 client id(clid) = 2097152 loop execute... 0 loop execute... 1 loop execute... 2 loop execute... 3 loop execute... 4 loop execute... 5 loop execute... 6 loop execute... 7 loop execute... 8 loop execute... 9 loop execute... 10 loop execute... 11 loop execute... 12 loop execute... 13 loop execute... 14 client id(clid) = 2097153 loop execute... 15 loop execute... 17 loop execute... 19 …..
5. 서버 대 서버 프로그램
다음은 3개의 서버 프로세스를 이용하여 하나의 프로세스는 UCS로 계속 루프하고, 다른 하나는 데이터베이스에서 데이터를 선택하여 또 다른 프로세스를 호출하여 다른 테이블에 삽입하는 예제 프로그램이다.
-
<ucssvr.c>는 UCS 프로세스로 mainsvr.pc에 있는 MAIN이라는 서비스를 계속 tpcall하는 프로그램이다.
-
UCS 프로세스로부터 tpcall을 받은 <mainsvr.pc>는 데이터베이스에 있는 test_sel이라는 테이블에서 첫 번째 데이터부터 선택하여 <inssvr.pc>에 있는 INS라는 서비스를 tpcall한다.
-
tpcall을 받은 <inssvr.pc>는 test_ins라는 테이블에 test_sel 테이블에서 선택해온 데이터를 삽입한다. 이 과정이 이루어지면 <mainsvr.pc>는 tx_commit()을 하고, test_sel 테이블에서 inssvr.pc에게 넘겨준 데이터를 삭제한다.
-
test_sel 테이블에 6개의 데이터가 있기 때문에 동일한 과정을 6번 반복한다.
-
삭제할 데이터가 없기 때문에 1403 에러가 발생한다.
설정 파일
*DOMAIN tmax1 SHMKEY =79970, MINCLH=1, MAXCLH=3, TPORTNO=8844, BLOCKTIME=120 *NODE tmaxs2 TMAXDIR = "/user/jaya/tmax3511", APPDIR = "/user/jaya/tmax3511/appbin", PATHDIR = "/user/jaya/tmax3511/path", TLOGDIR = "/user/jaya/tmax3511/log/tlog", ULOGDIR = "/user/jaya/tmax3511/log/ulog", SLOGDIR = "/user/jaya/tmax3511/log/slog" *SVRGROUP tmaxs2_nx NODENAME = "tmaxs2" ### tms for Oracle ### tmaxs2_xa NODENAME = "tmaxs2", DBNAME = ORACLE, OPENINFO = "Oracle_XA+Acc=P/scott/tiger+SesTm=60", TMSNAME = tms_ora *SERVER ucssvr SVGNAME = tmaxs2_nx, SVRTYPE = UCS, MIN = 1 mainsvr SVGNAME = tmaxs2_xa, MIN = 1 inssvr SVGNAME = tmaxs2_xa, MIN = 1 *SERVICE MAIN SVRNAME = mainsvr INS SVRNAME = ins
test_sel 테이블
SQL> select * from test_sel; A -------------------- aaaaa bbbbb ccccc ddddd eeeee fffff 6 rows selected. SQL> select * from test_ins; no rows selected
서버 프로그램
<ucssvr.c>
#include <stdio.h> #include <usrinc/atmi.h> #include <unistd.h> int usermain(int argc, char *argv[]) /* Tmax의 UCS 모드에서 main과 같은 부분 */ { int ret; int jobs; long len; char *sndbuf, *rcvbuf; printf("usermain start\n"); sndbuf = (char *)tpalloc("STRING", NULL, 0); rcvbuf = (char *)tpalloc("STRING", NULL, 0); while(1) { ret = tpcall("MAIN", sndbuf, 0, &rcvbuf, &len, 0); if (ret == -1) { error processing… } jobs = tpschedule(-1); sleep (10); } }
<mainsvr.pc>
#include <stdio.h> #include <ctype.h> #include <usrinc/atmi.h> EXEC SQL include sqlca.h; #define MAXROW 6 EXEC SQL begin declare section; varchar v_a[MAXROW][11]; EXEC SQL end declare section; MAIN(TPSVCINFO *msg) { char *sndbuf, *rcvbuf; int i=0, errno; long len, ret; printf("[mainsvr] START\n"); printf("[mainsvr] CURSOR DECLARE\n"); EXEC SQL DECLARE cur_test_sel CURSOR FOR SELECT NVL(a,' ') FROM test_sel WHERE rownum <= 6; printf("[mainsvr] CURSOR OPEN\n"); EXEC SQL OPEN cur_test_sel; printf("[mainsvr] open cursor error : %d\n", sqlca.sqlcode); if ( sqlca.sqlcode != 0 ){ error processing… } printf("[mainsvr] CURSOR FETCH\n"); EXEC SQL FETCH cur_test_sel into :v_a; if (sqlca.sqlcode < 0) { errno = sqlca.sqlcode; printf("[mainsvr] Fetch error : %d", errno); printf("[mainsvr] CURSOR CLOSE\n"); EXEC SQL CLOSE cur_test_sel; printf("[mainsvr] TPRETURN FAIL\n"); tpreturn( TPFAIL, errno, (char *)NULL, 0, 0 ); } printf("[mainsvr] CURSOR CLOSE\n"); EXEC SQL CLOSE cur_test_sel; for(i=0; i<MAXROW; i++) { sndbuf = (char *)tpalloc("STRING", 0, 0); rcvbuf = (char *)tpalloc("STRING", 0, 0); v_a[i].arr[v_a[i].len] = 0; strcpy(sndbuf, v_a[i].arr); printf("[mainsvr] %d : %s / %s\n", i, v_a[i].arr, sndbuf); printf("[mainsvr] TX_BEGIN\n"); ret = tx_begin(); if (ret < 0) { error processing… } printf("[mainsvr] INSERT\n"); if(tpcall("INS", sndbuf, strlen(sndbuf), &rcvbuf, &len, 0)<0) { error processing… } else { /* Success */ printf("[mainsvr] TX_COMMIT\n"); EXEC SQL DELETE FROM TEST_SEL WHERE A = :sndbuf; if(sqlca.sqlcode != 0) { printf("[mainsvr] delete error : %d\n", sqlca.sqlcode); ret = tx_rollback(); if (ret < 0) { error processing… } error processing… } tpfree(sndbuf); tpfree(rcvbuf); ret = tx_commit(); if (ret < 0) { error processing… } } } … tpreturn( TPSUCCESS, 0, (char *)NULL, 0, 0 ); }
<inssvr.pc>
#include <stdio.h> #include <ctype.h> #include <usrinc/atmi.h> EXEC SQL include sqlca.h; INS( TPSVCINFO *msg ) { char *buf; int i=0, errno; long len; printf("woong : START\n"); buf = (char *)msg->data; printf("%s\n", buf); printf("woong : INSERT\n"); EXEC SQL INSERT INTO TEST_INS VALUES(:buf); if (sqlca.sqlcode != 0 ) { error processing… } … fflush(stdout); tpreturn(TPSUCCESS, 0, (char *)NULL, 0, 0 ); }
결과
서버 프로그램 예제의 결과는 다음과 같다.
[mainsvr] START [mainsvr] CURSOR DECLARE [mainsvr] CURSOR OPEN [mainsvr] open cursor error : 0 [mainsvr] CURSOR FETCH [mainsvr] CURSOR CLOSE [mainsvr] 0 : aaaaa / aaaaa [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START aaaaa woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] 1 : bbbbb / bbbbb [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START bbbbb woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] 2 : ccccc / ccccc [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START ccccc woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] 3 : ddddd / ddddd [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START ddddd woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] 4 : eeeee / eeeee [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START eeeee woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] 5 : fffff / fffff [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START fffff woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT………………………6번째가 끝나고 더 이상 select되는 데이터가 없음. [mainsvr] TPRETURN SUCCESS [mainsvr] START [mainsvr] CURSOR DECLARE [mainsvr] CURSOR OPEN [mainsvr] open cursor error : 0 [mainsvr] CURSOR FETCH [mainsvr] CURSOR CLOSE [mainsvr] 0 : aaaaa / aaaaa [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START aaaaa woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] delete error : 1403 [mainsvr] TPRETURN FAIL [mainsvr] START [mainsvr] CURSOR DECLARE [mainsvr] CURSOR OPEN [mainsvr] open cursor error : 0 [mainsvr] CURSOR FETCH [mainsvr] CURSOR CLOSE [mainsvr] 0 : aaaaa / aaaaa [mainsvr] TX_BEGIN [mainsvr] INSERT woong : START aaaaa woong : INSERT woong : TPRETURN SUCCESS [mainsvr] TX_COMMIT [mainsvr] delete error : 1403 [mainsvr] TPRETURN FAIL ………………… ………………… …………………
test_ins 테이블
각 테이블을 선택하면 다음과 같은 결과를 확인할 수 있다.
SQL> select * from test_ins; NAME -------------------- bbbbb ccccc ddddd eeeee fffff aaaaa 6 rows selected. SQL> select * from test_sel; no rows selected