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>
#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