Chapter 2. UCS Program

Table of Contents

2.1. Overview
2.2. UCS Program Component
2.2.1. Server Program
2.2.2. Client Program
2.3. UCS Environment Configuration and Compilation
2.3.1. Environment Configuration
2.3.2. Compilation

This chapter describes how to configure a UCS program and how to compile it.

2.1. Overview

A UCS (User Control Server) is a Tmax program that allows a user to control the flow of a program directly instead of the need for middleware. The program and process is called a UCS program and a UCS process, respectively.

UCS is used for jobs that require information delivery that isn't directly requested by a client, such as stock prices information, notifications, scheduled jobs, and integration with external institutions.

2.2. UCS Program Component

The UCS program must have an implementation part for usermain() and must be linked to a UCS library (libsvrucs.a / libsvrucs.so) for compilation. Usually, usermain() is implemented as a infinite loop. In other words, if usermain() is terminated (function return), the process will perform tpsvrdone() and then terminated. It is similar to how when main() is terminated, a process will terminate.

Caution

When writing a UCS program, the program will receive a termination command from the Tmax kernel or from the data sent from the client above through tpschedule(). Due of this, tpschedule() must always exist in a usermain() infinite loop.

The following is a simple usermain() example that sends specific information to connected clients in a unrequested message:

+1   #include <stdio.h>
+2   #include <usrinc/atmi.h>
+3   #include <usrinc/ucs.h>
+4
+5   #define MAX_CLI 10
+6   int num_cli;
+7   int client_id[MAX_CLI];
+8   int count;
+9
+10  int
+11  tpsvrinit(int argc, char *argv[])
+12  {
+13    num_cli = 0;
+14    count = 0;
+15  }
+16
+16  int
+17  usermain(int argc, char *argv[])  /* Same part as main in a Tmax ucs mode */
+18  {
+19     int         jobs;
+20     int         i;
+21     int         ret;
+22     char        *sndbuf;
+23     static int count = 0;
+24
+25     printf("usermain start\n");
+26
+27     sndbuf = (char *)tpalloc("CARRAY", NULL, 1024);
+28    
+29     while(1) {
+30        for  (i = 0; i < num_cli; i++) {
+31                  sprintf(sndbuf, "Success tpsendtocli [%d] 012345678901234\n", 
                             count);
+32              tpsendtocli (client_id[i], sndbuf, 1024, 0); 
+33            }
+34            count++;
+35         sleep(1);
+36         jobs = tpschedule(-1);
+37     }
+38  }
+39 
+40  LOGIN(TPSVCINFO *msg) /* SERVICE part in Tmax */
+41  {
+42        char        *sndbuf;
+43        int         clid;
+44        int         ret;
+45        int         i;
+46        
+47        printf("msg->data = [%.*s]\n", msg->len, msg->data);
+48        fflush(stdout);
+49
+50        sndbuf = (char *)tpalloc("CARRAY", NULL, 1024);
+51        
+52        printf("Success transaction");
+53        sprintf(sndbuf, "Success transaction");
+54
+55        if (num_cli < MAX_CLI) {
+56            client_id[num_cli] = tpgetclid();
+57                printf("client id(clid) = %d\n", client_id[num_cli]);
+58                num_cli++;
+59        }
+60
+61        tpreturn(TPSUCCESS, 0, (char *)sndbuf, 1024, 0);
+62  }        

The following describes an example program:

  1. tpsvrinit() is performed to start and returns to usermain().

  2. Line 30: The num_cli value is 0, so it escapes from the For statement.

  3. Line 36: Checks if a service request or the tmdown command have been received from a client through tpschedule().

  4. Line 40: Executes when the LOGIC SERVICE request has been received from a client. If there was no request, it escapes from tpschedule().

  5. Line 56: Saves client information connected through tpgetclid() to the global variable client_id and then increase the num_cli value.

  6. Line 61: Sends the response data to a client that requested LOGIN SERVICE.

  7. Line 36: Escapes from tpschedule().

  8. Line 30: The num_cli value is a positive value so the For statement is performed.

  9. Line 32: Sends the information to a client, which is stored in client_id, through tpsendtocli(). (This is the part that sends unrequested messages.)

  10. Repeat steps 3-9.

  11. If the tmdown command is received from tpschedule(), the process that performs tpsvrdone() will be terminated.

2.2.1. Server Program

A UCS server program consists of the following modules and libraries:

  • $(TMAXDIR)/lib/libsvrucs.a or $(TMAXDIR)/lib/shared/libsvrucs.so

    A library that contains main() and various UCS related APIs. This must be linked when creating a UCS program.

  • int tpsvrinit(int argc, char *argv[])

    This is executed once when a program starts. Mostly, this initializes global variables and implements database connection in case of Non-XA's.

  • int tpsvrdone()

    This is executed once when a program is terminated. Mostly, this returns used resources and implements a database disconnection in case of Non-XA's.

  • int usermain(int argc, char *argv[])

    An actual application logic will be implemented. The application process will be terminated after executing tpsvrdone() if the process is returned from usermain(), so mostly this is implemented as a infinite loop.

    To receive client request data or a tmdown command, tpschedule() is always required. If tpschedule() is not called, a Tmax server will not be terminated. Terminate the Tmax server with tmdown -i type.

