Examples
This chapter describes examples of API usage.
1. Basic Usage Example
-
Compile the following functions using a dynamic module to create my_function.sl.
#include <tdlcall.h> /* Function to be called by tdlcall */ long my_function(void *args) { long urcode; urcode = (long)time (NULL); strcpy((char*)args, "my_function"); return urcode; }
-
The part that uses this module uses as follows:
/* To use the TDL-related functions, 'include' must be needed. */ #include <tdlcall.h> int retval; char data[256]; long urcode; /* Call the tdlcall function: TDL Version 1 */ retval = tdlcall("my_function", (void*)data, &urcode, TDL_NOFLAGS); if (retval != TDL_OK) { printf("tdlcall(%s) = %d, with err[%s]\n", "my_function", retval, tdlerror(retval)); } else { /* Displays values received from my_function */ printf("tdlcall(%s) = %d, urcode = %#08x, data = %s\n","my_function", retval, urcode, data); }
2. C++ Interface Usage Example
This section describes an interface using TDL in C++.
-
Compile the following functions using a dynamic module to create dlib.so.
-
dlib.h
/* dlib.h */ namespace TmaxSoft { class Airplain { private: int state; public: Airplain(); virtual char *Start(); virtual char *Stop(); virtual int getState(); }; } class Car { private: int state; public: Car(); virtual char *Start(); virtual char *Stop(); virtual int getState(); };
-
dlib.cpp
/* dlib.cpp */ #include <string.h> #include <usrinc/tdlcall.h> #include "dlib.h" long tdlcreate_cb(const char *snm, const char *cnm, void *args, void **obj) { if (0) { } else if (!strcmp(snm, "TmaxSoft") && !strcmp(cnm, "Airplain")) { *obj = (void *) new TmaxSoft::Airplain(); if (*obj != NULL) return 1; else return -1; } else if (!strcmp(snm, "") && !strcmp(cnm, "Car")) { *obj = (void *) new Car(); if (*obj != NULL) return 1; else return -1; } return -1; } long tdldestroy_cb(const char *snm, const char *cnm, void *args, void *obj) { if (0) { } else if (!strcmp(snm, "TmaxSoft") && !strcmp(cnm, "Airplain")) { delete (TmaxSoft::Airplain *)obj; return 1; } else if (!strcmp(snm, "") && !strcmp(cnm, "Car")) { delete (Car *)obj; return 1; } return -1; } TmaxSoft::Airplain::Airplain() { state = 0; } char* TmaxSoft::Airplain::Start() { state = 2; return (char *)"TmaxSoft::Airplain::Start "; } char* TmaxSoft::Airplain::Stop() { state = 1; return (char *)"TmaxSoft::Airplain::Stop "; } int TmaxSoft::Airplain::getState() { return state; } Car::Car() { state = 0; } char* Car::Start() { state = 2; return (char *)"Car::Start "; } char* Car::Stop() { state = 1; return (char *)"Car::Stop "; } int Car::getState() { return state; }
-
-
The part that uses this module uses as follows:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <usrinc/tdlcall.h> #include "dlib.h" int main(int argc, char *argv[]) { int ret; long urcode; TmaxSoft::Airplain *obj; if ((ret = tdlcreate("dlib", "TmaxSoft", "Airplain", NULL, (void **)&obj, &urcode, 0)) < 0) { printf("obj is NULL\n"); printf("%s\n", tdlerror(ret)); } else { printf("obj %s\n", obj->Start()); printf("obj %s\n", obj->Stop()); printf("obj %d\n", obj->getState()); } return 0; }
-
Since it is difficult for the class to accurately identify symbols using nm, tdlinit and tdlupdate require export files. Export files are used as follows:
If VERSION is set to 1, 2, or 3, function names are listed one per line. If VERSION is set to 4, class names are listed one per line. If namespaces are used, list each entry on a separate line in the "namespace::classname" format.
# libuser.so foo bar # libuserclass.so classCar classBus tmaxsoft::classCar tmaxsoft::classBus tibero::myClass
3. Explicit Version Protection Usage Example
#include <stdio.h> #include <stdlib.h> #include <usrinc/atmi.h> #include <usrinc/tmaxapi.h> #include <usrinc/tdlcall.h> TSVC1(TPSVCINFO *msg) { int i; int n; long urcode; char *rcvbuf; long rcvlen; int ret; printf("TSVC1 service is started!\n"); /* Start explicit version protection by calling tdlstart */ tdlstart(); n = tdlcall("myfunction1", (void*)msg->data, &urcode, 0); if (n != TDL_OK) { printf("tdlcall(myfunction1) = %d, with err[%s]\n", n, tdlerror(n)); } else { printf("tdlcall(myfunction1) = %d, urcode = %#08x\n", n, urcode); } sprintf((char *)msg->data, "[TSVC1]tdlcall(myfunction1)=%d", urcode); if ((rcvbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) { printf("recvbuf alloc failed !\n"); tpreturn (TPFAIL, -1, NULL, 0, 0); } if(tpcall("TSVC2", rcvbuf, 0, &rcvbuf, &rcvlen, 0)==-1) { printf("Can't send request to service TSVC2[%d]\n", tperrno); tpfree((char *)rcvbuf); tpreturn (TPFAIL, -1, NULL, 0, 0); } /* End explicit version protection by calling tdlend */ tdlend(); strcat((char *)msg->data, rcvbuf); msg->len = strlen((char *)msg->data); tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len, 0); }
4. Quick MAXMODULES Change
This section describes the existing MAXMODULES change feature and the version that uses tdlsync and tdlinit, which are part of the TDL configuration.
4.1. Existing MAXMODULES Change
The following is the existing MAXMODULES change method. Relocating the modules makes this process time-consuming, which is a key disadvantage.
> tdlrm > tdlinit
4.2. MAXMODULES Change Using tdlsync and tdlinit
The following is the MAXMODULES change method using tdlsync and tdlinit.
Only the new index is calculated and initialized based on the changed MAXMODULES value. As this method does not require relocating the modules, it reduces both time and cost compared to the method in Existing MAXMODULES Change.
> tdlsync -B original_maxmodules.bak - Change the MAXMODULES value of tdl.cfg. > tdlinit -B original_maxmodules.bak
5. TDL Multi-Environment Configuration Example
5.1. Tmax Multi-Node Configuration
When using a Tmax multi-node environment and implicit version protection, set TDL=Y in the DOMAIN clause. The masternodeno is numbered based on the order of nodes registered in the Tmax environment configuration.
Tmax environment configuration
*DOMAIN tmax1 SHMKEY = 71190, MINCLH = 1, MAXCLH = 1, TPORTNO = 8118, RACPORT=4444 *NODE tmaxs7 TMAXDIR = "/data/phk6254/tmax", APPDIR = "/data/phk6254/tmax/appbin", PATHDIR = "/data/phk6254/tmax/path", TLOGDIR = "/data/phk6254/tmax/log/tlog", ULOGDIR = "/data/phk6254/tmax/log/ulog", SLOGDIR = "/data/phk6254/tmax/log/slog", IP="192.168.1.89" tmaxi9 TMAXDIR = "/data/phk6254/tmax", APPDIR = "/data/phk6254/tmax/appbin", PATHDIR = "/data/phk6254/tmax/path", TLOGDIR = "/data/phk6254/tmax/log/tlog", ULOGDIR = "/data/phk6254/tmax/log/ulog", SLOGDIR = "/data/phk6254/tmax/log/slog", IP="192.168.1.86"
TDL environment configuration
The following is a TDL master node configuration example.
#shared memory version (1|2|3|4) VERSION=3 # shared memory key SHMKEY=0x92100 # shared memory and file creation permission IPCPERM=0750 # number of dynamic loadable modules, rouded up to powers of 2 MAXMODULES=1024 # shared memory backup BACKUP=tdl.bak # path of a command file for searching export functions #COMMAND=tdlcmd # path of a log directory #LOGDIR=log #MONITOR=Y #DIRMAPPINGLIST=(mod1:run1),(mod2:run2),(mod3:run3) LANG=C masternodeno=0 DOMAINID=1 MODE=master
The following is a TDL slave node configuration example.
#shared memory version (1|2|3|4) VERSION=3 # shared memory key SHMKEY=0x92100 # shared memory and file creation permission IPCPERM=0750 # number of dynamic loadable modules, rouded up to powers of 2 MAXMODULES=1024 # shared memory backup BACKUP=tdl.bak # path of a command file for searching export functions #COMMAND=tdlcmd # path of a log directory #LOGDIR=log #MONITOR=Y #DIRMAPPINGLIST=(mod1:run1),(mod2:run2),(mod3:run3) LANG=C masternodeno=0 DOMAINID=1 MODE=slave
Running racd on master and slave nodes
tmaxs7@phk6254:/data/phk6254>export TMAX_RAC_PORT=4444 tmaxs7@phk6254:/data/phk6254>racd -k
Running TDL in a multi-node environment
tmaxs7@phk6254:/data/phk6254>tdlinit (I) TDLUTIL0046 TDLDIR initialization complete [TDL0331] tmaxs7@phk6254:/data/phk6254>tdlshm TDLDIR = /data/phk6254/tmax BACKUP = /data/phk6254/tmax/tdl.bak VERSION = 3, SHMKEY = 0x92100, IPCPERM = 0750 MAXMODULES = 1024, CURMODULES = 6, Global SEQNO = 561c9c45, MONITOR = N MAXPROC = 0 MODE = MASTER, LANG = C, DOMAINID = 1 Index = 0, Funcname = TOLOWER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 1, Funcname = TOUPPER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 2, Funcname = func3_A, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 3, Funcname = func3_B, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 4, Funcname = ECHO_A, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 5, Funcname = ECHO_B, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Msg from rnode(tmaxi9): TDLDIR = /data/phk6254/tmax BACKUP = /data/phk6254/tmax/tdl.bak VERSION = 3, SHMKEY = 0x92100, IPCPERM = 0750 MAXMODULES = 1024, CURMODULES = 6, Global SEQNO = 561c9c45, MONITOR = N MAXPROC = 0 MODE = SLAVE, LANG = C, DOMAINID = 1 Index = 0, Funcname = func3_A, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 1, Funcname = TOLOWER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 2, Funcname = TOUPPER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 3, Funcname = ECHO_A, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 4, Funcname = ECHO_B, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 5, Funcname = tdlcall_s, Libname = tdlcall_s, Seqno = 561c9c45, Active = Y remote opration ok tmaxs7@phk6254:/data/phk6254>tdlupdate -m tdlcall2s_s (I) TDLUTIL0083 tdlcall2s_s.561c9c61 updated successfully [TDL0443]
5.2. TDL Multi-Node Configuration
The masternodeno is numbered based on the order registered in the tdl.rac environment configuration.
TDL Envionment Configuration
The following is a TDL master node configuration example.
#shared memory version (1|2|3|4) VERSION=3 # shared memory key SHMKEY=0x92100 # shared memory and file creation permission IPCPERM=0750 # number of dynamic loadable modules, rouded up to powers of 2 MAXMODULES=1024 # shared memory backup BACKUP=tdl.bak # path of a command file for searching export functions #COMMAND=tdlcmd # path of a log directory #LOGDIR=log #MONITOR=Y #DIRMAPPINGLIST=(mod1:run1),(mod2:run2),(mod3:run3) LANG=C masternodeno=0 DOMAINID=1 MODE=master RACFILE=tdl.rac
The following is a TDL slave node configuration example.
#shared memory version (1|2|3|4) VERSION=3 # shared memory key SHMKEY=0x92100 # shared memory and file creation permission IPCPERM=0750 # number of dynamic loadable modules, rouded up to powers of 2 MAXMODULES=1024 # shared memory backup BACKUP=tdl.bak # path of a command file for searching export functions #COMMAND=tdlcmd # path of a log directory #LOGDIR=log #MONITOR=Y #DIRMAPPINGLIST=(mod1:run1),(mod2:run2),(mod3:run3) LANG=C masternodeno=0 DOMAINID=1 MODE=slave RACFILE=tdl.rac
tdl.rac configuration file
tmaxs7 192.168.1.89 4444 tmaxi9 192.168.1.86 4444
Running racd on master and slave nodes
The following is an example of running racd on master and slave nodes.
tmaxs7@phk6254:/data/phk6254/tmax/config>cat tdlracd.env [NODE1] TMAX_RAC_PORT=4444 tmaxs7@phk6254:/data/phk6254/tmax/config>racd -k -i tdlracd.env -l NODE1
Running TDL in a multi-node environment
tmaxs7@phk6254:/data/phk6254>tdlinit (I) TDLUTIL0046 TDLDIR initialization complete [TDL0331] tmaxs7@phk6254:/data/phk6254>tdlshm TDLDIR = /data/phk6254/tmax BACKUP = /data/phk6254/tmax/tdl.bak VERSION = 3, SHMKEY = 0x92100, IPCPERM = 0750 MAXMODULES = 1024, CURMODULES = 6, Global SEQNO = 561c9c45, MONITOR = N MAXPROC = 0 MODE = MASTER, LANG = C, DOMAINID = 1 Index = 0, Funcname = TOLOWER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 1, Funcname = TOUPPER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 2, Funcname = func3_A, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 3, Funcname = func3_B, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 4, Funcname = ECHO_A, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 5, Funcname = ECHO_B, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Msg from rnode(tmaxi9): TDLDIR = /data/phk6254/tmax BACKUP = /data/phk6254/tmax/tdl.bak VERSION = 3, SHMKEY = 0x92100, IPCPERM = 0750 MAXMODULES = 1024, CURMODULES = 6, Global SEQNO = 561c9c45, MONITOR = N MAXPROC = 0 MODE = SLAVE, LANG = C, DOMAINID = 1 Index = 0, Funcname = func3_A, Libname = tdlcall2_s, Seqno = 561c9c45, Active = Y Index = 1, Funcname = TOLOWER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 2, Funcname = TOUPPER, Libname = tdlcall2s_s, Seqno = 561c9c45, Active = Y Index = 3, Funcname = ECHO_A, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 4, Funcname = ECHO_B, Libname = tdlcall2v_s, Seqno = 561c9c45, Active = Y Index = 5, Funcname = tdlcall_s, Libname = tdlcall_s, Seqno = 561c9c45, Active = Y remote opration ok tmaxs7@phk6254:/data/phk6254>tdlupdate -m tdlcall2s_s (I) TDLUTIL0083 tdlcall2s_s.561c9c61 updated successfully [TDL0443]