Chapter 3. MultipleRM Program Examples

Table of Contents

3.1. Using Oracle and Tibero
3.1.1. Program Example
3.1.2. Environment Configuration and Compilation
3.2. Using Two Oracle Instances
3.2.1. Program Examples
3.2.2. Environment Configuration and Compilation

This chapter describes examples of MultipleRM programs, environment configuration, and makefile for compilation in TCS.

3.1. Using Oracle and Tibero

In TCS, Oracle and Tibero can be used through the server library. This section describes examples of MultipleRM programs, environment configuration, and makefile for compilation.

3.1.1. Program Example

The following shows sample TCS programs that use both Oracle and Tibero. The program examples can be used by writing a server program with Embedded SQL and pre-compiling it with the pre-compiler provided by each database vendor.

Service Execution

The following is program source code that executes a service.

#include <stdio.h>
#include <usrinc/atmi.h>

extern int oracle_call(TPSVCINFO *msg);
extern int tibero_call(TPSVCINFO *msg);

MDB_SVC1(TPSVCINFO *msg)
{
    int ret;
    int fail = 0;

    ret = oracle_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    ret = tibero_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    if ( fail ) {
        tpreturn(TPFAIL,0,(char *)msg->data, msg->len,0);
    }

    tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len,0);
}       

Oracle Call Function

The following program uses a function to call Oracle.

#include <stdio.h>
#include <usrinc/atmi.h>
#include <usrinc/tx.h>

EXEC SQL include sqlca.h;

EXEC SQL begin declare section;
    char h_addr[100];
EXEC SQL end declare section;

int oracle_call(TPSVCINFO *msg)
{
    int     i;

    strcpy(h_addr, msg->data);

    EXEC SQL INSERT
        INTO account( account_id, address, phone )
        VALUES ( tmax_seq.nextval,:h_addr, '007-1234' );

    if ( sqlca.sqlcode != 0 ){
        printf( "insert failed sqlcode = %d\n",sqlca.sqlcode );
        tpreturn( TPFAIL, -1, NULL, 0, 0 );
    }

    printf("ORACLE insert Success\n");

    return 0;
}

Tibero Call Function

The following program uses a function to call Tibero.

#include <stdio.h> 
#include <string.h> 
#include <usrinc/atmi.h>

EXEC SQL include sqlca.h;

EXEC SQL begin declare section;
    char h_addr[100];
EXEC SQL end declare section;

int tibero_call(TPSVCINFO *msg)
{
    strcpy(h_addr, msg->data);

    EXEC SQL INSERT
        INTO account( account_id, address, phone )
        VALUES ( tmax_seq.nextval,:h_addr, '007-1234' );

    if ( sqlca.sqlcode != 0 ){
        printf( "tibero insert failed sqlcode = %d\n",sqlca.sqlcode );
        tpreturn( TPFAIL, -1, NULL, 0, 0 );
    }

    printf("TIBERO insert Success\n");

    return 0;
}

3.1.2. Environment Configuration and Compilation

The following shows the environment configuration and compilation of MultipleRM that uses both Oracle and Tibero.

Environment Configuration

The following is a MultipleRM server configuration example.

*DOMAIN
domain        SHMKEY   = 81522, MAXUSER = 10000,
              MINCLH   = 1, MAXCLH = 1,
              TPORTNO  = 11500,  BLOCKTIME = 30, 
              MAXSACALL = 1024, MAXCACALL = 1024,
              MAXMTMAX = 3, MAXSTMAX = 10

*NODE
node1         TMAXDIR  = "/home/tmax",
              APPDIR   = "/home/tmax/appbin",
              PATHDIR  = "/home/tmax/path",
              TLOGDIR  = "/home/tmax/log/tlog",
              ULOGDIR  = "/home/tmax/log/ulog",
              SLOGDIR  = "/home/tmax/log/slog"

*SVRGROUP
svg_s1        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX+Acc=P/scott/tiger+SesTm=60",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX

svg_s2      NODENAME = node1,
              DBNAME = TIBERO,
              OPENINFO ="TIBERO_XA:user=scott,pwd=tiger, sestm=60,db=TMAX",
              TMSNAME = tms_tbr,
              SVGTYPE = STMAX

Makefile

-lnodb must be included in the LIBS (Tmax library) item of the makefile.

The following is a makefile that compiles a MultipleRM server program in 32bit Linux.

# Oracle Env
ORALIBDIR = /home/OraHome1/lib/
ORALIB = -lclntsh `cat /home/OraHome1/lib/ldflags`   `cat /home/OraHome1/lib/sysliblist` -ldl -lm

# Tibero Env
TBRLIB = -ltbxa -ltbertl
TBRLIBDIR = $(TB_HOME)/client/lib
TBRINCDIR = $(TB_HOME)/client/include

