Table of Contents Previous Next PDF


Managing Typed Buffers

Managing Typed Buffers
This topic includes the following sections:
Overview of Typed Buffers
Before a message can be sent from one process to another, a buffer must be allocated for the message data. Oracle Tuxedo ATMI clients use typed buffers to send messages to ATMI servers. A typed buffer is a memory area with a category (type) and optionally a subcategory (subtype) associated with it. Typed buffers make up one of the fundamental features of the distributed programming environment supported by the Oracle Tuxedo system.
Why typed? In a distributed environment, an application may be installed on heterogeneous systems that communicate across multiple networks using different protocols. Different types of buffers require different routines to initialize, send and receive messages, and encode and decode data. Each buffer is designated as a specific type so that the appropriate routines can be called automatically without programmer intervention.
Table 2‑1 lists the typed buffers supported by the Oracle Tuxedo system and indicates whether or not:
The buffer is self-describing; in other words, the buffer data type and length can be determined simply by (a) knowing the type and subtype, and (b) looking at the data.
If any routing functions are required, the application programmer must provide them as part of the application.
 
Table 2‑1 Typed Buffers 
C structure defined by the application. VIEW types must have subtypes that designate individual data structures. A view description file, in which the fields and types that appear in the data structure are defined, must be available to client and server processes that use a data structure described in a VIEW typed buffer. Encoding and decoding are performed automatically if the buffer is passed between machines of different types.
VIEW does not support mbstring type buffers.
All buffer types are defined in a file called tmtypesw.c in the $TUXDIR/lib directory. Only buffer types defined in tmtypesw.c are known to your client and server programs. You can edit the tmtypesw.c file to add or remove buffer types. In addition, you can use the BUFTYPE parameter (in UBBCONFIG) to restrict the types and subtypes that can be processed by a given service.
The tmtypesw.c file is used to build a shared object or dynamic link library. This object is dynamically loaded by both Oracle Tuxedo administrative servers, and application clients and servers.
See Also
tuxtypes(5) in Oracle Tuxedo File Formats, Data Descriptions, MIBs, and System Processes Reference
UBBCONFIG(5) in Oracle Tuxedo File Formats, Data Descriptions, MIBs, and System Processes Reference
Allocating a Typed Buffer
Initially, no buffers are associated with a client process. Before a message can be sent, a client process must allocate a buffer of a supported type to carry a message. A typed buffer is allocated using the tpacall(3c) function, as follows:
char*
tpalloc(char *
type, char *subtype, long size)
Table 2‑2 describes the arguments to the tpalloc() function.
 
Pointer to the name of a subtype being specified (in the view description file) for a VIEW, VIEW32, X_COMMON, or RECORD typed buffer.
In the cases where a subtype is not relevant, assign the NULL value to this argument.
The Oracle Tuxedo system automatically associates a default buffer size with all typed buffers except CARRAY, X_OCTET, and XML, which require that you specify a size, so that the end of the buffer can be identified.
For all typed buffers other than CARRAY, X_OCTET, and XML, if you specify a value of zero, the Oracle Tuxedo system uses the default associated with that typed buffer. If you specify a size, the Oracle Tuxedo system assigns the larger of the following two values: the specified size or the default size associated with that typed buffer.
The default size for all typed buffers other than STRING, CARRAY, X_OCTET, and XML is 1024 bytes. The default size for STRING typed buffers is 512 bytes. There is no default value for CARRAY, X_OCTET, and XML; for these typed buffers you must specify a size value greater than zero. If you do not specify a size, the argument defaults to 0. As a result, the tpalloc() function returns a NULL pointer and sets tperrno to TPEINVAL.
The VIEW, VIEW32, X_C_TYPE, and X_COMMON typed buffers require the subtype argument, as shown in Listing 2‑1.
Listing 2‑1 Allocating a VIEW Typed Buffer
struct aud *audv; /* pointer to aud view structure */
. . .
audv = (struct aud *) tpalloc("VIEW", "aud", sizeof(struct aud));
. . .
 
Listing 2‑2 shows how to allocate an FML typed buffer. Note that a value of NULL is assigned to the subtype argument.
Listing 2‑2 Allocating an FML Typed Buffer
FBFR *fbfr; /* pointer to an FML buffer structure */
. . .
fbfr = (FBFR *)tpalloc("FML", NULL, Fneeded(f, v))
. . .
 
Listing 2‑3 shows how to allocate a CARRAY typed buffer, which requires that a size value be specified.
Listing 2‑3 Allocating a CARRAY Typed Buffer
char *cptr;
long casize;
. . .
casize = 1024;
cptr = tpalloc("CARRAY", NULL, casize);
. . .
 
Upon success, the tpalloc() function returns a pointer of type char. For types other than STRING and CARRAY, you should cast the pointer to the proper C structure or FML pointer.
If the tpalloc() function encounters an error, it returns the NULL pointer. The following list provides examples of error conditions:
Failure to specify a size value for a CARRAY, X_OCTET, or XML typed buffer
Failure to specify a type (or subtype in the case of VIEW)
Specifying a type that is not known to the system
For a complete list of error codes and explanations of them, refer to tpalloc(3c) in the Oracle Tuxedo ATMI C Function Reference.
Listing 2‑4 shows how to allocate a STRING typed buffer. In this example, the associated default size is used as the value of the size argument to tpalloc().
Listing 2‑4 Allocating a STRING Buffer
char *cptr;
. . .
cptr = tpalloc("STRING", NULL, 0);
. . .
 
Listing 2‑5 shows how to allocate a RECORD typed buffer. In this example, the size is retrieved from Frneeded(). RECORD typed buffers requires the subtype argument.
Listing 2‑5 Allocating a RECORD Buffer
struct RECORD *rec; /* pointer to an RECORD buffer structure */
. . .
rec = (struct RECORD *)tpalloc("RECORD", "CUSTOMER", Frneeded("CUSTOMER"));
. . .
 
