Examples

This chapter describes examples of API usage.

1. Basic Usage Example

  1. 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;
    }
  2. 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++.

  1. 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; }
  2. 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;
    }
  3. 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]