[Figure 2.1] UCS Server Program Component

UCS Server Program Component

A UCS program consists of one module and one library as shown above, and tpschedule() must be called in a usermain() module.

In a UCS program, users can control the flow actively using the program component as shown above. A UCS program provides various APIs that can perform various applications.

$(TMAXDIR)/usrinc/ucs.h

The following are major API prototypes. For more information, refer to "Chapter 3. UCS Functions".

  • APIs that are used in all UCS programs:

    • int tpschedule(int sec)

    • int tpuschedule(int usec)

  • APIs that are used to send unrequested messages:

    • int tpsendtocli(int clid, char *data, long len, long flags)

    • int tpgetclid(void)

  • APIs for async communication with Non-Tmax programs:

    • int tpsetfd(void)

    • int tpissetfd(void)

    • int tpclrfd(void)

    • int tpgetctx(CTX_T *ctxp)

    • int tpcancelctx(CTX_T *ctxp)

    • CTX_T *tpsavectx()

    • int tprelay(char *svc, char *data, long len, long flags, CTX_T *ctxp)

  • callback API that is used for a tpacall (asynch communication) function in a UCS program:

    • int tpregcb(void)

    • int tpunregcb(void)

2.2.2. Client Program

Client programs, which receive services from a UCS program, are similar to regular programs. Client programs must include the following 2 configurations:

  • Configurations that receive data sent from a UCS program

  • Configurations that process data sent from a UCS program

The following describes functions that sets how to receive data is sent from a UCS program among multiple UCS programs used by a client program.

  • tpsetunsol_flag()

    Resets a flag value that is used to connect to Tmax using tpstart(). Mainly used to set the option to receive unrequested messages by using a flag.

  • tpsetunsol()

    Sets received, unrequested messages.

  • tpgetunsol()

    Receives unrequested messages.

For more information about each function, refer to "Chapter 3. UCS Functions".

2.3. UCS Environment Configuration and Compilation

2.3.1. Environment Configuration

Sets a SVGNAME in the SERVER section of an environment configuration file and sets the SVRTYPE to UCS.

The following is a UCS environment file example:

*DOMAIN
tmax1         SHMKEY =79970, MINCLH=1, MAXCLH=3, 
TPORTNO=8844, BLOCKTIME=120, RACPORT=3443
*NODE
tmaxs1  MAXDIR = "/user1/jaya/tmax3511",
        APDIR  = "/user1/jaya/tmax3511/appbin",
        PATHDIR = "/user1/jaya/tmax3511/path",
        TLOGDIR = "/user1/jaya/tmax3511/log/tlog",
        ULOGDIR = "/user1/jaya/tmax3511/log/ulog",
        SLOGDIR = "/user1/jaya/tmax3511/log/slog" 
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
svg1                NODENAME = "tmaxs1"
svg2                NODENAME = "tmaxs2"

*SERVER
ucssvr1             SVGNAME = svg1,
                    SVRTYPE = UCS, 
                    CPC = 5          # Number of channels between UCS and CLH
ucssvr2             SVGNAME = svg2,
                    SVRTYPE = UCS

*SERVICE
SVC1                SVRNAME = ucssvr1

2.3.2. Compilation

To compile a UCS server program, a program must be linked to a UCS library (libsvrucs.a or libsvrucs.so).

$TMAXDIR/usrinc/ucs.h must be included in a program, and -lsvrucs must be included in TMAXLIBS as a Makefile.

The following is a Makefile example used to compile a UCS server program in a 32bit Solaris system:

# Server makefile
TARGET  = $(COMP_TARGET)
APOBJS  = $(TARGET).o
SDLFILE  = demo.s

# In case of Solaris 
LIBS      = -lsvrucs -lsocket –lnsl -nodb 

# In case of other OSs
LIBS    = -lsvrucs -nodb
OBJS    = $(APOBJS) $(SDLOBJ) $(SVCTOBJ)
SDLOBJ  = ${SDLFILE:.s=_sdl.o}
SDLC    = ${SDLFILE:.s=_sdl.c}
SVCTOBJ = $(TARGET)_svctab.o
CFLAGS  = -O -I$(TMAXDIR)
APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
LIBDIR  = $(TMAXDIR)/lib

#
.SUFFIXES : .c
.c.o:
$(CC) $(CFLAGS) -c $<
#
# server compile
#
$(TARGET): $(OBJS)
        $(CC) $(CFLAGS) -L$(LIBDIR) -o $(TARGET) $(OBJS) $(LIBS)
        mv $(TARGET) $(APPDIR)/.
        rm -f $(OBJS)
$(APOBJS): $(TARGET).c
        $(CC) $(CFLAGS) -c $(TARGET).c
$(SVCTOBJ):
        touch $(SVCTDIR)/$(TARGET)_svctab.c
        $(CC) $(CFLAGS) -c $(SVCTDIR)/$(TARGET)_svctab.c
$(SDLOBJ):
        $(TMAXDIR)/bin/sdlc -i ../sdl/$(SDLFILE)
        $(CC) $(CFLAGS) -c ../sdl/$(SDLC)
#
clean:
        -rm -f *.o core $(TARGET)

Note

Makefile content may differ between different OS.