$ Server build
TARGET  = $(COMP_TARGET)
APOBJS  = $(TARGET).o
AP_ORA_OBJS = $(TARGET)_ora.o
AP_TBR_OBJS = $(TARGET)_tbr.o
NSDLOBJ = $(TMAXDIR)/lib/sdl.o

LIBS    = -lnsl -lsvr -lnodb

OBJS    = $(AP_ORA_OBJS) $(AP_TBR_OBJS) $(SVCTOBJ) $(APOBJS)
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR)

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
TMAXLIBDIR  = $(TMAXDIR)/lib

#
.SUFFIXES : .c

.c.o:
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $<
    
#
# server compile
#
all: $(TARGET)


$(TARGET):$(OBJS)
    echo $(OBJS)
    $(CC) $(CFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(TBRLIBDIR) -L$(ORALIBDIR) $(ORALIB) $(TBRLIB) $(OBJS) $(LIBS) $(NSDLOBJ)
    mv $(TARGET) $(APPDIR)/.
    rm -f $(OBJS)

$(AP_ORA_OBJS):
    echo $(OBJS)
    proc iname=$(TARGET)_ora.pc include=$(TMAXDIR)
    $(CC) $(CFLAGS) -c $(TARGET)_ora.c

$(AP_TBR_OBJS):
    echo $(OBJS)
    tbpc iname=$(TARGET)_tbr.tbc include=$(TMAXDIR)
    $(CC) $(CFLAGS) -I$(TBRINCDIR) -c $(TARGET)_tbr.c

$(APOBJS):
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $(TARGET).c

$(SVCTOBJ):
    echo $(OBJS)
    cp -f $(SVCTDIR)/$(TARGET)_svctab.c .
    touch ./$(TARGET)_svctab.c
    $(CC) $(CFLAGS) -c ./$(TARGET)_svctab.c

#
clean:
    -rm -f *.o core $(TARGET) $(TARGET).lis

Note

The makefile content may be different for each operating system.

3.2. Using Two Oracle Instances

Two Oracle instances can be used in TCS through the server library. This section describes examples of programs that use two Oracle instances, environment configuration, and makefile for compilation.

3.2.1. Program Examples

The following example shows transaction processing on a single server that uses two Oracle RM instances.

Since the same Oracle client library is used, the user must specify the instance to use when executing a query from user code. For xa_open in Oracle, an OCI function, such as xaoSvcCtx or xaoEnv, can be used to obtain a connection to the desired instance.

Service Execution

The following is program source code that executes a service.

#include <stdio.h>
#include <usrinc/atmi.h>

extern int oracle_call(TPSVCINFO *msg);

MDB_SVC2(TPSVCINFO *msg)
{
    int ret;
    int fail = 0;

    ret = oracle_call(msg);
    if (ret < 0) {
        fail = 1;
    }

    if ( fail ) {
        tpreturn(TPFAIL,0,(char *)msg->data, msg->len,0);
    }

    tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len,0);
}       

Oracle Call Function

The following program uses a function to call Oracle.

#include <stdio.h>
#include <usrinc/atmi.h>
#include <usrinc/tx.h>
#include <oci.h>

static void checkerr(errhp, status)
OCIError *errhp;
sword status;
{
    text errbuf[512];
    sb4 errcode;

    switch (status)
    {
        case OCI_SUCCESS:
            break;
        case OCI_SUCCESS_WITH_INFO:
            break;
        case OCI_NEED_DATA:
            break;
        case OCI_NO_DATA:
            break;
        case OCI_ERROR:  /* get the error info and display it on the screen */
            (void) OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, &errcode,
                                errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
            (void) printf("Error - %s\n", errbuf);
            break;
        case OCI_INVALID_HANDLE:
            break;
        case OCI_STILL_EXECUTING:
            break;
        case OCI_CONTINUE:
            break;
        default:
            break;
    }
}

int
oracle_call(TPSVCINFO *msg)
{
    int     i;
    OCIEnv *envhp;
    OCIServer *srvhp;
    OCIError *errhp;
    OCISvcCtx *svchp;
    OCISession *usrhp;
    OCIStmt *stmthp;
    dvoid *tmp;
    char *sql = {"INSERT "
        "INTO hahehiho_account( account_id, address, phone ) "
        "VALUES ( skt_seq.nextval,'asdf', '007-1234' )"};

    char *sql2 = {"INSERT "
        "INTO hahehiho_account( account_id, address, phone ) "
        "VALUES ( skt_seq.nextval,'fdsa', '700-1234' )"};

    svchp = xaoSvcCtx("A");
    envhp = xaoEnv("A");
    printf("oracle call A octxt[%d]\n", svchp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp,
                           (ub4) OCI_HTYPE_ERROR,
                           52, (dvoid **) &tmp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
               (ub4) OCI_HTYPE_STMT, 50, (dvoid **) &tmp);

    checkerr(errhp, OCIStmtPrepare(stmthp, errhp,(text *)sql, (ub4)strlen(sql), 
            (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));

    checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
            (OCISnapshot *) NULL, (OCISnapshot *) NULL,
            (ub4) OCI_DEFAULT));

    svchp = xaoSvcCtx("B");
    envhp = xaoEnv("B");
    printf("oracle call B octxt[%d]\n", svchp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp,
                           (ub4) OCI_HTYPE_ERROR,
                           52, (dvoid **) &tmp);

    OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
               (ub4) OCI_HTYPE_STMT, 50, (dvoid **) &tmp);

    checkerr(errhp, OCIStmtPrepare(stmthp, errhp,(text *)sql2, (ub4)strlen(sql2),
            (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));


    checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
            (OCISnapshot *) NULL, (OCISnapshot *) NULL,
            (ub4) OCI_DEFAULT));


    return 0;
}

