2.12.1 Defining Your Own Buffer Types

The application programmer is responsible for the code that manipulates buffers, which allocates and frees space, and sends and receives messages. For applications in which the default buffer types do not meet the needs of the application, other buffer types can be defined, and new routines can be written and then incorporated into the buffer type switch.

To define other buffer types, complete the following steps:

  1. Code any switch element routines that may be required.
  2. Add your new types and the names of your buffer management modules to tm_typesw.
  3. Build a new shared object or a DLL. The shared object or DLL must contain your updated buffer type switch and associated functions.
  4. Install your new shared object or DLL so that all servers, clients, and executables provided by the Oracle Tuxedo system are loaded dynamically at run time.

If your application is using static libraries and you are providing a customized buffer type switch, then you must build a custom server to link in your new type switch. For details, see buildwsh (1), TMQUEUE (5), or TMQFORWARD (5).

The rest of the sections in this topic address the steps listed in the preceding procedure to define a new buffer type in a shared-object or DLL environment. First, however, let’s look at the buffer switch that is delivered with the Oracle Tuxedo system software. The following listing shows the switch delivered with the system.

Listing Default Buffer Type Switch

#include <stdio.h>
#include <tmtypes.h>
/* 
 * Initialization of the buffer type switch.
 */
struct tmtype_sw_t tm_typesw[] = {
{
      "CARRAY",       /* type */
      "*",            /* subtype */
      0               /* dfltsize */
      NULL,           /* initbuf */
      NULL,           /* reinitbuf */
      NULL,           /* uninitbuf */
      NULL,           /* presend */
      NULL,           /* postsend */
      NULL,           /* postrecv */
      NULL,           /* encdec */
      NULL,           /* route */
      NULL,           /* filter */
      NULL,           /* format */
      NULL,           /* presend2 */
      NULL            /* multibyte code-set encoding conversion */
},
{
      "STRING",       /* type */
      "*",            /* subtype */
      512,            /* dfltsize */
      NULL,           /* initbuf */
      NULL,           /* reinitbuf */
      NULL,           /* uninitbuf */
      _strpresend,    /* presend */
      NULL,           /* postsend */
      NULL,           /* postrecv */
      _strencdec,     /* encdec */
      NULL,           /* route */
      _sfilter,       /* filter */
      _sformat,       /* format */
      NULL,           /* presend2 */
      NULL            /* multibyte code-set encoding conversion */
},
{
      "FML",          /* type */
      "*",            /* subtype */
      1024,           /* dfltsize */
      _finit,         /* initbuf */
      _freinit,       /* reinitbuf */
      _funinit,       /* uninitbuf */
      _fpresend,      /* presend */
      _fpostsend,     /* postsend */
      _fpostrecv,     /* postrecv */
      _fencdec,       /* encdec */
      _froute,        /* route */
      _ffilter,       /* filter */
      _fformat,       /* format */ 
      NULL,           /* presend2 */
      NULL            /* multibyte code-set encoding conversion */
},
{
      "VIEW",        /* type */
      "*",           /* subtype */
      1024,          /* dfltsize */
      _vinit,        /* initbuf */
      _vreinit,      /* reinitbuf */
      NULL,          /* uninitbuf */
      _vpresend,     /* presend */
      NULL,          /* postsend */
      NULL,          /* postrecv */
      _vencdec,      /* encdec */
      _vroute,       /* route */
      _vfilter,      /* filter */
      _vformat,      /* format */
      NULL,          /* presend2 */
      NULL           /* multibyte code-set encoding conversion */
},
{
      /* XATMI - identical to CARRAY */ 
      "X_OCTET",     /* type */
      "*",           /* subtype */
      0              /* dfltsize */
},
{     /* XATMI - identical to VIEW */ 
      {'X','_','C','_','T','Y','P','E'},          /* type */
      "*",          /* subtype */
      1024,         /* dfltsize */
      _vinit,       /* initbuf */
      _vreinit,     /* reinitbuf */
      NULL,         /* uninitbuf */
      _vpresend,    /* presend */
      NULL,         /* postsend */
      NULL,         /* postrecv */
      _vencdec,     /* encdec */
      _vroute,      /* route */
      _vfilter,     /* filter */
      _vformat,     /* format */
      NULL,         /* presend2 */
      NULL          /* multibyte code-set encoding conversion */
},
{
      /* XATMI - identical to VIEW */ 
      {'X','_','C','O','M','M','O','N'},         /* type */
      "*",         /* subtype */
      1024,        /* dfltsize */
      _vinit,      /* initbuf */
      _vreinit,    /* reinitbuf */
      NULL,        /* uninitbuf */
      _vpresend,   /* presend */
      NULL,        /* postsend */
      NULL,        /* postrecv */
      _vencdec,    /* encdec */
      _vroute,     /* route */
      _vfilter,    /* filter */
      _vformat,    /* format */
      NULL,        /* presend2 */
      NULL         /* multibyte code-set encoding conversion */
},
{
      "FML32",       /* type */
      "*",           /* subtype */
      1024,          /* dfltsize */
      _finit32,      /* initbuf */
      _freinit32,    /* reinitbuf */      
      _funinit32,    /* uninitbuf */
      _fpresend32,   /* presend */
      _fpostsend32,  /* postsend */
      _fpostrecv32,  /* postrecv */
      _fencdec32,    /* encdec */
      _froute32,     /* route */
      _ffilter32,    /* filter */
      _fformat32,    /* format */
      _fpresend232,  /* presend2 */
      _fmbconv32     /* multibyte code-set encoding conversion */
},
{
      "VIEW32",      /* type */
      "*",           /* subtype */
      1024,          /* dfltsize */
      _vinit32,      /* initbuf */
      _vreinit32,    /* reinitbuf */
      NULL,          /* uninitbuf */
      _vpresend32,   /* presend */
      NULL,          /* postsend */
      NULL,          /* postrecv */
      _vencdec32,    /* encdec */
      _vroute32,     /* route */
      _vfilter32,    /* filter */
      _vformat32,    /* format */
      NULL,          /* presend2 */
      _vmbconv32,    /* multibyte code-set encoding conversion */
},
{
      "XML",         /* type */ 
      "*",           /* subtype */ 
      0,             /* dfltsize */ 
      NULL,          /* initbuf */ 
      NULL,          /* reinitbuf */ 
      NULL,          /* uninitbuf */ 
      NULL,          /* presend */ 
      NULL,          /* postsend */ 
      NULL,          /* postrecv */ 
      NULL,          /* encdec */ 
      _xroute,       /* route */ 
      NULL,          /* filter */ 
      NULL,          /* format */
      NULL,          /* presend2 */
      NULL           /* multibyte code-set encoding conversion */
},
{
      "MBSTRING",    /* type */
      "*",           /* subtype */
      0,             /* dfltsize */
      _mbsinit,      /* initbuf */
      NULL,          /* reinitbuf */
      NULL,          /* uninitbuf */
      _mbspresend,   /* presend */
      NULL,          /* postsend */
      NULL,          /* postrecv */
      NULL,          /* encdec */
      NULL,          /* route */
      NULL,          /* filter */
      NULL,          /* format */      
      NULL,          /* presend2 */
      _mbsconv       /* multibyte code-set encoding conversion */
},
{
       "RECORD",     /* type */
       "*",          /* subtype */
       1024,         /* dfltsize */
       _rinit,       /* initbuf */
       _rreinit,     /* reinitbuf */
       _runinit,     /* uninitbuf */
       _rpresend,    /* presend */
       NULL,         /* postsend */
       NULL,         /* postrecv */
       _rencdec,     /* encdec */
       NULL,         /* route */
       NULL,         /* filter */
       NULL,         /* format */
       NULL          /* presend2 */
},
{
""
} 
};
struct tmtype_sw_t _TM_FAR *
_TMDLLENTRY
_tmtypeswaddr(void)
{
   return(tm_typesw);
}

