Chapter 4. UCS Usage Example

Table of Contents

4.1. Program Abnormal Termination Management
4.2. Asynch Communication Program Using A Socket
4.3. Program Using RQ
4.4. Client vs. Server Programs
4.5. Server vs. Server Program

Use UCS to program for specific business needs. This chapter shows examples that are programmed in various ways.

4.1. Program Abnormal Termination Management

The following example moves a core file to a specific directory and delivers information about an abnormal termination program to a connected client when an abnormal termination program (core) is generated.

<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);
}

4.2. Asynch Communication Program Using A Socket

The following example allows a socket to be connected from a client and performs tpacall for received requests. Results are sent to the client.

<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);
}

4.3. Program Using RQ

The following example dequeues data from a Fail queue to be called again.

<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.4. Client vs. Server Programs

The following example shows that if a client requests a LOGIN service while a server program is performing a loop, UCS will send a response.

Configuration File

*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

Client Program

  1. If a client program is executed, it will perform tpstart(), call the LOGIN service using tpcall(), and requests a service to a UCS process.

  2. tpsetunsol_flag(TPUNSOL_POLL) set in a client program means that the client program will receive messages sent from a server process.

  3. A client program will receive the message "Client Registration Success", which is contained in a sndbuff sent from a server process, in rcvbuff and will print it out.

    printf("After tpcall() received Message from server:%s\n", rcvbuf);
  4. If there is a client request, the loop count of a server process will increase, and as the count increases, the message "Success tpsendtocli [0]" contained in sndbuff will be sent from the for loop of a server process. This will be printed out as the loop count while the loop count in a client increases.

    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 ++;
          }
    }

The following is a client program example:

#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();
}

The following is a client program example result:

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

Server Program

  1. A server program will sleep for 5 seconds after Tmax starts and will infinitely loop while printing out "loop execute…0" until a request is received from a client.

    sleep(5);
    printf ("loop execute... %d\n", count);

    While looping infinitely, the server program will check if there is a request received from a client at the jobs = tpschedule(-1); code line of the loop. If there is no request, looping will continue and if there is a request, it will be received.

    client_id[num_cli] = tpgetclid();
    printf("client id(clid) = %d\n", client_id[num_cli]);
    num_cli++;
  2. The count of the for loop in the while loop is increased to the stored client ID value. sndbuf contains the increased count and operates the service to the client using tpsendtocli().

    for (i = 0; i < num_cli; i++)
    {
         sprintf(sndbuf, "Success tpsendtocli [%d]", count++);
         /*Send data to the customer by refering to the client ID*/
         tpsendtocli (client_id[i], sndbuf, 1024, 0);
    }
  3. tpreturn() is called with the sndbuf that contains the message that says the client was registered.

    sprintf(sndbuf, "Client Registration Success");
    tpreturn(TPSUCCESS, 0, (char *)sndbuf, 1000, 0);

The following is a server program example.:

#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");
}

/* Same with main in a Tmax UCS mode */
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++);

                /*Send data to the customer by refering to the client ID*/
                tpsendtocli (client_id[i], sndbuf, 1024, 0);
          }
          jobs = tpschedule(-1); /* Must exist at the end of while */
    }
}

LOGIN(TPSVCINFO *msg)
{
     char    *sndbuf;
     int     clid;
     int     ret;
     int     i;

     sndbuf = (char *)tpalloc("CARRAY", NULL, 1024);

     if (num_cli < MAX_CLI)
     {
            /* Store the client 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()
{
}

Result

The following is the result of the server program example:

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
…..

4.5. Server vs. Server Program

The following is an example in which three server processes are working. One is looping as a UCS and another selects data from a database and calls the final process to insert the data to a different table.

  1. <ucssvr.c> is a UCS process. It continuously calls tpcall for the MAIN service in mainsvr.pc.

  2. <mainsvr.pc> is called by tpcall by the UCS process. It selects the first data from the test_sel table in a database and calls tpcall for the INS service in <inssvr.pc>.

  3. <inssvr.pc> is called by tpcall. It inserts the data selected from the test_sel table to the test_in table. If this process is completed, <mainsvr.pc> will call tx_commit() and delete the data, which was sent to inssvr.pc, from the test_sel table.

  4. There are 6 units of data in the test_sel table, so repeat the same process 6 times.

  5. If there is no data to delete, a 1403 error will occur.

Configuration File

*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 Table

SQL> select * from test_sel;
A
--------------------
aaaaa
bbbbb
ccccc
ddddd
eeeee
fffff

6 rows selected.

SQL> select * from test_ins;

no rows selected

Server Program

<ucssvr.c>

#include <stdio.h>
#include <usrinc/atmi.h>
#include <unistd.h>

int usermain(int argc, char *argv[]) /* Same with main in a Tmax UCS mode */
{
        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 );
}

Result

The following is a server program example:

[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………………………The 6th ends and there is no more data to 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 Table

If each table is selected the following result can be checked:

SQL> select * from test_ins;

NAME
--------------------
bbbbb
ccccc
ddddd
eeeee
fffff
aaaaa

6 rows selected.

SQL> select * from test_sel;

no rows selected