Examples

This chapter describes the usage and the entire flow of APIs by using a simple application example.

1. Message Transmission Program

The following figure is the flow of the program that sends and receives messages between a client and the server by using HMS APIs.

figure basic1
Flow of a Message Transmission Program
  1. Client 1 copies the string data entered in the buffer to call a service.

  2. A server’s service routine receives the string and converts it from the lowercase to uppercase to send it to HMS.

  3. Client 2 receives a message from HMS after a specific time period.

1.1. HMS Configuration

The following is an example of an HMS configuration file.

*DOMAIN
hms     SHMKEY = 74347,
        TPORTNO = 8808

*NODE
Locke2  TMAXDIR ="/home/tmax5/tmax",
        APPDIR ="/home/tmax5/tmax/appbin/",
        MAXSESSION = 100

*SVRGROUP
hms01   NODENAME = "Locke2",  CPC = 1, SVGTYPE = "HMS", RESTART = Y,
        OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60",
        HMSINDEX = 2, HMSMSGLIVE = 1, HMSMAXTHR = 2, HMSMAXDBTHR = 5,
        HMSNAME = hms_ora
svg1    NODENAME = "Locke2"


*HMS
queue01 SVGNAME = hms01, BOOT = "WARM", TYPE = "QUEUE"
topic01 SVGNAME = hms01, BOOT = "WARM", TYPE = "TOPIC"

*SERVER
svr     SVGNAME = svg1

*SERVICE
SVC     SVRNAME = svr

1.2. Client Program

The following is an example of a client program.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <usrinc/atmi.h>
#include <usrinc/hmsapi.h>

