예제
본 장은 API 사용 프로그램 예제를 설명한다.
1. 기본적인 사용 예
-
다음과 같은 함수를 동적 모듈로 컴파일하여 my_function.sl을 생성한다.
#include <tdlcall.h> /* tdlcall로 호출되어질 함수 */ long my_function(void *args) { long urcode; urcode = (long)time (NULL); strcpy((char*)args, "my_function"); return urcode; }
-
이 모듈을 사용하는 측에서는 다음과 같이 사용한다.
/* TDL 관련 함수들을 사용하기 위하여 반드시 include 필요 */ #include <tdlcall.h> int retval; char data[256]; long urcode; /* tdlcall 함수 호출 : 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 { /* my_function 함수에서 전달받은 값 출력 */ printf("tdlcall(%s) = %d, urcode = %#08x, data = %s\n","my_function", retval, urcode, data); }
2. C++ 인터페이스 사용 예
본 절에서는 C++에서 TDL을 사용하는 인터페이스를 설명한다.
-
다음과 같은 함수를 동적 모듈로 컴파일하여 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; }
-
-
이 모듈을 사용하는 측에서는 다음과 같이 사용한다.
#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; }
-
클래스는 nm에서 심볼을 정확하게 확인하기 어렵기 때문에 tdlinit, tdlupdate의 경우에는 반드시 exp 파일이 필요하다. export 파일의 사용 방법은 다음과 같다.
VERSION=1, 2, 3으로 설정된 경우에는 함수명을 한 줄에 하나씩 나열했지만, VERSION=4로 설정한 경우에는 클래스명을 한 줄에 하나씩 나열한다. 만약 네임스페이스가 적용된 경우에는 namespace::classname 형태로 한 줄에 하나씩 나열한다.
# libuser.so foo bar # libuserclass.so classCar classBus tmaxsoft::classCar tmaxsoft::classBus tibero::myClass
3. 명시적 버전 보호 사용 예
#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"); /* 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); } /* tdlend 호출하여 명시적 버전 보호 종료 */ tdlend(); strcat((char *)msg->data, rcvbuf); msg->len = strlen((char *)msg->data); tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len, 0); }
4. 빠른 MAXMODULES 변경
본 절에서는 TDL 환경설정 중 기존의 MAXMODULES 변경 기능과 tdlsync와 tdlinit을 이용한 MAXMODULES 변경에 대해 설명한다.
4.1. 기존의 MAXMODULES 변경
다음은 기존의 MAXMODULES 변경하는 방법이다. 모듈의 재배치가 필요하기 때문에 많은 시간이 소요되는 단점이 있다.
> tdlrm > tdlinit
4.2. tdlsync와 tdlinit을 이용한 MAXMODULES 변경
tdlsync와 tdlinit을 이용한 MAXMODULES 변경 방법은 다음과 같다.
변경된 MAXMODULES 값을 기반으로 새로운 인덱스만 계산하여 초기화한다. 모듈의 재배치 과정이 없기 때문에, 기존의 MAXMODULES 변경의 방식보다 시간과 비용이 절감된다.
> tdlsync -B original_maxmodules.bak - tdl.cfg 의 MAXMODULES 값을 변경 > tdlinit -B original_maxmodules.bak
5. TDL 멀티 환경 구성 예제
5.1. Tmax 멀티 노드 구성
Tmax 멀티 노드 환경을 이용한 구성, 암시적 버전 보호 기능을 이용할 경우엔 DOMAIN 절에 TDL=Y를 설정한다. masternodeno 지정은 Tmax 환경설정에 등록된 node의 순서를 기준으로 넘버링한다.
Tmax 환경설정
*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 환경설정
다음은 TDL Master 노드 설정의 예이다.
#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
다음은 TDL slave 노드 설정의 예이다.
#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
master/slave 노드에서 racd 실행
tmaxs7@phk6254:/data/phk6254>export TMAX_RAC_PORT=4444 tmaxs7@phk6254:/data/phk6254>racd -k
TDL 멀티 환경 실행
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 멀티 노드 구성
masternodeno 지정은 tdl.rac 환경설정에 등록된 순서를 기준으로 넘버링한다.
TDL 환경설정
다음은 TDL master 노드를 설정하는 예이다.
#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
다음은 TDL slave 노드를 설정하는 예이다.
#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 환경 파일
tmaxs7 192.168.1.89 4444 tmaxi9 192.168.1.86 4444
master/slave 노드에서 racd 실행
다음은 master/slave 노드에서 racd를 실행하는 예이다.
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
TDL 멀티 환경 실행
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]