![]() |
![]() |
|
|
Dequeuing Messages
The syntax for tpdequeue() is as follows.
#include <atmi.h>
int tpdequeue(char *qspace, char *qname, TPQCTL *ctl, \
char **data, long *len, long flags)
When this call is issued it tells the system to dequeue a message from the qname queue in the queue space named qspace. The message is placed in a buffer (originally allocated by tpalloc(3c)) at the address pointed to by *data. len points to the length of the data. If len is 0 on return from tpdequeue(), the message had no data portion. By the use of bit settings in flags the system is informed how the call to tpdequeue() is to be handled. The TPQCTL structure pointed to by ctl carries further information about how the call should be handled.
tpdequeue(3c) Arguments
There are some important arguments to control the operation of tpdequeue(3c). Let's look at some of them.
tpdequeue(): the qspace Argument
qspace identifies a queue space previously created by the administrator. When the TMQUEUE server is defined in the SERVERS section of the configuration file, the service names it offers are aliases for the actual queue space name (which is specified as part of the OPENINFO parameter in the GROUPS section). For example, when your application uses the server TMQUEUE, the value pointed at by the qspace argument is the name of a service advertised by TMQUEUE. If no service aliases are defined, the default service is the same as the server name, TMQUEUE. In this case the configuration file may include:
TMQUEUE
SRVGRP = QUE1 SRVID = 1
GRACE = 0 RESTART = Y CONV = N
CLOPT = "-A"
or
CLOPT = "-s TMQUEUE"
The entry for server group QUE1 has an OPENINFO parameter that specifies the resource manager, the pathname of the device and the queue space name. The qspace argument in a client program then looks like this:
if (tpdequeue("TMQUEUE", "REPLYQ", (TPQCTL *)&qctl,
(char **)&reqstr, &len,TPNOTIME) == -1) {
Error checking
}
The example shown on the TMQUEUE(5) reference page shows how alias service names can be included when the server is built and specified in the configuration file. The sample program in A Sample Application, also specifies an alias service/queue space name.
tpdequeue(): the qname Argument
Queue names in a queue space must be agreed upon by the applications that will access the queue space. This is especially important for reply queues. If qname refers to a reply queue, the administrator creates it (and often an error queue) in the same manner that he or she creates any other queue. qname is a pointer to the name of the queue from which to retrieve the message or reply.
tpdequeue(): the data and len Arguments
These arguments have slightly different meanings than their counterparts in tpenqueue(). *data points to the address of a buffer where the system is to place the message being dequeued. When tpdequeue() is called, it is an error for its value to be NULL.
When tpdequeue() returns, len points to a long that carries information about the length of the data retrieved. If it is 0, it means that the reply had no data portion. This can be a legitimate and successful reply in some applications; receiving even a 0 length reply can be used to show successful processing of the enqueued request. If you wish to know whether the buffer has changed from before the call to tpdequeue(), save the length prior to the call to tpdequeue() and compare it to len after the call completes.
tpdequeue(): the flags Arguments
flags values are used to tell the BEA Tuxedo system how the tpdequeue() call is handled; the following are valid flags:
TPQCTL Structure
The third argument to tpdequeue() is a pointer to a structure of type TPQCTL. The TPQCTL structure has members that are used by the application and by the BEA Tuxedo system to pass parameters in both directions between application programs and the queued message facility. The client that calls tpdequeue() sets flags to mark fields for which the system should supply values. As described earlier, the structure is also used by tpenqueue(); some of the members apply only to that function. The entire structure is shown in The tpqctl_t Structure.
As input to tpdequeue(), the following fields may be set in the TPQCTL structure:
long flags; /* indicates which of the values are set */
char msgid[32]; /* id of message to dequeue */
char corrid[32]; /* correlation identifier of message to dequeue */
The following are valid flags on input to tpdequeue().
The following is a list of valid bits for the flags parameter controlling output information from tpdequeue(). For any of these bits, if the flag bit is turned on when tpdequeue() is called, the associated field in the structure (see The tpqctl_t Structure) is populated with the value provided when the message was queued, and the bit remains set. If a value is not available (that is, no value was provided when the message was queued) or the bit is not set when tpdequeue() is called, tpdequeue() completes with the flag turned off.
The following remaining bits for the flags parameter are cleared (set to zero) when tpdequeue() is called: TPQTOP, TPQBEFOREMSGID, TPQTIME_ABS, TPQTIME_REL, TPQEXPTIME_ABS, TPQEXPTIME_REL, and TPQEXPTIME_NONE. These bits are valid bits for the flags parameter controlling input information for tpenqueue().
If the call to tpdequeue() failed and tperrno(5) is set to TPEDIAGNOSTIC, a value indicating the reason for failure is returned in ctl->diagnostic. The valid codes for ctl->diagnostic include those for tpenqueue() described in TPQCTL Structure (except for QMENOSPACE and QMERELEASE) and the following additional codes.
Using TPQWAIT
When tpdequeue() is called with flags (of the TPQCTL structure) set to include TPQWAIT, if a message is not immediately available, the TMQUEUE server waits for the arrival, on the queue, of a message that matches the tpdequeue() request before tpdequeue() returns control to the caller. The TMQUEUE process sets the waiting request aside and processes requests from other processes while waiting to satisfy the first request. If TPQGETBYMSGID and/or TPQGETBYCORRID are also specified, the server waits until a message with the indicated message identifier and/or correlation identifier becomes available on the queue. If neither of these flags is set, the server waits until any message is put onto the queue. The amount of time it waits is controlled by the caller's transaction timeout, if the call is in transaction mode, or by the -t option in the CLOPT parameter of the TMQUEUE server, if the call is not in transaction mode.
The TMQUEUE server can handle a number of waiting tpdequeue() requests at the same time, as long as action resources are available to handle the request. If there are not enough action resources configured for the queue space, tpdequeue() fails. If this happens on your system, increase the number of action resources for the queue space.
Error Handling When Using TMQFORWARD Services
In considering how best to handle errors when dequeuing it is helpful to differentiate between two types of errors:
By default, if a message is dequeued within a transaction and the transaction is rolled back, then (if the retry parameter is greater than 0) the message ends up back on the queue and can be dequeued and executed again. It may be desirable to delay for a short period before retrying to dequeue and execute the message, allowing the transient problem to clear (for example, allowing for locks in a database to be released by another transaction). Normally, a limit on the number of retries is also useful to ensure that an application flaw doesn't cause significant waste of resources. When a queue is configured by the administrator, both a retry count and a delay period (in seconds) can be specified. A retry count of 0 implies that no retries are done. After the retry count is reached, the message is moved to an error queue that is configured by the administrator for the queue space. If the error queue is not configured, then messages that have reached the retry count are simply deleted. Messages on the error queue must be handled by the administrator who must work out a way of notifying the originator that meets the requirements of the application. The message handling method chosen should be mostly transparent to the originating program that put the message on the queue. There is a virtual guarantee that once a message is successfully enqueued it will be processed according to the parameters of tpenqueue() and the attributes of the queue. Notification that a message has been moved to the error queue should be a rare occurrence in a system that has properly tuned its queue parameters.
A failure queue (normally, different from the queue space error queue) may be associated with each queued message. This queue is specified on the enqueuing call as the place to put any failure messages. The failure message for a particular request can be identified by an application-generated correlation identifier that is associated with the message when it is enqueued.
The default behavior of retrying until success (or a predefined limit) is quite appropriate when the failure is caused by a transient problem that is later resolved, allowing the message to be handled appropriately.
There are cases where the problem is not transient. For example, the queued message may request operating on an account that does not exist (and the application is such that it won't come into existence within a reasonable time period if at all). In this case, it is desirable not to waste any resources by trying again. If the application programmer or administrator determines that failures for a particular operation are never transient, then it is simply a matter of setting the retry count to zero, although this will require a mechanism to constantly clear the queue space error queue of these messages (for example, a background client that reads the queue periodically). More likely, it is the case that some problems will be transient (for example, database lock contention) and some problems will be permanent (for example, the account doesn't exist) for the same service.
In the case that the message is processed (dequeued and passed to the application via a tpcall()) by TMQFORWARD, there is no mechanism in the information returned by tpcall() to indicate whether a TPESVCFAIL error is caused by a transient or permanent problem.
As in the case where the application is handling the dequeuing, a simple solution is to return success for the service, that is, tpreturn with TPSUCCESS, even though the operation failed. This allows the transaction to be committed and the message removed from the queue. If reply messages are being used, the information in the buffer returned from the service can indicate that the operation failed and the message will be enqueued on the reply queue. The rcode argument of tpreturn can also be used to return application specific information.
In the case where the service fails and the transaction must be rolled back, it is not clear whether or not TMQFORWARD should execute a second transaction to remove the message from the queue without further processing. By default, TMQFORWARD will not delete a message for a service that fails. TMQFORWARD's transaction is rolled back and the message is restored to the queue. A command line option may be specified for TMQFORWARD that indicates that a message should be deleted from the queue if the service fails and a reply message is sent back with length greater than 0. The message is deleted in a second transaction. The queue must be configured with a delay time and retry count for this to work. If the message is associated with a failure queue, the reply data will be enqueued to the failure queue in the same transaction as the one in which the message is deleted from the queue.
Procedure for Dequeuing Replies from Services Invoked Through TMQFORWARD
If your application expects to receive replies to queued messages, here is a procedure you may want to follow.
TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
Fill in the values for corrid, replyqueue and failurequeue before issuing the call. On return from the call, save corrid.
TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
TPQGETCORRID
Use the saved correlation identifier to populate corrid before issuing the call. If the call to tpdequeue() fails and sets tperrno(5) to TPEDIAGNOSTIC, then further information is available in diagnostic. If you receive the error code QMENOMSG, it means that no message was available for dequeuing.
TPQCORRID TPQREPLYQ
TPQFAILUREQ TPQMSGID
TPQGETBYCORRID
Populate corrid with the correlation identifier. When the call returns, check len to see if data has been received and check urcode to see if the service has returned a user return code.
![]() |
![]() |
![]() |
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|