See Also
tpalloc(3c) in Oracle Tuxedo ATMI C Function Reference
Putting Data in a Buffer
Once you have allocated a buffer, you can put data in it.
In Listing 2‑6, a VIEW typed buffer called aud is created with three members (fields). The three members are b_id, the branch identifier taken from the command line (if provided); balance, used to return the requested balance; and ermsg, used to return a message to the status line for the user. When audit is used to request a specific branch balance, the value of the b_id member is set to the branch identifier to which the request is being sent, and the balance and ermsg members are set to zero and the NULL string, respectively.
Listing 2‑6 Putting Data in a Message Buffer - Example 1
...
audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud));

/* Prepare aud structure */

audv->b_id = q_branchid;
audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");
...
 
When audit is used to query the total bank balance, the total balance at each site is obtained by a call to the BAL server. To run a query on each site, a representative branch identifier is specified. Representative branch identifiers are stored in an array named sitelist[]. Hence, the aud structure is set up as shown in Listing 2‑7.
Listing 2‑7 Placing Data in a Message Buffer - Example 2
...
/* Prepare aud structure */

audv->b_id = sitelist[i];/* routing done on this field */
audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");
...
 
The process of putting data into a STRING buffer is illustrated in the listing titled “Resizing a Buffer” on page 2‑14.
See Also
tpalloc(3c) in Oracle Tuxedo ATMI C Function Reference
Resizing a Typed Buffer
You can change the size of a buffer allocated with tpalloc() by using the tprealloc(3c) function as follows:
char*
tprealloc(char *
ptr, long size)
Table 2‑3 describes the arguments to the tprealloc() function.
 
Pointer to the buffer that is to be resized. This pointer must have been allocated originally by a call to tpalloc(). If it was not, the call fails and tperrno(5) is set to TPEINVAL to signify that invalid arguments have been passed to the function.
The pointer returned by tprealloc() points to a buffer of the same type as the original buffer. You must use the returned pointer to reference the resized buffer because the location of the buffer may have changed.
When you call the tprealloc() function to increase the size of the buffer, the Oracle Tuxedo system makes new space available to the buffer. When you call the tprealloc() function to make a buffer smaller, the system does not actually resize the buffer; instead, it renders the space beyond the specified size unusable. The actual content of the typed buffer remains unchanged. If you want to free up unused space, it is recommended that you copy the data into a buffer of the desired size and then free the larger buffer.
On error, the tprealloc() function returns the NULL pointer and sets tperrno to an appropriate value. Refer to tpalloc(3c) in Oracle Tuxedo ATMI C Function Reference for information on error codes.
WARNING:
If the tprealloc() function returns the NULL pointer, the contents of the buffer passed to it may have been altered and may be no longer valid.
Listing 2‑8 shows how to reallocate space for a STRING buffer.
Listing 2‑8 Resizing a Buffer
#include <stdio.h>
#include “atmi.h”

char instr[100]; /* string to capture stdin input strings */
long s1len, s2len; /* string 1 and string 2 lengths */
char *s1ptr, *s2ptr; /* string 1 and string 2 pointers */

main
()

{
  (void)gets(instr); /* get line from stdin */
  s1len = (long)strlen(instr)+1; /* determine its length */

  join application

  if ((s1ptr = tpalloc(“STRING”, NULL, s1len)) == NULL) {
     fprintf(stderr, “tpalloc failed for echo of: %s\n”, instr);
     leave application
     exit(1);
   }
   (void)strcpy(s1ptr, instr);

   make communication call with buffer pointed to by s1ptr

   (void)gets(instr); /* get another line from stdin */
   s2len = (long)strlen(instr)+1; /* determine its length */
   if ((s2ptr = tprealloc(s1ptr, s2len)) == NULL) {
     fprintf(stderr, “tprealloc failed for echo of: %s\n”, instr);
     free s1ptr's buffer
     leave application
     exit(1);
   }
   (void)strcpy(s2ptr, instr);

make communication call with buffer pointed to by s2ptr
. . .
}
 
Listing 2‑9 (an expanded version of the previous example) shows how to check for occurrences of all possible error codes.
Listing 2‑9 Error Checking for tprealloc()
. . .
if ((s2ptr=tprealloc(s1ptr, s2len)) == NULL)
   switch(tperrno) {
   case TPEINVAL:
     fprintf(stderr, "given invalid arguments\n");
     fprintf(stderr, "will do tpalloc instead\n");
       tpfree(s1ptr);
     if ((s2ptr=tpalloc("STRING", NULL, s2len)) == NULL) {
       fprintf(stderr, "tpalloc failed for echo of: %s\n", instr);
     leave application
    exit(1);
    }
    break;
  case TPEPROTO:
     fprintf(stderr, "tried to tprealloc before tpinit;\n");
     fprintf(stderr, "program error; contact product support\n");
       leave application
     exit(1);
  case TPESYSTEM:
     fprintf(stderr,
      "BEA Tuxedo error occurred; consult today's userlog file\n");
      leave application
    exit(1);
  case TPEOS:
     fprintf(stderr, "Operating System error %d occurred\n",Uunixerr);
     leave application
     exit(1);
  default:
     fprintf(stderr,
       "Error from tpalloc: %s\n", tpstrerror(tperrno));
     break;
}
 
See Also
tprealloc(3c) in Oracle Tuxedo ATMI C Function Reference
Checking for Buffer Type
The tptypes(3c) function returns the type and subtype (if one exists) of a buffer. The tptypes() function signature is as follows:
long
tptypes(char *
ptr, char *type, char *subtype)
Table 2‑4 describes the arguments to the tptypes() function.
 
