|
|
Customizing a Buffer
You may find that the buffer types supplied by the BEA Tuxedo system do not meet your needs. For example, perhaps your application uses a data structure that is not flat, but has pointers to other data structures, such as a parse tree for an SQL database query. To accommodate unique application requirements, the BEA Tuxedo System supports customized buffers.
To customize a buffer, you need to identify the following characteristics.
Custom Buffer Type Characteristics
The following table defines the list of routines that you may need to specify for each buffer type. If a particular routine is not applicable, you can simply provide a NULL pointer; the BEA Tuxedo system uses default processing, as necessary.
Custom Buffer Type Routines
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:
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 BEA Tuxedo system software. The following listing shows the switch delivered with the system.
Default Buffer Type Switch
#include <stdio.h>
#include <tmtypes.h>
/* Initialization of the buffer type switch */
static struct tmtype_sw_t tm_typesw[] = {
{
"CARRAY", /* type */
"", /* subtype */
0 /* dfltsize */
},
{
"STRING", /* type */
"", /*subtype */
512, /* dfltsize */
NULL, /* initbuf */
NULL, /* reinitbuf */
NULL, /* uninitbuf */
_strpresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_strencdec, /* encdec */
NULL, /* route */
NULL, /* filter */
NULL /* format */
},
{
"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 */
},
{
"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 */
},
{
"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 */
},
{
"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 */
},
{
"X_OCTET", /* type */
"", /* subtype */
0, /* dfltsize */
},
{
"'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 */
},
{
"'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 */
},
{
"XML", /* type */
"*", /* subtype */
0, /* dfltsize */
NULL, /* _xinit - not available */
NULL, /* _xrein
For a better understanding of the preceding listing, consider the declaration of the buffer type structure that is shown in the following listing.
Buffer Type Structure
/* The following definitions are in $TUXDIR/include/tmtypes.h */#define TMTYPELEN 8
#define TMSTYPELEN 16
struct tmtype_sw_t {
char type[TMTYPELEN]; /* type of buffer */
char subtype[TMSTYPELEN]; /* sub-type of buffer */
long dfltsize; /* default size of buffer */
/* buffer initialization function pointer */
int (_TMDLLENTRY *initbuf) _((char _TM_FAR *, long));
/* buffer re-initialization 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));
/* 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));
/* this space reserved for future expansion */
void (_TMDLLENTRY *reserved[10]) _((void));
};
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 \Q\Q*'', 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 BEA 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 BEA 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.
Coding Switch Element Routines
Presumably an application that is defining new buffer types is doing so because of a special processing need. For example, let's assume the application has a recurring need to compress data before sending a buffer to the next process. The application could write a presend routine. The declaration for the presend routine is shown in the following listing.
Semantics of the Presend Switch Element
long
presend(ptr, dlen, mdlen)
char *ptr;
long dlen, mdlen;
- ptr is a pointer to the application data buffer.
- dlen is the length of the data as passed into the routine.
- mdlen is the size of the buffer in which the data resides.
The data compression that takes place within your presend routine is the responsibility of the system programmer for your application.
On completion the routine should return the new, hopefully shorter length of the data to be sent (in the same buffer), or a -1 to indicate failure.
The name given to your version of the presend routine can be any identifier accepted by the C compiler. For example, suppose we name it _mypresend.
If you use our _mypresend compression routine, you will probably also need a corresponding _mypostrecv routine to decompress the data at the receiving end. Follow the template shown in the buffer(3c) entry in BEA Tuxedo C Function Reference.
Adding a New Buffer Type to tm_typesw
After the new switch element routines have been written and successfully compiled, the new buffer type must be added to the buffer type switch. To do this task, we recommend making a copy of $TUXDIR/lib/tmtypesw.c (the source code for the default buffer type switch). Give your copy a name with a .c suffix, such as mytypesw.c. Add the new type to your copy. The name of the type can be up to 8 characters in length. Subtype can be null ("") or a string of up to 16 characters. Enter the names of your new switch element routines in the appropriate locations, including the extern declarations. The following listing provides an example.
Adding a New Type to the Buffer Switch
#include <stdio.h>
#include <tmtypes.h>
/* Customized the buffer type switch */
static struct tmtype_sw_t tm_typesw[] = {
{
"SOUND", /* type */
"", /* subtype */
50000, /* dfltsize */
snd_init, /* initbuf */
snd_init, /* reinitbuf */
NULL, /* uninitbuf */
snd_cmprs, /* presend */
snd_uncmprs, /* postsend */
snd_uncmprs /* postrecv */
},
{
"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 */
},
{
""
}
};
In the previous listing, we added a new type: SOUND. We also removed the entries for VIEW, X_OCTET, X_COMMON, and X_C_TYPE, to demonstrate that you can remove any entries that are not needed in the default switch. Note that the array still ends with the NULL entry.
An alternative to defining a new buffer type is to redefine an existing type. Suppose, for the sake of argument, that the data compression for which you defined the buffer type MYTYPE was performed on strings. You could substitute your new switch element routines, _mypresend and _mypostrecv, for the two _dfltblen routines in type STRING.
Compiling and Linking Your New tm_typesw
To simplify installation, the buffer type switch is stored in a shared object.
Note: On some platforms the term "shared library" is used instead of "shared object." On the NT platform a "dynamic link library" is used instead of a "shared object." For the purposes of this discussion, however, the functionality implied by all three terms is equivalent, so we use only one term.
This section describes how to make all BEA Tuxedo processes in your application aware of the modified buffer type switch. These processes include application servers and clients, as well as servers and utilities provided by the BEA Tuxedo system.
- Copy and modify $TUXDIR/lib/tmtypesw.c, as described in Adding a New Buffer Type to tm_typesw. If additional functions are required, store them in either tmtypesw.c or a separate C source file.
- Compile tmtypesw.c with the flags required for shared objects.
- Link together all object files to produce a shared object.
- Copy libbuft.so.71 from the current directory to a directory in which it will be visible to applications, and processed before the default shared object supplied by the BEA Tuxedo system. We recommend using one of the following directories: $APPDIR, $TUXDIR/lib, or $TUXDIR/bin (on an NT platform).
Different platforms assign different names to the buffer type switch shared object, to conform to operating system conventions.
OS-specific Names for the Buffer Type Switch Shared Object
On This Platform . . .
The Name of the Buffer Type Switch Shared Object Is . . .
UNIX System
(most SVR4)libbuft.so.71
HP-UX
libbuft.sl
Sun OS
libbuft.so.71
Windows (16-bit)
wbuft.dll
Windows (32-bit)
wbuft32.dll
OS/2 (16-bit)
obuft.dll
OS/2 (32-bit)
obuft.dll
Please refer to the software development documentation for your platform for instructions on building a shared object library.
As an alternative, it is possible to statically link a new buffer type switch in every client and server process, but doing so is more error-prone and not as efficient as building a shared object library.
Compiling and Linking Your New tm_typesw for a 16-bit Windows Platform
If you have modified tmtypesw.c on a Windows platform, as described in Compiling and Linking Your New tm_typesw, then you can use the commands shown in the following sample code listing to make the modified buffer type switch available to your application.
Sample Code in Microsoft Visual C++
CL -AL -I..\e\|sysinclu -I..\e\|include -Aw -G2swx -Zp -D_TM_WIN
-D_TMDLL -Od -c TMTYPESW.C
LINK /CO /ALIGN:16 TMTYPESW.OBJ, WBUFT.DLL, NUL, WTUXWS /SE:250 /NOD
/NOE LIBW LDLLCEW, WBUFT.DEF
RC /30 /T /K WBUFT.DLL
Data Conversion
The purpose of the TYPE parameter in the MACHINES section of the configuration file is to group together machines that have the same form of data representation (and use the same compiler) so that data conversion is done on messages going between machines of different TYPEs. For the default buffer types, data conversion between unlike machines is transparent to the user (and to the administrator and programmer, for that matter).
If your application defines new buffer types for messages that move between machines with different data representation schemes, you must also write new encode/decode routines to be incorporated into the buffer type switch. When writing your own data conversion routines, keep the following guidelines in mind:
- You should use the semantics of the _tmencdec routine shown on the buffer(3c) page in the BEA Tuxedo C Function Reference. That is, you should code your routine so that it uses the same arguments and returns the same values on success or failure as _tmencdec. Follow the procedure provide in " for building servers with services that use your new buffer type.
The encode/decode routines are called only when the BEA Tuxedo system determines that data is being sent between two machines that are not of the same TYPE.
Copyright © 2000 BEA Systems, Inc. All rights reserved.
Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.