RCAH Example

This chapter describes RCAH customizing and the example.

1. RCAH Customizing

Each site uses different communication protocols between clients (communication program) and RCAs. Int thrmain(RCAINFO info) must be customized in the RCAH module to processes the communication protocol.

RCAH creates as many as threads defined in RCA_NTHR. When a client request is received, a thread is allocated from the thread pool to configure the basic environment and the user-created thrmain() is to process the request. When thrmain() is completed, the client is disconnected and the thread is returned to the thread pool.

When writing an RCAH using global variables, lock processing must be implemented because RCAH is a multithreaded program. Tmaxreadenv() cannot be used due to the loss of memory.

2. Sample

The following is a sample program tested on the Solaris 2.7 32 bit machine. TMAXDIR environment variable must be configured in the system.

2.1. Makefile

The following is a makefile example.

TARGET = rcah
LIBS    = -lrcah -lpthread -lsocket
CFLAGS  = -I$(TMAXDIR)

APOBJS  = $(TARGET).o

TMAX_INCDIR = $(TMAXDIR)/usrinc
TMAX_BINDIR = $(TMAXDIR)/bin
TMAX_LIBDIR = $(TMAXDIR)/lib
OBJS    = $(APOBJS)

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

$(TARGET):  $(APOBJS)
          $(CC) $(CFLAGS) -L$(TMAX_LIBDIR) -o $(TARGET) $(OBJS) $(LIBS) $(USERLIBS)

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

2.2. Program

The following is the header file and source file of a program.

<rca.h>

/* ------------------------- usrinc/rca.h --------------------- */
/*                              */
/*              Copyright (c) 2002 TmaxSoft Co., Ltd       */
/*                   All Rights Reserved            */
/*                              */
/* ------------------------------------------------------------ */

#ifndef _TMAX_RCA_H
#define _TMAX_RCA_H
#ifndef _TMAX_MTLIB
#define _TMAX_MTLIB     1
#endif


#include <usrinc/tmaxapi.h>
#ifndef _WIN32
#define __cdecl
#endif


/* ------ type definition ------ */
typedef struct {
    int fd;
int portno;
    int count;
    int status1;
    int status2;
    void *user_data;
    void *system_data;
} *RCAINFO;


#if defined (__cplusplus)
extern "C" {
#endif

#ifndef _TMAX_KERNEL
int thrmain(RCAINFO);
int thrinit(RCAINFO);
int thrdone(RCAINFO);
#endif

#if defined (__cplusplus)
}
#endif

#endif

<rcah.c>

#include        <stdlib.h>
#include        <string.h>
#include        <unistd.h>
#include        <netdb.h>
#include        <sys/types.h>
#include        <sys/socket.h>
#include        <sys/un.h>
#include        <netinet/in.h>
#include        <arpa/inet.h>
#include        <pthread.h>
#include        <errno.h>
#include        <usrinc/rca.h>

struct msg {
    int     len;
    char    svcname[16];
};

int start_flag;

int thrinit(RCAINFO info)
{
      int n;

      n = tpstart(NULL);
      if (n < 0) {
          printf("RCA_%d: tpstart fail, tperrno = %d, errno = %d\n",
                pthread_self(), tperrno, errno);
          return -1;
      }

      start_flag = 1;
      printf("RCA_%d: thrinit ok\n", pthread_self());
      return 1;
}

int thrdone(RCAINFO info)
{

      if (start_flag) {
          start_flag = 0;
          tpend();
      }
      printf("RCA_%d: thrdone ok\n", pthread_self());
      return 0;
}


int thrmain(RCAINFO info)
{
      struct msg header;
      int n;
      long len;
      char *sndbuf;
      char buf[8192];

      buf[0] = 0;

      n = read(info->fd, &header, sizeof(struct msg));
      if (n != sizeof(struct msg)) {
          printf("RCA_%d: read header fail = %d\n", pthread_self(), n);
          return -1;
      }

      len = ntohl(header.len);
      n = read(info->fd, buf, len);
      if (n != len) {
          printf("RCA_%d: read data fail = %d\n", pthread_self(), n);
          return -1;
      }
      /* ----------------------------------------------- */

      if (!start_flag) {
          n = tpstart(NULL);
          if (n < 0) {
              printf("RCA_%d: tpstart fail, tperrno = %d\n", pthread_self(),
              tperrno);
              return -1;
          }
          start_flag = 1;
      }

      sndbuf = (char *)tpalloc("CARRAY", NULL, len + 1);
      if (sndbuf == NULL) {
          printf("RCA_%d: tpalloc fail, tperrno = %d\n", pthread_self(), tperrno);
          return -1;
      }

      memcpy(sndbuf, buf, len);
      n = tpcall(header.svcname, sndbuf, len, &sndbuf, &len, 0);
      if (n < 0) {
          printf("RCA_%d: tpcall fail, tperrno = %d\n", pthread_self(), tperrno);
          tpfree(sndbuf);
          return -1;
      }
      memcpy(buf, sndbuf, len);
      header.len = htonl(len);
      tpfree(sndbuf);

      /* ----------------------------------------------- */
      write(info->fd, &header, sizeof(struct msg));
      write(info->fd, buf, len);

      return 0;
}