BEA Logo BEA Tuxedo Release 7.1

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   Tuxedo Doc Home   |   Programming   |   Topic List   |   Previous   |   Next   |   Contents

   Programming a BEA Tuxedo Application Using FML

Buffer Allocation and Initialization

The functions described in this section are provided for writing stand-alone FML programs. If you are using the BEA Tuxedo ATMI functions, keep in mind that for tasks such as allocating and freeing message buffers, you must call ATMI functions such as tpalloc(3c), tprealloc(3c), and tpfree(3c), instead of FML functions such as Falloc, Falloc32(3fml), Frealloc, Frealloc32(3fml), and Ffree, Ffree32(3fml).

Most FML functions require a pointer to a fielded buffer as an argument. The typedef FBFR is available for declaring such pointers, as shown in the following example.

FBFR *fbfr;

In this section, the variable fbfr refers to a pointer to a fielded buffer. Never attempt to declare fielded buffers themselves; declare only pointers to fielded buffers.

When a server receives a request that contains an FML buffer, it allocates space for that FML buffer and for any embedded views or buffers referenced by FLD_PTR fields. A pointer to the new FML buffer is passed to the user-written code. Once the server processing is complete, all buffers allocated when the message was received must be destroyed. The BEA Tuxedo system checks the FML buffer and all subsidiary buffers, and deletes any buffers to which it finds references. As a programmer writing server code, you should be aware of the following situations:

The functions used to reserve space for fielded buffers are explained in the following text, but first we describe a function that can be used to determine whether a given buffer is, in fact, a fielded buffer.

Fielded

Fielded (or Fielded32) is used to test whether the specified buffer is fielded.

int
Fielded(FBFR *fbfr)

Fielded32 is used with 32-bit FML.

Fielded returns true (1) if the buffer is fielded. It returns false (0) if the buffer is not fielded but does not set Ferror.

For more information, refer to Fielded, Fielded32(3fml) in the BEA Tuxedo FML Function Reference.

Fneeded

The amount of memory to allocate for a fielded buffer depends on the maximum number of fields the buffer will contain and the total amount of space needed for all the field values. The function Fneeded can be used to determine the amount of space (in bytes) needed for a fielded buffer; it takes the number of fields and the space needed for all field values (in bytes) as arguments.

long
Fneeded(FLDOCC F, FLDLEN V)

Here:

The space needed for field values is computed by estimating the amount of space that is required by each field value if stored in standard structures (for example, a long is stored as a long and needs four bytes). For variable length fields, estimate the average amount of space needed for the field. The space calculated by Fneeded includes a fixed overhead for each field; it adds that to the space needed for the field values.

Once you obtain the estimate of space from Fneeded, you can allocate the desired number of bytes using malloc(3) and set up a pointer to the allocated memory space. For example, the following code allocates space for a fielded buffer large enough to contain 25 fields and 300 bytes of values.

#define NF 25
#define NV 300
extern char *malloc;
. . .
if((fbfr = (FBFR *)malloc(Fneeded(NF, NV))) == NULL)
F_error("pgm_name"); /* no space to allocate buffer */

However, this allocated memory space is not yet a fielded buffer. Finit must be used to initialize it.

For more information, refer to Fneeded, Fneeded32(3fml) in the BEA Tuxedo FML Function Reference.

Fvneeded

The Fvneeded function determines the amount of space (in bytes) needed for a VIEW buffer. The function takes a pointer to the name of the VIEW as an argument.

long
Fvneeded(char *subtype)

The Fvneeded function returns the size of the VIEW in number of bytes.

For more information, refer to Fvneeded, Fvneeded32(3fml) in the BEA Tuxedo FML Function Reference.

Finit

The Finit function initializes an allocated memory space as a fielded buffer.

int
Finit(FBFR *fbfr, FLDLEN buflen)

Here:

A call to Finit to initialize the memory space allocated in the previous example looks like the following code.

Finit(fbfr, Fneeded(NF, NV));

Now fbfr points to an initialized, empty fielded buffer. Up to Fneeded(NF, NV) bytes minus a small amount (F_OVHD as defined in fml.h) are available in the buffer to hold fields.

Note: The numbers used in the malloc(3) call (as described in the previous section) and Finit call must be the same.

For more information, refer to Finit, Finit32(3fml) in the BEA Tuxedo FML Function Reference.

Falloc

Calls to Fneeded, malloc(3) and Finit may be replaced by a single call to Falloc, which allocates the desired amount of space and initializes the buffer.

FBFR *
Falloc(FLDOCC
F, FLDLEN V)

Here:

A call to Falloc that provides the same functionality created by the calls to Fneeded, malloc(), and Finit described in the previous three sections, must be written as follows.

extern FBFR *Falloc;
. . .
if((fbfr = Falloc(NF, NV)) == NULL)
F_error("pgm_name"); /* couldn't allocate buffer */

Storage allocated with Falloc (or Fneeded, malloc(3), and Finit) should be freed with Ffree. (See Ffree, Ffree32(3fml) in the BEA Tuxedo FML Function Reference.)

