Table of Contents
This chapter describes how to configure a UCS program and how to compile it.
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.
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.
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:
tpsvrinit() is performed to start and returns to usermain().
Line 30: The num_cli value is 0, so it escapes from the For statement.
Line 36: Checks if a service request or the tmdown command have been received from a client through tpschedule().
Line 40: Executes when the LOGIC SERVICE request has been received from a client. If there was no request, it escapes from tpschedule().
Line 56: Saves client information connected through tpgetclid() to the global variable client_id and then increase the num_cli value.
Line 61: Sends the response data to a client that requested LOGIN SERVICE.
Line 36: Escapes from tpschedule().
Line 30: The num_cli value is a positive value so the For statement is performed.
Line 32: Sends the information to a client, which is stored in client_id, through tpsendtocli(). (This is the part that sends unrequested messages.)
Repeat steps 3-9.
If the tmdown command is received from tpschedule(), the process that performs tpsvrdone() will be terminated.
A UCS server program consists of the following modules and libraries:
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.
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)
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.
For more information about each function, refer to "Chapter 3. UCS Functions".
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
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)
Makefile content may differ between different OS.