BEA Logo BEA Tuxedo Release 8.0

  BEA Home  |  Events  |  Solutions  |  Partners  |  Products  |  Services  |  Download  |  Developer Center  |  WebSUPPORT

 

   Tuxedo Documentation   |   Programming BEA Tuxedo ATMI Applications Using C   |   Local Topics   |   Previous Topic   |   Next Topic   |   Contents

 


Sending Asynchronous Messages

This section explains how to:

The type of asynchronous processing discussed in this section is sometimes referred to as fan-out parallelism because it allows a client's requests to be distributed (or "fanned out") simultaneously to several services for processing.

The other type of asynchronous processing supported by the BEA Tuxedo system is pipeline parallelism in which the tpforward() function is used to pass (or forward) a process from one service to another. For a description of the tpforward() function, refer to Writing Servers.

Sending an Asynchronous Request

The tpacall(3c) function sends a request to a service and immediately returns. Use the following signature to call the tpacall() function:

int
tpacall(char *svc, char *data, long len, long flags)

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

tpacall( ) Function Arguments

Argument

Description

svc

Pointer to the name of the service offered by your application.

data

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 data 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 data.

len

Length of the request data in the buffer referenced by data. 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, indicating that the argument should be ignored.

flags

Flag options. You can list a group of flags by using the logical OR operator. If you set this value to zero, the communication is conducted in the default manner. For a list of valid flags and defaults, refer to tpacall(3c) in the BEA Tuxedo ATMI C Function Reference.

The tpacall() function sends a request message to the service named in the svc parameter and immediately returns from the call. Upon successful completion of the call, the tpacall() function returns an integer that serves as a descriptor used to access the correct reply for the relevant request. While tpacall() is in transaction mode (as described in Writing Global Transactions) there may not be any outstanding replies when the transaction commits; that is, within a given transaction, for each request for which a reply is expected, a corresponding reply must eventually be received.

If the value TPNOREPLY is assigned to the flags parameter, the parameter signals to tpacall() that a reply is not expected. When this flag is set, on success tpacall() returns a value of 0 as the reply descriptor. If subsequently passed to the tpgetrply() function, this value becomes invalid. Guidelines for using this flag value correctly when a process is in transaction mode are discussed in Writing Global Transactions.

On error, tpacall() returns -1 and sets tperrno(5) to a value that reflects the nature of the error. tpacall() returns many of the same error codes as tpcall(). The differences between the error codes for these functions are based on the fact that one call is synchronous and the other, asynchronous. These errors are discussed at length in Managing Errors.

Example: Sending an Asynchronous Message with TPNOTRAN | TPNOREPLY

The following example shows how tpacall() uses the TPNOTRAN and TPNOREPLY flags. This code is similar to the code in Example: Sending a Synchronous Message with TPNOTRAN Set. In this case, however, a reply is not expected from the PRINTER service. By setting both TPNOTRAN and TPNOREPLY flags, the client is indicating that no reply is expected and the PRINTER service will not participate in the current transaction. This situation is discussed more fully in Managing Errors.

Sending an Asynchronous Message with TPNOREPLY | TPNOTRAN

#include <stdio.h>
#include "atmi.h"

main()

{
char *rbuf; /* report buffer */
long rlen, rrlen; /* buffer lengths of send, reply buffers for report */

join application

if (rbuf = tpalloc("STRING", NULL, 0) == NULL) /* allocate space for report */
error
(void)strcpy(rbuf, "REPORT=accrcv DBNAME=accounts");/* send parms of report */
rlen = strlen(rbuf)+1; /* length of request */

start transaction

if (tpcall("REPORT", rbuf, rlen, &rbuf, &rrlen, 0)
== -1) /* get report print stream */
   error
if (tpacall("PRINTER", rbuf, rrlen, TPNOTRAN|TPNOREPLY)
== -1) /* send report to printer */
error

. . .
commit transaction
free buffer
leave application
}

Example: Sending Asynchronous Requests

The following example shows a series of asynchronous calls that make up the total bank balance query. Because the banking application data is distributed among several database sites, an SQL query needs to be executed against each one. The application performs these queries by selecting one branch identifier per database site, and calling the ABAL or TBAL service for each site. The branch identifier is not used in the actual SQL query, but it enables the BEA Tuxedo system to route each request to the proper site. In the following code, the for loop invokes tpacall() once for each site.

Sending Asynchronous Requests

audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");

for (i=0; i<NSITE; i++) {

/* Prepare aud structure */

audv->b_id = sitelist[i]; /* routing done on this field */

/* Do tpacall */

if ((cd[i]=tpacall(sname, (char *)audv, sizeof(struct aud), 0))
== -1) {
(void)fprintf (stderr,
"%s: %s service request failed for site rep %ld\n",
pgmname, sname, sitelist[i]);
tpfree((char *)audv);
return(-1);
}
}

Getting an Asynchronous Reply

A reply to a service call can be received asynchronously by calling the tpgetrply(3c) function. The tpgetrply() function dequeues a reply to a request previously sent by tpacall().

Use the following signature to call the tpgetrply() function:

int
tpgetrply(int *cd, char **data, long *len, long flags)

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

tpgetrply( ) Function Arguments

Argument

Description

cd

Pointer to the call descriptor returned by the tpacall() function.

*data

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 *data to zero. 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, then you must set odata to the address of the pointer returned when you allocated the input buffer. It is an error for this parameter to point to NULL.

len

Pointer to the length of the reply data. It is an error for this parameter to point to NULL.

flags

Flag options. You can list a group of flags using the logical OR operator. If you set this value to zero, the communication is conducted in the default manner. For a list of valid flags and defaults, refer to tpcall(3c)) in the BEA Tuxedo ATMI C Function Reference.

By default, the function waits for the arrival of the reply that corresponds to the value referenced by the cd parameter. During this waiting interval, a blocking timeout may occur. A time-out occurs when tpgetrply() fails and tperrno(5) is set to TPETIME (unless the flags parameter is set to TPNOTIME).

 

back to top previous page next page