For a better understanding of the preceding listing, consider the declaration of the buffer type structure that is shown in the following listing.

Listing Buffer Type Structure

/*
 * The following definitions are in $TUXDIR/include/tmtypes.h
 */
#define TMTYPELEN ED_TYPELEN 
#define TMSTYPELEN ED_STYPELEN
struct tmtype_sw_t {
    char type[TMTYPELEN];       /* type of buffer */
    char subtype[TMSTYPELEN];   /* subtype of buffer */
    long dfltsize;              /* default size of buffer */
/* buffer initialization function pointer */
int (_TMDLLENTRY *initbuf) _((char _TM_FAR *, long));
/* buffer reinitialization function pointer */
int (_TMDLLENTRY *reinitbuf) _((char _TM_FAR *, long));
/* buffer un-initialization function pointer */
int (_TMDLLENTRY *uninitbuf) _((char _TM_FAR *, long));
/* pre-send buffer manipulation func pointer */
long (_TMDLLENTRY *presend) _((char _TM_FAR *, long, long));
/* post-send buffer manipulation func pointer */
void (_TMDLLENTRY *postsend) _((char _TM_FAR *, long, long));
/* post-receive buffer manipulation func pointer*/
long (_TMDLLENTRY *postrecv) _((char _TM_FAR *, long, long));
/* XDR encode/decode function pointer */
long (_TMDLLENTRY *encdec) _((int, char _TM_FAR *, long, char _TM_FAR *, 
long));
/* routing function pointer */
int (_TMDLLENTRY *route) _((char _TM_FAR *, char _TM_FAR *, char _TM_FAR *, 
long, char _TM_FAR *));
/* buffer filtering function pointer */
int (_TMDLLENTRY *filter) _((char _TM_FAR *, long, char _TM_FAR *, long));
/* buffer formatting function pointer */
int (_TMDLLENTRY *format) _((char _TM_FAR *, long, char _TM_FAR *, 
char _TM_FAR *, long));
/* process buffer before sending, possibly generating copy */
long (_TMDLLENTRY *presend2) _((char _TM_FAR *, long, 
long, char _TM_FAR *, long, long _TM_FAR *));
/* Multibyte code-set encoding conversion function pointer*/
long (_TMDLLENTRY *mbconv) _((char _TM_FAR *, long, 
char _TM_FAR *, char _TM_FAR *, long, long _TM_FAR *));
/* this space reserved for future expansion */
void (_TMDLLENTRY *reserved[8]) _((void));
};
/* 
 * application types switch pointer
 * always use this pointer when accessing the table
 */