Pointer to a data buffer. This pointer must have been originally allocated by a call to tpalloc() or tprealloc(), it may not be NULL, and it must be cast as a character type; otherwise, the tptypes() function reports an invalid argument error.
Pointer to the subtype of the data buffer, if one exists. subtype is of character type. For all types other than VIEW, VIEW32, RECORD, X_C_TYPE, and X_COMMON, upon return the subtype parameter points to a character array containing the NULL string.
Note:
For RECORD typed buffer, the maximum length of record name (subtype) is 32 bytes. If the length of record name is greater than 16, tptypes() will populate the first 16 bytes of subtype, but RECORD * pointer will point to the beginning of full-length record name.
Upon success, the tptypes() function returns the length of the buffer in the form of a long integer.
In the event of an error, tptypes() returns a value of -1 and sets tperrno(5) to the appropriate error code. For a list of these error codes, refer to the “Introduction to the C Language Application-to-Transaction Monitor Interface” and tpalloc(3c) in the Oracle Tuxedo ATMI C Function Reference.
You can use the size value returned by tptypes() upon success to determine whether the default buffer size is large enough to hold your data, as shown in Listing 2‑10.
Listing 2‑10 Getting Buffer Size
. . .
iptr = (FBFR *)tpalloc("FML", NULL, 0);
ilen = tptypes(iptr, NULL, NULL);
. . .
if (ilen < mydatasize)
      iptr=tprealloc(iptr, mydatasize);
 
See Also
tptypes(3c) in Oracle Tuxedo ATMI C Function Reference
Freeing a Typed Buffer
The tpfree(3c) function frees a buffer allocated by tpalloc() or reallocated by tprealloc(). The tpfree() function signature is as follows:
void
tpfree(char *
ptr)
The tpfree() function takes only one argument, ptr, which is described in Listing 2‑5.
 
Pointer to a data buffer. This pointer must have been allocated originally by a call to tpalloc() or tprealloc(), it may not be NULL, and it must be cast as a character type; otherwise, the function returns without freeing anything or reporting an error condition.
When freeing an FML32 buffer using tpfree(), the routine recursively frees all embedded buffers to prevent memory leaks. In order to preserve the embedded buffers, you should assign the associated pointer to NULL before issuing the tpfree() routine. When ptr is NULL, no action occurs.
Listing 2‑11 shows how to use the tpfree() function to free a buffer.
Listing 2‑11 Freeing a Buffer
struct aud *audv; /* pointer to aud view structure */
. . .
audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud));
. . .
tpfree((char *)audv);
 
See Also
tpfree(3c) in Oracle Tuxedo ATMI C Function Reference
Using a VIEW Typed Buffer
There are two kinds of VIEW typed buffers. The first, FML VIEW, is a C structure generated from an FML buffer. The second is simply an independent C structure.
The reason for converting FML buffers into C structures and back again (and the purpose of the FML VIEW typed buffers) is that while FML buffers provide data-independence and convenience, they incur processing overhead because they must be manipulated using FML function calls. C structures, while not providing flexibility, offer the performance required for lengthy manipulations of buffer data. If you need to perform a significant amount of data manipulation, you can improve performance by transferring fielded buffer data to C structures, operating on the data using normal C functions, and then converting the data back to the FML buffer for storage or message transmission.
For more information on the FML typed buffer and FML file conversion, refer to the Oracle Tuxedo ATMI FML Function Reference.
To use VIEW typed buffers, you must perform the following steps:
Compile the view description files using viewc, the Oracle Tuxedo view compiler. Specify the resulting header file in the #include statement for your application program.
Setting Environment Variables for a VIEW Typed Buffer
To use a VIEW typed buffer in an application, you must set the following environment variables shown in Table 2‑6.
 
FIELDTBLS or FIELDTBLS32
Comma-separated list of field table filenames for FML or FML32 typed buffers. Required only for FML VIEW types.
FLDTBLDIR or FLDTBLDIR32
Colon-separated list of directories to search for the field table files for FML and FML32 typed buffers. For Microsoft Windows, use a semicolon-separated list. Required only for FML VIEW types.
VIEWFILES or VIEWFILES32
Comma-separated list of allowable filenames for VIEW or VIEW32 description files.
VIEWDIR or VIEWDIR32
Colon-separated list of directories to search for VIEW or VIEW32 files. For Microsoft Windows, use a semicolon-separated list.
Creating a View Description File
To use a VIEW typed buffer, you must define the C record in a view description file. The view description file includes, a view for each entry, a view that describes the characteristic C structure mapping and the potential FML conversion pattern. The name of the view corresponds to the name of the C language structure.
The following format is used for each structure in the view description file:
$ /* View structure */
VIEW viewname
type cname fbname count flag size null
Table 2‑7 describes the fields that must be specified in the view description file for each C structure.
 
Data type of the field. Can be set to short, long, float, double, char, string, or carray.
Note:
mbstring data type is supported by the VIEW32 typed buffer only .
If you will be using the FML-to-VIEW or VIEW-to-FML conversion functions, this field must be included to indicate the corresponding FML name. This field name must also appear in the FML field table file. This field is not required for FML-independent VIEWs.
P—change the interpretation of the NULL value
S—one-way mapping from fielded buffer to structure
F—one-way mapping from structure to fielded buffer
N—zero-way mapping
C—generate additional field for associated count member (ACM)
L—hold number of bytes transferred for STRING, CARRAY, and MBSTRING
Note:
The view32 command automatically adds the L option flag for MBSTRING typed buffers
For STRING and CARRAY buffer types, specifies the maximum length of the value. This field is ignored for all other buffer types.
User-specified NULL value, or minus sign (-) to indicate the default value for a field. NULL values are used in VIEW typed buffers to indicate empty C structure members.
The default NULL value for all numeric types is 0 (0.0 for dec_t). For character types, the default NULL value is ‘\0’. For STRING, CARRAY, and MBSTRING types, the default NULL value is “ ”.
You may enclose STRING, CARRAY, MBSTRING, and char NULL values in double or single quotes. The view compiler does not accept unescaped quotes within a user-specified NULL value.
You can include a comment line by prefixing it with the # or $ character. Lines prefixed by a $ sign are included in the .h file.
Listing 2‑12 is an excerpt from an example view description file based on an FML buffer. In this case, the fbname field must be specified and match that which appears in the corresponding field table file. Note that the CARRAY1 field includes an occurrence count of 2 and sets the C flag to indicate that an additional count element should be created. In addition, the L flag is set to establish a length element that indicates the number of characters with which the application populates the CARRAY1 field.
Listing 2‑12 View Description File for FML VIEW
$ /* View structure */
VIEW MYVIEW
#type             cname              fbname            count flag size null
float              float1          FLOAT1          1     -    - 0.0
double             double1             DOUBLE1            1     -    - 0.0
long             long1               LONG1           1     -    - 0
short              short1           SHORT1           1      -    - 0
int              int1          INT1            1      -    - 0
dec_t              dec1                DEC1           1      -    9,16 0
char             char1               CHAR1            1      -    - '\0'
string             string1           STRING1            1      -    20 '\0'
carray             carray1            CARRAY1              2      CL   20 '\0'
   bool                 bool1               BOOL1               1      -     -        0 
   signedchar          signedchar1        SIGNEDCHAR1        1      -     -        0
   unsignedchar        unsignedchar1     UNSIGNEDCHAR1      1      -     -        0
   wchar_t             wchar_t1            WCHAR_T1           1      -     -        0
   unsignedint        unsignedint1       UNSIGNEDINT1       1      -     -         0
   unsignedlong       unsignedlong1      UNSIGNEDLONG1      1      -     -         0
   longlong            longlong1           LONGLONG1           1      -    -         0
   unsignedlonglong   unsignedlonglong1 UNSIGNEDLONGLONG1 1      -     -        0
   longdouble          longdouble1         LONGDOUBLE1        1      -    -         0
   struct               struct1             STRUCT1              1     -     -        0