3.2.2. Environment Configuration and Compilation

The following shows the environment configuration and compilation of MultipleRM that uses two Oracle instances.

Environment Configuration

The following is a MultipleRM server configuration example.

*DOMAIN
domain        SHMKEY   = 81522, MAXUSER = 10000,
              MINCLH   = 1, MAXCLH = 1,
              TPORTNO  = 11500,  BLOCKTIME = 30, 
              MAXSACALL = 1024, MAXCACALL = 1024,
              MAXMTMAX = 3, MAXSTMAX = 10

*NODE
node1         TMAXDIR  = "/home/tmax",
              APPDIR   = "/home/tmax/appbin",
              PATHDIR  = "/home/tmax/path",
              TLOGDIR  = "/home/tmax/log/tlog",
              ULOGDIR  = "/home/tmax/log/ulog",
              SLOGDIR  = "/home/tmax/log/slog"

*SVRGROUP
svg_s1        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX1+Acc=P/scott/tiger+SesTm=60+DB=A",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX,
              RMID = 0

svg_s2        NODENAME = node1,
              DBNAME = ORACLE,
              OPENINFO ="Oracle_Xa+SqlNet=TMAX2+Acc=P/scott/tiger+SesTm=60+DB=B",
              TMSNAME = tms_ora,
              SVGTYPE = STMAX,
              RMID = 1

svgm1         NODENAME = node1,
              SVGLIST = "svg_s2,svg_s1",
              SVGTYPE = MTMAX

*SERVER
sample SVGNAME = svgm1, LOGLVL = DEBUG4

*SERVICE
MDB_SVC2 SVRNAME = sample

Makefile

-lnodb must be included in the LIBS item of the makefile.

The following is a makefile that compiles a MultipleRM server program in 32bit Linux.

# Oracle Env
ORALIBDIR = /home/OraHome1/lib/
ORALIB = -lclntsh `cat /home/OraHome1/lib/ldflags`   `cat /home/OraHome1/lib/sysliblist` -ldl -lm

LIBS    = -lnsl -lsvrmrm

OBJS    = $(AP_ORA_OBJS) $(AP_TBR_OBJS) $(SVCTOBJ) $(APOBJS)
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR)

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svctTARGET  = $(COMP_TARGET)
APOBJS  = $(TARGET).o
AP_ORA_OBJS = $(TARGET)_ora.o
NSDLOBJ = $(TMAXDIR)/lib/sdl.o

LIBS    = -lnsl -lsvr -lnodb

OBJS    = $(AP_ORA_OBJS) $(SVCTOBJ) $(APOBJS) 
SVCTOBJ = $(TARGET)_svctab.o

CFLAGS  =  -O -I$(TMAXDIR) -I$(ORACLE_HOME)/include -I$(ORACLE_HOME)/rdbms/demo -I$(ORACLE_HOME)/rdbms/public

APPDIR  = $(TMAXDIR)/appbin
SVCTDIR = $(TMAXDIR)/svct
TMAXLIBDIR  = $(TMAXDIR)/lib

#
.SUFFIXES : .c

.c.o:
    echo $(OBJS)
    $(CC) $(CFLAGS) -c $<

#
# server compile
#
all: $(TARGET)


$(TARGET):$(OBJS)
    $(CC) $(CFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(ORALIBDIR) $(ORALIB)  $(OBJS) $(LIBS) $(NSDLOBJ)
    mv $(TARGET) $(APPDIR)/.
    rm -f $(OBJS)

$(AP_ORA_OBJS):
    $(CC) $(CFLAGS) -c $(TARGET)_ora.c

$(APOBJS):
    $(CC) $(CFLAGS) -c $(TARGET).c

$(SVCTOBJ): 
    echo $(OBJS)
    cp -f $(SVCTDIR)/$(TARGET)_svctab.c .
    touch ./$(TARGET)_svctab.c 
    $(CC) $(CFLAGS) -c ./$(TARGET)_svctab.c

#
clean:
    -rm -f *.o core $(TARGET) $(TARGET).lis

Note

The makefile content may be different for each operating system.