extern struct tmtype_sw_t *tm_typeswp;

The listing for the default buffer type switch shows the initialization of the buffer type switch. The nine default buffer types are shown, followed by a field for naming a subtype. Except for the VIEW (and equivalently X_C_TYPE and X_COMMON) type, subtype is NULL. The subtype for VIEW is given as ``*'', which means that the default VIEW type puts no constraints on subtypes; all subtypes of type VIEW are processed in the same manner.

The next field gives the default (minimum) size of the buffer. For the CARRAY (and equivalently X_OCTET) type this is given as 0, which means that the routine that uses a CARRAY buffer type must tpalloc() enough space for the expected CARRAY.

For the other types, the Oracle Tuxedo system allocates (with a tpalloc() call) the space shown in the dfltsize field of the entry (unless the size argument of tpalloc() specifies a larger size).

The remaining eight fields of entries in the buffer type switch contain the names of switch element routines. These routines are described in the buffer(3c) page in the Oracle Tuxedo C Function Reference. The name of a routine provides a clue to the purpose of the routine. For example, _fpresend on the FML type is a pointer to a routine that manipulates the buffer before sending it. If no presend manipulation is needed, a NULL pointer may be specified. NULL means no special handling is required; the default action should be taken. See buffer(3c) for details.

It is particularly important that you notice the NULL entry at the end of the switch. Any changes that are made must always leave the NULL entry at the end of the array.