int main(int argc, char **argv)
{
    char *sndbuf, *rcvbuf;
    long rcvlen, sndlen;
    HMS_SHND *sess;
    HMS_CHND *cons;
    hms_msg_t *msg;

    if (argc != 2) {
        printf("Usage : %s <message>\n\n", argv[0]);
        exit(1);
    }

    if (tmaxreadenv("tmax.env", "TMAX") == -1) {
        printf("error: tmaxreadenv() failed - %d\n", tperrno);
        exit(1);
    }

    if (tpstart((TPSTART_T *) NULL) == -1) {
        printf("error: tpstart() fail - %d\n", tperrno);
        exit(1);
    }

    if ((sndbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) {
        printf("error: sendbuf alloc failed !\n");
        tpend();
        exit(1);
    }

    if ((rcvbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) {
        printf("error: recvbuf alloc failed !\n");
        tpfree((char *)sndbuf);
        tpend();
        exit(1);
    }

    strcpy(sndbuf, argv[1]);

    if(tpcall("SVC", sndbuf, 0, &rcvbuf, &rcvlen, 0)==-1){
        printf("error: Can't send request to service SVC\n");
        tpfree((char *)sndbuf);
        tpfree((char *)rcvbuf);
        tpend();
        exit(1);
    }

    sleep(5);

    /* RECV MESSAGE FROM HMS */
    if ((sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0)) == NULL) {
        printf("error: hms_create_session() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    if ((cons = hms_create_receiver(sess, "queue01", "cons01", NULL, NULL, 0))
              == NULL) {
        printf("error: hms_create_receiver() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    /* ALLOCATION */
    if ((msg = hms_alloc(sess, 1024)) == NULL) {
        printf("error: hms_alloc() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    /* RECV MESSAGE */
    if (hms_recvex(cons, &msg, 5, 0) == -1) {
        printf("error: hms_recvex() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    /* GET BODY */
    rcvlen = 1024;
    if (hms_get_body(msg, rcvbuf, &rcvlen) == -1) {
        printf("error: hms_get_body() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    printf("HMS MESSAGE : %s\n", rcvbuf);

    /* CLOSE RECEIVER */
    if (hms_close_receiver(cons, 0) == -1) {
        printf("error: hms_close_receiver() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    /* CLOSE SESSION */
    if (hms_close_session(sess, 0) == -1) {
        printf("error: hms_close_session() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    hms_free(msg);
    tpend();

    return 0;
}

1.3. Server Program

The following is an example of a server program.

<svr.c>

#include <stdio.h>
#include <stdlib.h>
#include <usrinc/atmi.h>
#include <usrinc/hmsapi.h>

HMS_SHND *sess = NULL;
HMS_CHND *prod = NULL;

int tpsvrinit(int argc, char **argv)
{
    while(1) {
        sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0);
        if (sess != NULL) {
            break;
        }
        if (tperrno != TPENOREADY) {
            printf("hms_create_session(hms01) : FAIL tperrno = %d\n", tperrno);
            return -1;
        }
    }
    prod = hms_create_sender(sess, "queue01", "prod_svc", 0);
    if (prod == NULL) {
        printf("hms_create_sender() : FAIL tperrno = %d\n", tperrno);
        return -1;
    }
    return 1;
}

int tpsvrdone()
{
    hms_close_sender(prod, 0);
    hms_close_session(sess, 0);
    return 1;
}

SVC(TPSVCINFO *msg)
{
    int n, i;
    hms_msg_t *hmsmsg = NULL;
    char *data = msg->data;
    int  len = msg->len, asize;
    printf("SVC STARTED!\n");

    /* TOUPPER */
    for (i = 0; i < len; i++)
        data[i] = toupper(data[i]);

    /* ALLOCATION */
    asize = len +1024;
    hmsmsg = hms_alloc(sess, asize);
    if (hmsmsg == NULL) {
        printf("hms_alloc : fail tperrno = %d\n", tperrno);
        tpreturn(TPFAIL, 0, NULL, 0, 0);
    }

    /* SET BODY */
    n = hms_set_body(hmsmsg, data, len);
    if (n < 0) {
        hms_free(hmsmsg);
        printf("hms_set_body : fail tperrno = %d\n", tperrno);
        tpreturn(TPFAIL, 0, NULL, 0, 0);
    }

    /* SEND : hms01, persistent */
    n = hms_sendex(prod, hmsmsg, HMS_DLV_PERSISTENT, 0, 0, 0);
    if (n < 0) {
        hms_free(hmsmsg);
        printf("hms_sendex(prod) : fail tperrno = %d\n", tperrno);
        tpreturn(TPFAIL, 0, NULL, 0, 0);
    }

    /* FREE */
    hms_free(hmsmsg);

    printf("SVC SUCCESS!\n");
    tpreturn(TPSUCCESS, 0, NULL, 0, 0);
}

1.4. Program Compilation

Client and server programs are compiled in the same manner as Tmax applications.

For more information about how to compile a program, refer to Tmax Application Development Guide.

2. Message Storage Program

The following is the flow of the program that stores messages exchanged between the client and server into the database by using HMS APIs.

figure basic2
Flow of a Message Saving Program
  1. The client receives user input and transmits it to HMS as a queue-type message.

  2. The server creates a consumer within an async session, and the ASYNC service receives the messages.

  3. The ASYNC service inserts the received messages to the database.

2.1. HMS Configuration

The following is an example of HMS configuration.

*DOMAIN
hms     SHMKEY = 74347,
        TPORTNO = 8808

*NODE
Locke2  TMAXDIR ="/home/tmax5/tmax",
        APPDIR  ="/home/tmax5/tmax/appbin/",
        MAXSESSION = 100

*SVRGROUP
hms01   NODENAME = "Locke2",  CPC = 1, SVGTYPE = "HMS", RESTART = Y,
        OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60",
        HMSINDEX = 2, HMSMSGLIVE = 1, HMSMAXTHR = 2, HMSMAXDBTHR = 5,
        HMSNAME = hms_ora
svg1    NODENAME = "Locke2", RESTART = N,
        OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60",
        DBNAME = "ORACLE", TMSNAME = tms_ora, MINTMS = 1

*HMS
queue01 SVGNAME = hms01, BOOT = "WARM", TYPE = "QUEUE"
topic01 SVGNAME = hms01, BOOT = "WARM", TYPE = "TOPIC"

*SERVER
async   SVGNAME = svg1, CLOPT = "-- -i"

*SERVICE
ASYNCSVC   SVRNAME = async

2.2. Client Program

The following is an example of a client program.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <usrinc/atmi.h>
#include <usrinc/hmsapi.h>


int main(int argc, char **argv)
{
    long len;
    HMS_SHND *sess;
    HMS_PHND *prod;
    hms_msg_t *msg;
    char *data;
    int no;

    if (argc != 3) {
        printf("Usage : %s <no> <message>\n\n", argv[0]);
        exit(1);
    }

    if (tmaxreadenv("tmax.env", "TMAX") == -1) {
        printf("error: tmaxreadenv() failed - %d\n", tperrno);
        exit(1);
    }

    if (tpstart((TPSTART_T *) NULL) == -1) {
        printf("error: tpstart() fail - %d\n", tperrno);
        exit(1);
    }

    len = strlen(argv[2]);
    data = argv[2];
    no = atoi(argv[1]);

    /* SEND MESSAGE TO HMS */
    if ((sess = hms_create_session("hms01", 0, HMS_AUTO_ACK, 0)) == NULL) {
        printf("error: hms_create_session() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    if ((prod = hms_create_sender(sess, "queue01", "prod01", 0)) == NULL) {
        printf("error: hms_create_sender() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    /* ALLOCATION */
    if ((msg = hms_alloc(sess, len + 1024)) == NULL) {
        printf("error: hms_alloc() failed tperrno = %d\n", tperrno);
        tpend();
        exit(1);
    }

    /* SET BODY */
    if (hms_set_body(msg, data, len) == -1) {
        printf("error: hms_set_body() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    /* SET PROPERTY */
    if (hms_set_property(msg, "NO", HMS_INT, (char *)&no, sizeof(int)) == -1) {
        printf("error: hms_set_property() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    /* SEND MESSAGE */
    if (hms_sendex(prod, msg, HMS_DLV_PERSISTENT, 0, 0, 0) == -1) {
        printf("error: hms_sendex() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    if (hms_close_sender(prod, 0) == -1) {
        printf("error: hms_close_sender() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    if (hms_close_session(sess, 0) == -1) {
        printf("error: hms_close_session() failed tperrno = %d\n", tperrno);
        hms_free(msg);
        tpend();
        exit(1);
    }

    hms_free(msg);
    tpend();

    return 0;
}

2.3. Server Program

The following is an example of a server program.

<async.pc>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <usrinc/atmi.h>
#include <usrinc/hmsapi.h>

HMS_SHND *sess;
HMS_CHND *cons;
int svrinit_start = 0;

void abend_callback(HMS_SHND *session)
{
    printf("START ABEND_CALLBACK FUNCTION\n");
    hms_close_session(session, 0);
    printf("hms_close_session success\n");
    while (1) {
        sess = (HMS_SHND *) hms_create_async_session("hms01", abend_callback, 0);
        if (sess == NULL) {
            if (tperrno == TPENOREADY) {
                usleep(500000);
                continue;
            }
            printf("hms_create_session() : FAIL [%d]\n\n", tperrno);
            return;
        }
        break;
    }
    cons = (HMS_CHND *) hms_create_receiver(sess, "queue01", "consasync", NULL,
           "ASYNCSVC", 0);
    if (cons == NULL) {
        printf("hms_create_receiver() : FAIL tperrno = %d\n\n", tperrno);
        return;
    }
    printf("END ABEND_CALLBACK FUNCTION\n");
}

int tpsvrinit(int argc, char **argv)
{
    int c;
    while ((c = getopt(argc, argv, "i")) != EOF) {
        switch (c) {
            case 'i':
                svrinit_start = 1;
                break;
        }
    }
    if (svrinit_start == 1) {
        printf("ASYNC SERVICE svrinit()\n");
        while(1) {
            sess = (HMS_SHND *) hms_create_async_session("hms01", abend_callback,
            0);
            if (sess == NULL) {
                if (tperrno == TPENOREADY) {
                    usleep(500000);
                    continue;
                }
                printf("ASYNC SERVICE hms_create_async_session() failed,
                        tperrno[%d]\n", tperrno);
                return;
            }
            break;
        }
        cons = (HMS_CHND *) hms_create_consumer(sess, "queue01", HMS_QUEUE,
                "consasync", "", "ASYNCSVC", 0);
        if (cons == NULL)
            printf("ASYNC SERVICE hms_create_consumer() failed, tperrno[%d]\n",
                    tperrno);
            return -1;
        }
        printf("ASYNC SERVICE svrinit() success\n");
    }
    return 1;
}

int tpsvrdone()
{
    if (svrinit_start == 1) {
        printf("ASYNC SERVICE svrdone()\n");
        hms_close_consumer(cons, 0);
        hms_close_session(sess, 0);
    }
    return 1;
}

/* DB INSERT */
EXEC SQL include sqlca.h;

EXEC SQL begin declare section;
int no;
char message[128];
EXEC SQL end declare section;

int DBInsert( int n, char *data )
{
    printf("UPDATE START!!!\n");
    memset( message, 0x00, sizeof(message) );
    no = n;
    strcpy(message, data);

    EXEC SQL insert into hmstest(no, message) values(:no, :message);

    if ( sqlca.sqlcode != 0 ){
        printf( "insert failed sqlcode = %d\n",sqlca.sqlcode );
        return -1;
    }

    return 1;
}

ASYNCSVC(TPSVCINFO *svc)
{
    hms_msg_t *msg;
    char *data;
    long llen = 4096;
    int prop = 0;
    int type;

    printf("ASYNC SERVICE CALLED\n");
    msg = (hms_msg_t *)svc->data;

    if ((data = (char *)tpalloc("CARRAY", NULL, 4096)) == NULL) {
        printf("ASYNC SERVICE tpalloc return failed. tperrno[%d]\n",
                tperrno);
        tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0);
    }

    if (hms_get_body(msg, data, &llen) < 0) {
        printf("ASYNC SERVICE hms_get_body() return failed. tperrno[%d]\n",
                tperrno);
        tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0);
    }
    data[llen] = '\0';

    llen = sizeof(int);
    if (hms_get_property(msg, "NO", &type, (char *)&prop, &llen) < 0) {
        printf("ASYNC SERVICE hms_get_property() return failed. tperrno[%d]\n",
                tperrno);
    }
    printf("ASYNC SERVICE RECV MESSAGE, BODY[%s], PROPERTY[NO:%d]\n", data, prop);

    if (DBInsert(prop, data) == -1)
        tpreturn(TPFAIL, TPFAIL_ACK, svc->data, svc->len, 0);
    tpreturn(TPSUCCESS, 0, svc->data, svc->len, 0);
}

2.4. Database Script

Table Creation Script

The following is an Oracle table creation script.

sqlplus scott/tiger << EOF
    create table hmstest (
      no number(7),
      message char(128)
    );
EOF
Table and Data Output Script

The following is an example of a script to display Oracle tables and their data.

sqlplus scott/tiger << EOF
desc hmstest;
select * from hmstest;
select count(*) from hmstest;
EOF

2.5. Program Compilation

Server and client programs are compiled in the same manner as Tmax applications.

For more information about program compilation, refer to Tmax Application Development Guide.