END
 
Listing 2‑13 illustrates the same view description file for an independent VIEW.
Listing 2‑13 View Description File for an Independent View
$ /* View data structure */
VIEW MYVIEW
#type          cname          fbname count flag size null
float          float1              - 1 - - -
double          double1             - 1 - - -
long          long1             - 1 - - -
short          short1              - 1 - - -
int          int1              - 1 - - -
dec_t          dec1             - 1 - 9,16 -
char          char1             - 1 - - -
string          string1             - 1 - 20 -
carray          carray1             - 2 CL 20 -
   bool             bool1
   
signedchar       signedchar1
   unsignedchar     unsignedchar1
   wchar_t           wchar_t1
   unsignedint      unsignedint1
   unsignedlong     unsignedlong1
   longlong         longlong1
   unsignedlonglong unsignedlonglong1
   longdouble        longdouble1
   struct            struct1
END
 
Note that the format is similar to the FML-dependent view, except that the fbname and null fields are not relevant and are ignored by the viewc compiler. You must include a value (for example, a dash) as a placeholder in these fields.
Executing the VIEW Compiler
To compile a VIEW typed buffer, run the viewc command, specifying the name of the view description file as an argument. To specify an independent VIEW, use the -n option. You can optionally specify a directory in which the resulting output file should be written. By default, the output file is written to the current directory.
For example, for an FML-dependent VIEW, the compiler is invoked as follows:
viewc myview.v
Note:
To compile a VIEW32 typed buffer, run the viewc32 command.
For an independent VIEW, use the -n option on the command line, as follows:
viewc -n myview.v
The output of the viewc command includes:
One or more COBOL COPY files; for example, MYVIEW.cbl
Note:
Listing 2‑14 provides an example of the header file created by viewc.
Listing 2‑14 Header File Created Using the VIEW Compiler
struct MYVIEW {
float float1;
double double1;
long long1;
short short1;
int int1;
dec_t dec1;
char char1;
char string1[20];
unsigned short L_carray1[2]; /* length array of carray1 */
short C_carray1; /* count of carray1 */
char carray1[2][20];
   bool             bool1
   
signedchar       signedchar1
   unsignedchar     unsignedchar1
   wchar_t           wchar_t1
   unsignedint      unsignedint1
   unsignedlong     unsignedlong1
   longlong         longlong1
   unsignedlonglong unsignedlonglong1
   longdouble        longdouble1
   struct            struct1
};
 
The same header file is created for FML-dependent and independent VIEWs.
In order to use a VIEW typed buffer in client programs or service subroutines, you must specify the header file in the application #include statements.
See Also
viewc, viewc32(1) in Oracle Tuxedo Command Reference
Using a RECORD Typed Buffer
To use RECORD typed buffers, you must perform the following steps:
Compile the copybook files using cpy2record, the copybook to RECORD tool. Specify the RECORD name for your application program.
Setting Environment Variables for a RECORD Typed Buffer
To use a RECORD typed buffer in an application, you must set the following environment variables.
 
Colon-separated list of directories to search for RECORD files. For Microsoft Windows, use a semicolon-separated list.
Creating a Copybook File
To use a RECORD typed buffer, you must define the record in a COBOL copybook file. The copybook file includes a RECORD for each entry. The name of the RECORD corresponds to the name of the COBOL language field. For more information about COBOL copybook, please see COBOL language reference.
Below is an excerpt from an example COBOL copybook file.
$ /* copybook record */
01 CUSTOMER.
02 NAME PIC X(10).
02 BALANCE PIC S9(9) COMP-5.
02 ADDRESS PIC X(80).
Generating the RECORD Description File
To generate RECORD description file, run cpy2record command, specifying the name of the copybook file as an argument. You can optionally specify a directory in which the resulting output file should be written. By default, the output file is written to the current directory.
For example, the tool is invoked as follows:
cpy2record abc.cbl
The output of the cpy2record command is the binary version of the RECORD description file, for example, abc.R.
See Also
cpy2record in Oracle Tuxedo Command Reference
Using an FML Typed Buffer
To use FML typed buffers, you must perform the following steps:
Create an FML header file and specify the header file in a #include statement in the application.
FML functions are used to manipulate typed buffers, including those that convert fielded buffers to C structures and vice versa. By using these functions, you can access and update data values without having to know how data is structured and stored. For more information on FML functions, see Oracle Tuxedo ATMI FML Function Reference.
Setting Environment Variables for an FML Typed Buffer
To use an FML typed buffer in an application program, you must set the following environment variables shown in Table 2‑9.
 
