6.2 Sending Synchronous Messages

The tpcall() function sends a request to a service subroutine and synchronously waits for a reply. Use the following signature to call the tpcall() function:

int
tpcall(char *svc, char *idata, long ilen, char **odata, long *olen, long flags)

The following table describes the arguments to the tpcall() function.

Table 6-1 tpcall( ) Function Arguments

Argument Description
svc Pointer to the name of the service offered by your application.
idata Pointer that contains the address of the data portion of the request. The pointer must reference a typed buffer that was allocated by a prior call to tpalloc(). Note that the type (and optionally the subtype) of idata must match the type (and optionally the subtype) expected by the service routine. If the types do not match, the system sets tperrno to TPEITYPE and the function call fails. If the request requires no data, set idata to the NULL pointer. This setting means that the parameter can be ignored. If no data is being sent with the request, you do not need to allocate a buffer for idata .
ilen Length of the request data in the buffer referenced by idata . If the buffer is a self-defining type, that is, an FML, FML32, VIEW, VIEW32, X_COMMON, X_C_TYPE, or STRING buffer, you can set this argument to zero to indicate that the argument must be ignored.
*odata Address of a pointer to the output buffer that receives the reply. You must allocate the output buffer using the tpalloc() function. If the reply message contains no data, upon successful return from tpcall(), the system sets *olen to zero, and the pointer and the contents of the output buffer remain unchanged. You can use the same buffer for both the request and reply messages. If you do, you must set *odata to the address of the pointer returned when you allocate the input buffer. It is an error for this parameter to point to NULL.
olen Pointer to the length of the reply data. It is an error for this parameter to point to NULL.
flags Flag options. You can OR a series of flags together. If you set this value to zero, the communication is conducted in the default manner. For a list of valid flags and the defaults, refer to tpcall(3c) in the Oracle Tuxedo ATMI C Function Reference.

tpcall() waits for the expected reply.

Note:

Calling the tpcall() function is logically the same as calling the tpcall() function immediately followed by tpgetrply(), as described in Sending Asynchronous Messages.

The request carries the priority set by the system for the specified service (svc) unless a different priority has been explicitly set by a call to the tpsprio() function (described in Setting and Getting Message Priorities).

tpcall() returns an integer. On failure, the value of this integer is -1 and the value of tperrno(5) is set to a value that reflects the type of error that occurred. For information on valid error codes, refer to tpcall(3c) in the Oracle Tuxedo ATMI C Function Reference.

Note:

Communication calls may fail for a variety of reasons, many of which can be corrected at the application level. Possible causes of failure include: application defined errors (TPESVCFAIL), errors in processing return arguments (TPESVCERR), typed buffer errors (TPEITYPE, TPEOTYPE), timeout errors (TPETIME), and protocol errors (TPEPROTO), among others. For a detailed discussion of errors, refer to Managing Errors. For a complete list of possible errors, refer to tpcall() in the Oracle Tuxedo ATMI C Function Reference.

The Oracle Tuxedo system automatically adjusts a buffer used for receiving a message if the received message is too large for the allocated buffer. You should test for whether or not the reply buffers have been resized.

To access the new size of the buffer, use the address returned in the * olen parameter. To determine whether a reply buffer has changed in size, compare the size of the reply buffer before the call to tpcall() with the value of *olen after its return. If *olen is larger than the original size, the buffer has grown. If not, the buffer size has not changed.

You must reference the output buffer by the value returned in odata after the call because the output buffer may change for reasons other than an increase in buffer size. You do not need to verify the size of request buffers because the request data is not adjusted once it has been allocated.

Note:

If you use the same buffer for the request and reply message, and the pointer to the reply buffer has changed because the system adjusted the size of the buffer, then the input buffer pointer no longer references a valid address.