For more information, refer to Falloc, Falloc32(3fml) in the BEA Tuxedo FML Function Reference.

Ffree

Ffree is used to free memory space allocated as a fielded buffer. Ffree32 does not free the memory area referenced by a pointer in a FLD_PTR field.

int
Ffree(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example.

#include  <fml.h>
. . .
if(Ffree(fbfr) < 0)
F_error("pgm_name"); /* not fielded buffer */

Ffree is preferable to free(3), because Ffree invalidates a fielded buffer, whereas free(3) does not. It is necessary to invalidate fielded buffers because malloc(3) re-uses memory that has been freed without clearing it. Thus, if free(3) is used, malloc can return a piece of memory that looks like a valid fielded buffer, but is not.

Space for a fielded buffer may also be reserved directly. The buffer must begin on a short boundary. You must allocate at least F_OVHD bytes (defined in fml.h) for the buffer; if you do not, Finit returns an error.

The following code is analogous to the preceding example but Fneeded cannot be used to size the static buffer because it is not a macro.

/* the first line aligns the buffer */
static short buffer[500/sizeof(short)];
FBFR *fbfr=(FBFR *)buffer;
. . .
Finit(fbfr, 500);

Be careful not to enter code such as the following!

FBFR badfbfr;
. . .
Finit(&badfbfr, Fneeded(NF, NV));

This code is wrong: the structure for FBFR is not defined in the user header files. As a result, a compilation error will be produced.

For more information, refer to Ffree, Ffree32(3fml) in the BEA Tuxedo FML Function Reference.

Fsizeof

Fsizeof returns the size of a fielded buffer in bytes.

long
Fsizeof(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. In the following code, for example, Fsizeof returns the same number that Fneeded returned when the fielded buffer was originally allocated.

long bytes;
. . .
bytes = Fsizeof(fbfr);

For more information, refer to Fsizeof, Fsizeof32(3fml) in the BEA Tuxedo FML Function Reference.

Funused

Funused may be used to determine how much space is available in a fielded buffer for additional data.

long
Funused(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example.

long unused;
. . .
unused = Funused(fbfr);

Note that Funused does not indicate the location, in the buffer, of the unused bytes; only the number of unused bytes is specified.

For more information, refer to Funused, Funused32(3fml) in the BEA Tuxedo FML Function Reference.

Fused

Fused may be used to determine how much space is used in a fielded buffer for data and overhead.

long
Fused(FBFR *fbfr)

Here fbfr is a pointer to a fielded buffer. Consider the following example.

long used;
. . .
used = Fused(fbfr);

Note that Fused does not indicate the location, in the buffer, of the used bytes; only the number of used bytes is specified.

For more information, refer to Fused, Fused32(3fml) in the BEA Tuxedo FML Function Reference.

Frealloc

This function enables you to change the size of a buffer for which you have allocated space by calling Falloc.

If you have allocated space with tpalloc(3c), you must call tprealloc(3c) to reallocate that space.) Being able to re-size the buffer can be useful if, for example, a buffer runs out of space while a new field value is being added. Simply by calling Frealloc you can increase the size of the buffer. In other situations you may want to call Frealloc to decrease the size of the buffer.

FBFR *
Frealloc(FBFR *fbfr, FLDOCC nf, FLDLEN nv)

Here:

Consider the following example.

FBFR *newfbfr;
. . .
if((newfbfr = Frealloc(fbfr, NF+5, NV+300)) == NULL)
F_error("pgm_name"); /* couldn't re-allocate space */
else
fbfr = newfbfr; /* assign new pointer to old */

In this case, the application needed to remember the number of fields and the number of value space bytes previously allocated. Note that the arguments to Frealloc (as with its counterpart realloc(3)) are absolute values, not increments. This example does not work if it is necessary to re-allocate space several times.

The following example shows a second way of incrementing the allocated space.

/* define the increment size when buffer out of space */
#define INCR 400
FBFR *newfbfr;
. . .
if((newfbfr = Frealloc(fbfr, 0, Fsizeof(fbfr)+INCR)) == NULL)
F_error("pgm_name"); /* couldn't re-allocate space */
else
fbfr = newfbfr; /* assign new pointer to old */

You do not need to know the number of fields or the value space size with which the buffer was last initialized. Thus, the easiest way to increase the size is to use the current size plus the increment as the value space. The previous example can be executed as many times as needed without remembering past executions or values. You do not need to call Finit after calling Frealloc.

If the amount of additional space requested in the call to Frealloc is contiguous to the old buffer, newfbfr and fbfr in the previous examples are the same. However, defensive programming dictates that you should declare newfbfr as a safeguard in case either a new value or NULL is returned. If Frealloc fails, do not use fbfr again.

Note: The buffer size can be decreased only to the number of bytes currently being used in the buffer.

For more information, refer to Frealloc, Frealloc32(3fml) in the BEA Tuxedo FML Function Reference.