FIELDTBLS or FIELDTBLS32
Comma-separated list of field table filenames for FML or FML32 typed buffers, respectively.
FLDTBLDIR or FLDTBLDIR32
Colon-separated list of directories to search for the field table files for FML and FML32, respectively. For Microsoft Windows, use a semicolon-separated list.
Creating a Field Table File
Field table files are always required when FML buffers and/or FML-dependent VIEWs are used. A field table file maps the logical name of a field in an FML buffer to a string that uniquely identifies the field.
The following format is used for the description of each field in the FML field table:
$ /* FML structure */
*base
value
name number type flags comments
Table 2‑10 describes the fields that must be specified in the FML field table file for each FML field.
 
*base value
Specifies a base for offsetting subsequent field numbers, providing an easy way to group and renumber sets of related fields. The *base option allows field numbers to be reused. For a 16-bit buffer, the base plus the relevant number must be greater than or equal to 100 and less than 8191. This field is optional.
Type of the field. This value can be any of the following: char, string, short, long, float, double, or carray.
All fields are optional, and may be included more than once.
Listing 2‑15 illustrates a field table file that may be used with the FML-dependent VIEW example.
Listing 2‑15 Field Table File for FML VIEW
# name number type flags comments
FLOAT1 110 float - -
DOUBLE1 111 double - -
LONG1 112 long - -
SHORT1 113 short - -
INT1 114 long - -
DEC1 115 string - -
CHAR1 116 char - -
STRING1 117 string - -
CARRAY1 118 carray - -
   BOOL1
   SIGNEDCHAR
1
   UNSIGNEDCHAR1
   WCHAR_T1
   UNSIGNEDINT1
   UNSIGNEDLONG1
   LONGLONG1
   UNSIGNEDLONGLONG1
   LONGDOUBLE1
   STRUCT1
 
Creating an FML Header File
In order to use an FML typed buffer in client programs or service subroutines, you must create an FML header file and specify it in the application #include statements.
To create an FML header file from a field table file, use the mkfldhdr(1) command. For example, to create a file called myview.flds.h, enter the following command:
mkfldhdr myview.flds
For FML32 typed buffers, use the mkfldhdr32 command.
Listing 2‑16 shows the myview.flds.h header file that is created by the mkfldhdr command.
Listing 2‑16 myview.flds.h Header File
/* fname fldid */
/* ----- ----- */

#define FLOAT1 ((FLDID)24686) /* number: 110 type: float */
#define DOUBLE1 ((FLDID)32879) /* number: 111 type: double */
#define LONG1 ((FLDID)8304) /* number: 112 type: long */
#define SHORT1 ((FLDID)113) /* number: 113 type: short */
#define INT1 ((FLDID)8306) /* number: 114 type: long */
#define DEC1 ((FLDID)41075) /* number: 115 type: string */
#define CHAR1 ((FLDID)16500) /* number: 116 type: char */
#define STRING1 ((FLDID)41077) /* number: 117 type: string */
#define CARRAY1 ((FLDID)49270) /* number: 118 type: carray */
#define   BOOL1
#define   SIGNEDCHAR
1
#define   UNSIGNEDCHAR1
#define   WCHAR_T1
#define   UNSIGNEDINT1
#define   UNSIGNEDLONG1
#define   LONGLONG1
#define   UNSIGNEDLONGLONG1
#define   LONGDOUBLE1
#define   STRUCT1
 
Specify the new header file in the #include statement of your application. Once the header file is included, you can refer to fields by their symbolic names.
See Also
mkfldhdr, mkfldhdr32(1) in Oracle Tuxedo Command Reference
Using an XML Typed Buffer and the Apache Xerces C++ Parser
As XML continues to gain acceptance as a data standard, Oracle Tuxedo customers are increasingly using XML typed buffers in their applications. To assist customers in this effort, Oracle has integrated the Apache Xerces C++ Version 2.5 parser into the Oracle Tuxedo software distribution.
This section introduces the following topics:
About the XML Typed Buffer
XML buffers enable Oracle Tuxedo applications to use XML for exchanging data within and between applications. Oracle Tuxedo applications can send and receive simple XML buffers, and route those buffers to the appropriate servers. All logic for dealing with XML documents, including parsing, resides in the application.
An XML document consists of:
The programming model for the XML buffer type is similar to that for the CARRAY buffer type: you must specify the length of the buffer with the tpalloc() function. The maximum supported size of an XML document is 4 GB.
Formatting and filtering for Events processing (which are supported when a STRING buffer type is used) are not supported for the XML buffer type. Therefore, the _tmfilter and _tmformat function pointers in the buffer type switch for XML buffers are set to NULL.
The XML parser in the Oracle Tuxedo system performs the following functions:
Data-dependent routing is supported for XML buffers. The routing of an XML document can be based on element content, or on element type and an attribute value. The XML parser determines the character encoding being used; if the encoding differs from the native character sets (US-ASCII or EBCDIC) used in the Oracle Tuxedo configuration files (UBBCONFIG and DMCONFIG), the element and attribute names are converted to US-ASCII or EBCDIC.
Attributes configured for routing must be included in an XML document. If an attribute is configured as a routing criteria but it is not included in the XML document, routing processing fails.
The content of an element and the value of an attribute must conform to the syntax and semantics required for a routing field value. The user must also specify the type of the routing field value. XML supports only character data. If a range field is numeric, the content or value of that field is converted to a numeric value during routing processing.
About the Apache Xerces C++ Parser
The Xerces-C++ 2.5.0 parser, written in a portable subset of C++, comes with a shared library for parsing, generating, manipulating, and validating XML documents. It complies with the XML 1.0 recommendation and associated standards DOM 1.0, DOM 2.0. SAX 1.0, SAX 2.0, Namespaces, and W3C’s XML Schema recommendation version 1.0.
Because the Xerces-C++ 1.7 parser did not cache the Document Type Definition (DTD) and XML Schema files when validation was required, or cache external entity files used in DTD, Oracle Tuxedo 8.1 improved the performance of the Xerces-C++ 1.7 parser by adding an option to cache external DTD, Schema, and entity files that might otherwise be retrieved repeatedly over the Web. Continued support for this modification is available with Tuxedo 9.x and Xerces C++ 2.5.0.
XML Parser Control
There are two ways to turn on/off caching for the Xerces-C++ parser:
Note:
XML Parser Support for ICU
The International Components for Unicode (ICU) 3.0 library, a C/C++ library that supports over 200 different coded character sets (encoding forms) on a wide variety of platforms, is included with the Oracle Tuxedo distribution. The Xerces-C++ 2.5.0 parser is built with the ICU 3.0 library.
XML Parser Sample Application
A sample application for using the Xerces-C++ parser ATMI functions is provided in the Oracle Tuxedo user documentation. Among other things, the sample demonstrates how to write a wrapper for the Xerces-C++ parser so that Tuxedo clients and servers written in C can call the Xerces-C++ ATMI functions.
Xerces Schema Sample
A sample application for using XML schemas with the Xerces parser is provided in the Oracle Tuxedo documentation. See Tutorial for xmlfmlapp: A Full C XML/FML32 Conversion Application in Tutorials for Developing Oracle Tuxedo ATMI Applications
See Also
getURLEntityCacheDir(3c), setURLEntityCacheDir(3c), getURLEntityCaching(3c), setURLEntityCaching(3c), Xerces API parser on-line documentation.
Converting XML Data To and From FML/FML32 Buffers
As an input/output format, XML data is gaining broader use in modern application development. Most Tuxedo customers, in contrast, have large investments in existing defined services that make use of Tuxedo FML/FML32 buffers as the preferred data transport.
Oracle Tuxedo addresses this issue by adding functionality that allows for data conversion of XML to and from FML/FML32 buffers. This conversion can be initiated one of two ways:
For programmers, on-demand conversion of XML data to and from FML/FML32 buffers features four new ATMI functions for manual conversion. For more information, see “Using On-Demand Conversion.”
For application administrators, automatic conversion of XML to and from FML/FML32 buffers features a new BUFTYPECONV parameter in the SERVICES section of the UBBCONFIG configuration file initiates conversion when the server is booted. For more information, see “Using Automatic Conversion.”
Regardless of the method used for conversion, the FML/FML32 field types are mapped to XML in a particular manner. For information on conversion mapping, see “Mapping XML To and From FML/FML32 Field Types.”
Note:
Increasing the size of shared libraries may cause running Tuxedo application processes (that directly or indirectly depend on those libraries) to consume increased amounts of memory which, in turn, can impact performance.
XML to and from FML/FML32 conversion should not be used by a Tuxedo system process.
For other known issues or limitations regarding conversion between XML and FML/FML32 buffers using the Xerces parser, see “Conversion Limitations.”
Using On-Demand Conversion
On-demand conversion gives you the option to manually execute conversion of XML data to FML/FML32 buffers or conversion of FML/FML32 buffers to XML.
The following four ATMI functions provide on-demand conversion:
tpxmltofml() - converts XML to FML
tpfmltoxml() - converts FML to XML
tpxmltofml32() - converts XML to FML32
tpfml32toxml() - converts FML32 to XML
For a detailed description of these functions and their arguments, see “Oracle Tuxedo ATMI C Function Reference.”
Initiating On-Demand Conversion
For on-demand conversion of XML data to and from FML/FML32 buffers, perform the following steps:
Use the rtag argument to specify the input/output XML root tag for the buffer type conversion in the function call (optional)
Set the flag argument to select Xerces parser options (optional)
On-Demand Conversion and Xerces Parser XML Validation
If you are using the ATMI functions to initiate conversion of XML to and from FML/FML32 buffers, parser validation is determined one of two ways.
For a detailed description of the ATMI functions and their Xerces parser flag arguments, see Oracle Tuxedo ATMI C Function Reference.”
Using Automatic Conversion
Automatic conversion starts and ends with XML. That is, XML buffers are input, converted and processed to FML/FML32 buffers, and finally reconverted back to XML.
To initiate conversion between XML and FML/FML32 buffers you must specify the BUFTYPECONV parameter in the SERVICES section of the UBBCONFIG file. This parameter accepts only one of two value options: XML2FML or XML2FML32.
When you boot a server with this parameter, the input buffer is converted from an XML buffer to an FML/FML32 buffer via client tpcall(), tpacall(), tpconnect(), or tpsend()before being delivered to the service. When tpreturn() or tpsend() is called, an FML/FML32 buffer is converted to XML before it is returned.
Services using the BUFTYPECONV parameter allow clients or other services to send and receive XML buffers without changing how the existing service handles FML/FML32 buffers.
Note:
Keep in mind the following regarding BUFTYPECONV parameter use:
When a service uses the BUFTYPECONV parameter, all output FML/FML32 buffers are converted to XML. Creating a new service name using the BUFTYPECONV parameter allows you to output XML and keep the original service name to output FML/FML32 buffers.
Automatic XML to FML/FML32 buffers conversion only takes action on input XML data. All other input buffers are not converted even if specified in BUFTYPECONV.
XML, FML, and FML32 input/output service data is converted only if the service acts as a server. In other words, if a client or other service makes a request to the service using the BUFTYPECONV parameter.
If a service using the BUFTYPECONV parameter acts as a client, conversion does not take place. For example, a service with the BUFTYPECONV parameter using tpcall() on another service.
In /Q messaging mode, TMQFORWARD uses tpcall() to call a service. If the called service uses the BUFTYPECONV parameter, automatic conversion will take place.
During automatic conversion, the input XML root element name cannot be saved, so the output XML root tag uses the default root tag <FML Type="FML"> or <FML Type="FML32">.
Initiating Automatic Conversion
For automatic conversion of XML data to and from FML/FML32 buffers, perform the following steps:
Add the BUFTYPECONV parameter specifying either XML2FML or XML2FML32, as appropriate.
Use TPXPARSFILE environment variable to control Xerces parser attributes and settings (optional).
Use tmloadcf -y to compile and load the UBBCONFIG file.
Use tmboot -y to boot the server
Automatic Conversion and Xerces Parser XML Validation
The Xerces parser uses default attribute settings to control XML validation during automatic conversion. However, Tuxedo supports 14 specific Xerces DOMParser class attributes that provide some automatic conversion customizing flexibility.
If you are using the automatic conversion method, parser validation is determined one of two ways:
Specifying validation options through the TPXPARSFILE environment variable
The TPXPARSFILE environment variable designates the fully qualified path to a text file that contains the XercesDOMParser class attribute settings you want to modify.
Each attribute in the text file is written on a separate line in the following format:
<parser attribute>=<setting>
The <parser attribute> can be any or all of the 14 parser attributes in the following table, where (D) denotes the default setting.
Note:
 
Listing 2‑17 is a sample input plain text file for the TPXPARSFILE environment variable.
Listing 2‑17 Sample Input for TXPARSFILE Environment Variable
CacheGrammarFromParse=True
DoNameSpaces=True
DoSchema=True
ExternalSchemaLocation= http://www.xml.org/sch.xsd
ExitOnFirstFatalError=c:\xml\example.xsd
IncludeIgnorableWhiteSpace=True
LoadGrammar=
NoNamespaceSchemaLocation=
StandardUriConformant=True
UseCachedGrammarInParse=True
UseScanner=WF
ValidationConstraintFatal=True
ValidationScheme=Val_Auto
ValidationSchemaFullChecking=True
 
Mapping XML To and From FML/FML32 Field Types
The relationship between the XML format and the FML/FML32 fields is one in which the XML element names are the same as the FML/FML32 field names, and the XML values are interpreted using the corresponding field type.
The opening and closing tag uses the name of the field. Attributes are optionally provided for FLD_FML32, FLD_MBSTRING and FLD_VIEW32. Field names and attributes are case sensitive.
The field value is read as a string and converted to the following field type:
<FIELDNAME Attribute="Attribute Value"> FIELDVALUE </FIELDNAME>
FML/FML32 field types are mapped to XML buffer types as follows:
 
The FLD_SHORT, FLD_LONG, FLD_CHAR, FLD_FLOAT, FLD_DOUBLE, and FLD_STRING fields are simple conversions to and from the XML string values.
During FLD_CARRAY field conversion, the XML byte stream value is converted from two alphanumeric characters in XML to one byte value in Tuxedo. That is, each XML pair of characters represents a hex byte value.
During conversion to XML, the FLD_PTR fieldname points to one of the following valid Tuxedo buffer types: STRING, MBSTRING, CARRAY, FML, FML32, and VIEW32 and ignores any invalid buffer types. When the buffer content is converted to XML, the BUFTYPE attribute is included in the buffer type tag (see example 1).
During conversion to FML32, the BUFTYPE attribute must be included in the buffer type tag. The only valid values are Tuxedo buffer types: STRING, MBSTRING, CARRAY, FML, FML32, and VIEW32. If the BUFTYPE attribute is not specified or an invalid value is used, the element is ignored in FML32.
The FLD_FML32 fieldname is supported with the opening and closing tags based upon the FML field name. This XML document includes multiple descriptions of <fieldname>value</fieldname> for each field contained in the buffer.
Note:
An optional attribute, Tpmbenc, can be used to specify the encoding for the entire MBSTRING field of FML32 buffers during XML to FML32 conversion
Example 1:
<ACCT Tpmbenc="EUC"><NM>Smith</NM><TRAN>OPEN</TRAN></ACCT>
Example 2: <BANK><BID>001</BID><ID><NM>Jones</NM><AC>001</AC></ID>
</BANK>
The FLD_VIEW32 fieldname is supported, and therefore, the FLD_INT and FLD_DECIMAL fields are also recognized. FLD_INT is treated like FLD_LONG.
The start and end tag is based on the FLD_VIEW32 field name. It will take a Vname attribute for specifying the view name to use. This XML document includes multiple descriptions of
where fbname is the buffer name of the view member field.
The FLD_MBSTRING field conversion uses the Encoding attribute and the field data to describe the FML32 field. This conversion is similar to Fmbpack32 usage. Please note the following conditions:
1.
If the Encoding attribute is present and the value is specified, the data values are used to create the FLD_MBSTRING value.
2.
If the Encoding attribute is not present and Tpmbenc has been set for the full FML32 buffer, then the FLD_MBSTRING adopts the Tpmbenc value.
3.
If the Encoding attribute is not present and Tpmbenc is not specified, then an attempt is made to get the process environment TPMBENC (all caps) and use that encoding as the FLD_MBSTRING value in place of the attribute definition.
Conversion Limitations
The following limitations exist for conversion of XML data to and from FML/FML32 buffers using the Xerces 2.5.0 parser delivered with Tuxedo.
Digitally signed XML, FML or FML32 buffers fail signature checking when using automatic conversion. The tpenvelope() function for digital signatures can only be used during on-demand conversion.
Conversion between XML and FML/FML32 buffers does not necessarily create the exact same XML document as which you started. Tuxedo FML/FML32 buffers group equivalent field types within a buffer and bases output order on that grouping; therefore, specific element ordering based on input XML is lost. The Xerces parser cannot track FML/FML32 field input order, or control FML/FML32 field output order.
Please note the following:
See Also
“Tutorial for xmlstockapp, a C and C++ XML Parser Application” in Tutorials for Developing Oracle Tuxedo ATMI Applications
tpfml32toxml(3c), tpfmltoxml(3c), tpxmltofml32(3c), and tpxmltofml(3c) in Oracle Tuxedo ATMI C Function Reference
tuxenv(5)and UBBCONFIG(5)in Oracle Tuxedo File Formats, Data Descriptions, MIBs, and System Processes Reference
Using an MBSTRING Typed Buffer
To support the multibyte coded character sets required by Chinese, Japanese, Korean, and other Asian Pacific languages, Oracle Tuxedo includes the MBSTRING typed buffer for transport of multibyte character user data. Chinese, Japanese, Korean, and other Asian Pacific languages use coded character sets that use more than one byte to represent a character.
Using the MBSTRING typed buffer and the multibyte character encoding feature, the Oracle Tuxedo system can convert user data from one encoding representation to another encoding representation when an MBSTRING buffer (or an FLD_MBSTRING field in an FML32 buffer) is transmitted between processes. Figure 2‑1 shows through example how encoding conversion works.
Figure 2‑1 Encoding Conversion Using MBSTRING Buffers—Example
As indicated in the example, the MBSTRING typed buffer is capable of carrying information identifying the code-set character encoding, or simply encoding, of its user data. In the example, the client-request MBSTRING buffer holds Japanese user data represented by the Shift-JIS (SJIS) encoding, while the server-reply MBSTRING buffer holds Japanese user data represented by the Extended UNIX Code (EUC) encoding. The multibyte character encoding feature reads environment variables TPMBENC and TPMBACONV to determine the source encoding, the target encoding, and the state (on or off) of automatic encoding conversion.
The encoding conversion capability enables the underlying Tuxedo system software to convert the encoding representation of an incoming message to an encoding representation supported by the machine on which the receiving process is running. The conversion is neither a conversion between character code sets nor a translation between languages, but rather a conversion between different character encodings for the same language.
Multibyte Character Encoding Control
There are two ways of controlling character encoding conversions:
The following two flowcharts demonstrate how the environment variables and ATMI are used during the allocating, sending, receiving, and converting of an MBSTRING buffer.
Figure 2‑2 Allocating and Sending an MBSTRING Buffer
Figure 2‑3 Receiving and Converting an MBSTRING Buffer (Sheet 1 of 2)
Figure 2‑3 Receiving and Converting an MBSTRING Buffer (Sheet 2 of 2)
Enabling MBSTRING to be Self-describing
MBSTRING can be self-describing if sendlen is set to zero. Some Tuxedo buffers provide a capability for the buffer to determine its own length if the user does not provide it. This self-describing behavior is triggered when an application sets the sendlen argument of a Tuxedo function call (for example, tpcall()) to zero.
Implementation
This self-describing behavior is implemented by adding the following:
_mbspresend() function to the MBSTRING typeswitch function list
A protective file, $TUXDIR/udataobj/sendlen0_unsafe_tpmbenc, containing the names of the codeset encoding names which are considered unsafe to use with the feature.
The _mbspresend() addition requires any user who customizes Tuxedo buffers to rebuild their applications.
Safe/Unsafe Encoding Names
The idea of safe or unsafe encoding names specified by TPMBENC comes from whether or not the multibyte character data for these encodings can contain embedded NULLs. Because the _mbspresend() function uses strlen() to determine the length of the data, an embedded NULL causes the length to be incorrectly set and the wrong number of data bytes are sent.
The default list in sendlen0_unsafe_tpmbenc has the multibyte Unicode encoding names (in uppercase and lowercase, for convenience) which can contain embedded NULLs. You should modify this list as application administration or performance is considered.
If the file exists and contains a list of names, then Tuxedo reads this file once (at _mbsinit()) and stores the list internally. During mbsinit(), the TPMBENC name is compared to the stored list and the buffer is set as safe or unsafe to use. When _mbspresend() is called (sendlen argument is set to zero) and the buffer is marked safe, then the length is set internally by Tuxedo.
Multibyte Character Support Limitations
The following limitations exist for the multibyte character support in Oracle Tuxedo:
Multibyte Character Encoding Support for libiconv
libiconv, an encoding conversion library that provides support for many coded character sets and encodings, is included with the Oracle Tuxedo 8.1 or later software distribution. The multibyte character encoding feature uses the character conversion functions in this library to convert from any of the supported character encodings to any other supported character encoding, through Unicode conversion.
libiconv provides support for the following encodings:
See Also
For more information about multibyte character encoding, see the following documents:
tuxenv(5), tuxtypes(5), and typesw(5) in Oracle Tuxedo File Formats, Data Descriptions, MIBs, and System Processes Reference
Customizing a Buffer
You may find that the buffer types supplied by the Oracle 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 Oracle Tuxedo system supports customized buffers.
To customize a buffer, you need to identify the following characteristics shown in Table 2‑11.
 
Table 2‑12 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 Oracle Tuxedo system uses default processing, as necessary.
 
Specifies filter information. This routine is called to evaluate an expression against a typed buffer and to return a match if it finds one. If the typed buffer is VIEW or FML, the FML Boolean expressions are used. This routine is used by the EventBroker to evaluate matches for events.
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.
2.
3.
4.
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. Listing 2‑18 shows the switch delivered with the system.
Listing 2‑18 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 Listing 2‑19.
Listing 2‑19 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.
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 Listing 2‑20.
Listing 2‑20 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 the Oracle 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. Listing 2‑21 provides an example.
Listing 2‑21 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:
This section describes how to make all Oracle 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 Oracle Tuxedo system.
1.
Copy and modify $TUXDIR/lib/tmtypesw.c, as described in “Adding a New Buffer Type to tm_typesw” on page 2‑66. If additional functions are required, store them in either tmtypesw.c or a separate C source file.
2.
Compile tmtypesw.c with the flags required for shared objects.
3.
4.
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 Oracle Tuxedo system. We recommend using one of the following directories: $APPDIR, $TUXDIR/lib, or $TUXDIR/bin (on a Windows 2003 platform).
Different platforms assign different names to the buffer type switch shared object, to conform to operating system conventions.
 
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” on page 2‑67, then you can use the commands shown in Listing 2‑22 to make the modified buffer type switch available to your application.
Listing 2‑22 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 reference page buffer(3c) in Oracle Tuxedo ATMI 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 the _tmencdec routine. When defining new buffer types, follow the procedure provided in “Defining Your Own Buffer Types” on page 2‑56 for building servers with services that will use your new buffer type.
The encode/decode routines are called only when the Oracle Tuxedo system determines that data is being sent between two machines that are not of the same TYPE.
 

Copyright © 1994, 2017, Oracle and/or its affiliates. All rights reserved.