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

   Using the BEA Tuxedo System /Q Component

Dequeuing Messages

The syntax for TPDEQUEUE() is as follows.

01 TPQUEDEF-REC.
COPY TPQUEDEF.
01 TPTYPE-REC.
COPY TPTYPE.
01 DATA-REC.
COPY User Data.
01 TPSTATUS-REC.
COPY TPSTATUS.
CALL "TPDEQUEUE" USING TPQUEDEF-REC TPTYPE-REC DATA-REC TPSTATUS-REC.

When this call is issued it tells the system to dequeue a message from the QNAME in TPQUEDEF-REC queue, in the queue space named QSPACE-NAME in TPQUEDEF-REC. The message is placed in DATA-REC. LEN in TPTYPE-REC is set to the length of the data. If LEN is 0 on return from TPDEQUEUE(), the message had no data portion. By the use of settings in TPQUEDEF-REC the system is informed how the call to TPDEQUEUE() is to be handled.

TPDEQUEUE() Arguments

There are some important arguments to control the operation of TPDEQUEUE(3cbl). Let's look at some of them.

TPDEQUEUE(): the QSPACE-NAME in TPQUEDEF-REC Argument

QSPACE-NAME 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 QSPACE-NAME is the name of a service advertised by TMQUEUE. If no service aliases are defined, the name of the default service is the same as that of the server, TMQUEUE. In this case the configuration file may include the following.

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 path name of the device, and the queue space name. The QSPACE-NAME argument in a client program then looks like the following:

  01 TPQUEDEF-REC.
COPY TPQUEDEF.
01 TPTYPE-REC.
COPY TPTYPE.
01 TPSTATUS-REC.
COPY TPSTATUS.
01 USER-DATA-REC PIC X(100).
*
*
*
MOVE LOW-VALUES TO TPQUEDEF-REC.
MOVE "TMQUEUE" TO QSPACE-NAME IN TPQUEDEF-REC.
MOVE "REPLYQ" TO QNAME IN TPQUEDEF-REC.
SET TPTRAN IN TPQUEDEF-REC TO TRUE.
SET TPBLOCK IN TPQUEDEF-REC TO TRUE.
SET TPTIME IN TPQUEDEF-REC TO TRUE.
SET TPSIGRSTRT IN TPQUEDEF-REC TO TRUE.
MOVE LOW-VALUES TO TPTYPE-REC.
MOVE "STRING" TO REC-TYPE IN TPTYPE-REC.
MOVE LENGTH OF USER-DATA-REC TO LEN IN TPTYPE-REC.
CALL "TPDEQUEUE" USING
TPQUEDEF-REC
TPTYPE-REC
USER-DATA-REC
TPSTATUS-REC.

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

TPDEQUEUE(): the QNAME in TPQUEDEF-REC Argument

Queue names in a queue space must be agreed upon by the applications that will access the queue space. This requirement 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 contains the name of the queue from which to retrieve a message or reply.

TPDEQUEUE(): the DATA-REC and LEN in TPTYPE-REC Arguments

These arguments have a different flavor than they do on TPENQUEUE(). DATA-REC is where the system is to place the message being dequeued.

It is an error for LEN to be 0 on input. When TPDEQUEUE() returns, LEN contains 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 record 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. If the reply is larger than LEN, then DATA-REC will contain only as many bytes as will fit. The remainder are discarded and TPDEQUEUE() fails with TPTRUNCATE.

TPDEQUEUE(): the Settings in TPQUEDEF-REC

Settings in TPQUEDEF-REC are used to tell the BEA Tuxedo system how the TPDEQUEUE() call is handled; the following are valid settings:

TPNOTRAN

If the caller is in transaction mode, this setting specifies that the message is to be dequeued outside of the caller's transaction. Either TPNOTRAN or TPTRAN must be set.

TPTRAN

If the caller is in transaction mode, this setting specifies that the message is to be dequeued within the same transaction. Either TPNOTRAN or TPTRAN must be set.

TPNOBLOCK

The message is not dequeued if a blocking condition exists. If TPNOBLOCK is set and a blocking condition exists such as the internal buffers into which the message is transferred are full, the call fails and tperrno(5) is set to TPEBLOCK. If TPNOBLOCK is set and a blocking condition exists because the target queue is opened exclusively by another application, the call fails, tperrno() is set to TPEDIAGNOSTIC, and the diagnostic field of the TPQCTL structure is set to QMESHARE. In the latter case, the other application, which is based on a BEA product other than the BEA Tuxedo system, opened the queue for exclusive read and/or write using the Queuing Services API (QSAPI). Either TPNOBLOCK or TPBLOCK must be set.

TPBLOCK

When TPBLOCK is set and a blocking condition exists, the caller blocks until the condition subsides or a timeout occurs (either transaction or blocking timeout). This blocking condition does not include blocking on the queue itself if the TPQWAIT setting is specified. Either TPNOBLOCK or TPBLOCK must be set.

TPNOTIME

Setting this value asks that the call be immune to blocking timeouts; transaction timeouts may still occur. Either TPNOTIME or TPTIME must be set.

TPTIME

Setting this value asks that the call receive blocking timeouts. Either TPNOTIME or TPTIME must be set.

TPNOCHANGE

If this value is set, the record type of DATA-REC is not allowed to change. That is, the type and sub-type of the received record must match the type and subtype of the record DATA-REC. Either TPNOCHANGE or TPCHANGE must be set.

TPCHANGE

By default, if a record is received that differs in type from the record DATA-REC, DATA-REC's record type changes to the received record's type so long as the receiver recognizes the incoming record type. That is, the type and sub-type of the received record must match the type and sub-type of the record DATA-REC. Either TPNOCHANGE or TPCHANGE must be set.

TPSIGRSTRT

Setting this value says that any underlying system calls that are interrupted by a signal should be reissued. Either TPSIGRSTRT or TPNOSIGRSTRT must be set.

TPNOSIGRSTRT

If this value is set and a signal is received, the call fails and sets TP-STATUS to TPEGOTSIG. Either TPSIGRSTRT or TPNOSIGRSTRT must be set.

TPQUEDEF-REC Structure

The first argument to TPDEQUEUE() is the structure TPQUEDEF-REC. The TPQUEDEF-REC 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() uses settings to mark members the application wants the system to fill in. As described earlier, the structure is also used by TPENQUEUE(); some of the members only apply to that function. The entire structure is shown in The TPQUEDEF-REC Structure.

As input to TPDEQUEUE(), the following elements may be set in the TPQUEDEF structure.

05 MSGID                PIC X(32).
05 CORRID PIC X(32).

The following is a list of valid settings in TPQUEDEF-REC that control input for TPDEQUEUE().

TPQGETNEXT

Setting this value requests that the next message on the queue be dequeued, using the default queue order. One of the following must be set: TPQGETNEXT, TPQGETBYMSGID, or TPQGETBYCORRID.

TPQGETBYMSGID

Setting this value requests that the message identified by MSGID be dequeued. The message identifier is returned by a prior call to TPENQUEUE(). Note that the message identifier is not valid if the message has moved from one queue to another. Note also that the entire 32 bytes of the message identifier value are significant, so the value identified by MSGID must be completely initialized (for example, padded with spaces).

One of the following must be set: TPQGETNEXT, TPQGETBYMSGID, or TPQGETBYCORRID.

TPQGETBYCORRID

Setting this value requests that the message identified by CORRID be dequeued. The correlation identifier is specified by the application when enqueuing the message with TPENQUEUE(). Note that the entire 32 bytes of the correlation identifier value are significant, so the value identified by CORRID must be completely initialized (for example, padded with spaces).

One of the following must be set: TPQGETNEXT, TPQGETBYMSGID, or TPQGETBYCORRID.

TPQWAIT

Setting this value indicates that an error should not be returned if the queue is empty. Instead, the process should wait until a message is available. Set TPQNOWAIT to not wait until a message is available. If TPQWAIT is set in conjunction with TPQGETBYMSGID or TPQGETBYCORRID, it indicates that an error should not be returned if no message with the specified message identifier or correlation identifier is present in the queue. Instead, the process should wait until a message meeting the criteria is available. The process is still subject to the caller's transaction timeout, or, when not in transaction mode, the process is still subject to the timeout specified on the TMQUEUE process by the -t option.

If a message matching the desired criteria is not immediately available and the configured action resources are exhausted, TPDEQUEUE fails, TP-STATUS is set to TPEDIAGNOSTIC, and DIAGNOSTIC is set to QMESYSTEM.

Note that each TPDEQUEUE() request specifying the TPQWAIT control parameter requires that a queue manager (TMQUEUE) action object be available if a message satisfying the condition is not immediately available. If one is not available, the TPDEQUEUE() request fails. The number of available queue manager actions are specified when a queue space is created or modified. When a waiting dequeue request completes, the associated action object associated is made available for another request.

TPQPEEK

If TPQPEEK is set, the specified message is read but not removed from the queue. The TPNOTRAN flag must be set. It is not possible to read messages enqueued or dequeued within a transaction before the transaction completes.

When a thread is non-destructively dequeuing a message using TPQPEEK, the message may not be seen by other non-blocking dequeuers for the brief time the system is processing the non-destructive dequeue request. This includes dequeuers using specific selection criteria (such as message identifier and correlation identifier) that are looking for the message currently being non-destructively dequeued.

On output from TPDEQUEUE(), the following elements may be set in TPQUEDEF-REC:

05 PRIORITY     PIC S9(9) COMP-5. 
05 MSGID PIC X(32).
05 CORRID PIC X(32).
05 TPQUEQOS-DELIVERY-FLAG PIC S9(9) COMP-5.
05 TPQUEQOS-REPLY-FLAG PIC S9(9) COMP-5.
05 REPLYQUEUE PIC X(15).
05 FAILUREQUEUE PIC X(15).
05 DIAGNOSTIC PIC S9(9) COMP-5.
05 CLIENTID OCCURS 4 TIMES PIC S9(9) COMP-5
05 APPL-RETURN-CODE PIC S9(9) COMP-5.
05 APPKEY PIC S9(9) COMP-5.

The following is a list of valid settings in TPQUEDEF-REC controlling output information from TPDEQUEUE(). For any of these settings, if the setting is true when TPDEQUEUE() is called, the associated element in the record is populated with the value provided when the message was queued, and the setting remains true. If the value is not available (that is, no value was provided when the message was queued) or the setting is not true when TPDEQUEUE() is called, TPDEQUEUE() completes with the setting not true.

TPQPRIORITY

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with an explicit priority, then the priority is stored in PRIORITY. The priority is in the range 1 to 100, inclusive, and the higher the number, the higher the priority (that is, a message with a higher number is dequeued before a message with a lower number). If TPQNOPRIORITY is set, the priority is not available.

Note that if no priority was explicitly specified when the message was queued, the priority for the message is 50.

TPQMSGID

If this value is set and the call to TPDEQUEUE() is successful, the message identifier is stored in MSGID. The entire 32 bytes of the message identifier value are significant. If TPQNOMSGID is set, the message identifier is not available.

TPQCORRID

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with a correlation identifier, then the correlation identifier is stored in CORRID. The entire 32 bytes of the correlation identifier value are significant. Any BEA Tuxedo /Q provided reply to a message has the correlation identifier of the original message. If TPQNOCORRID is set, the correlation identifier is not available.

TPQDELIVERYQOS

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with a delivery quality of service, then the flag-TPQQOSDELIVERYDEFAULTPERSIST, TPQQOSDELIVERYPERSISTENT, or TPQQOSDELIVERYNONPERSISTENT-specified by TPQUEQOS-DELIVERY-FLAG indicates the delivery quality of service. If TPQNODELIVERYQOS is set, the delivery quality of service is not available.

Note that if no delivery quality of service was explicitly specified when the message was queued, the default delivery policy of the target queue dictates the delivery quality of service for the message.

TPQREPLYQOS

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with a reply quality of service, then the flag-TPQQOSREPLYDEFAULTPERSIST, TPQQOSREPLYPERSISTENT, or TPQQOSREPLYNONPERSISTENT-specified by TPQUEQOS-REPLY-FLAG indicates the reply quality of service. If TPQNOREPLYQOS is set, the reply quality of service is not available.

Note that if no reply quality of service was explicitly specified when the message was queued, the default delivery policy of the REPLYQUEUE queue dictates the delivery quality of service for any reply. The default delivery policy is determined when the reply to a message is enqueued. That is, if the default delivery policy of the reply queue is modified between the time that the original message is enqueued and the reply to the message is enqueued, the policy used is the one in effect when the reply is finally enqueued.

TPQREPLYQ

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with a reply queue, then the name of the reply queue is stored in REPLYQUEUE. Any reply to the message should go to the named reply queue within the same queue space as the request message. If TPQNOREPLYQ is set, the reply queue is not available.

TPQFAILUREQ

If this value is set, the call to TPDEQUEUE() is successful, and the message was queued with a failure queue, then the name of the failure queue is stored in FAILUREQUEUE. Any failure message should go to the named failure queue within the same queue space as the request message. If TPQNOFAILUREQ is set, the failure queue is not available.

The remaining settings in TPQUEDEF-REC are set to the following values when TPDEQUEUE() is called: TPQNOTOP, TPQNOBEFOREMSGID, TPQNOTIME_ABS, TPQNOTIME_REL, TPQNOEXPTIME_ABS, TPQNOEXPTIME_REL, and TPQNOEXPTIME_NONE.

If the call to TPDEQUEUE() fails and TP-STATUS is set to TPEDIAGNOSTIC, a value indicating the reason for failure is returned in DIAGNOSTIC. The valid settings for DIAGNOSTIC include those for TPENQUEUE() described in TPQUEDEF-REC Structure (except for QMENOSPACE and QMERELEASE) and the following additional codes.

[QMENOMSG]

No message was available for dequeuing. Note that it is possible that the message exists on the queue and another application process has read the message from the queue. In this case, the message may be put back on the queue if that other process rolls back the transaction.

[QMEINUSE]

When dequeuing a message by message identifier or correlation identifier, the specified message is in use by another transaction. Other wise all messages currently on the queue are in use by other transactions. This diagnostic is not returned by a queue manager from BEA Tuxedo Release 7.1 or later.

Using TPQWAIT

When TPDEQUEUE() is called with flags 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 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 APPL-CODE in the TPSVCRET-REC 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 is 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.

  1. As a preliminary step, the queue space must include a reply queue and a failure queue. The application must also agree on the content of the correlation identifier. The service should be coded to return TPSUCCESS on a logical failure and return an explanatory code in the APPL-CODE in the TPSVCRET-REC argument of TPRETURN.

  2. When you call TPENQUEUE() to put the message on the queue, set the following:

    TPQCORRID      TPQREPLYQ
    TPQFAILUREQ TPQMSGID

    (Fill in the values for CORRID, REPLYQUEUE and FAILUREQUEUE before issuing the call. On return from the call, save CORRID.)

  3. When you call TPDEQUEUE() to check for a reply, specify the reply queue in QNAME and set the following:

    TPQCORRID       TPQREPLYQ
    TPQFAILUREQ TPQMSGID
    TPQGETBYCORRID

    (Use the saved correlation identifier to populate CORRID before issuing the call. If the call to TPDEQUEUE() fails and sets TP-STATUS to TPEDIAGNOSTIC, then further information is available in the DIAGNOSTIC settings. If you receive the error code QMENOMSG, it means that no message was available for dequeuing.)

  4. Set up another call to TPDEQUEUE(). This time have QNAME point to the name of the failure queue and set the following:

    TPQCORRID       TPQREPLYQ
    TPQFAILUREQ TPQMSGID
    TPQGETBYCORRID

    Populate TPQCORRID with the correlation identifier. When the call returns, check LEN to see if data has been received and check APPL-RETURN-CODE to see if the service has returned a user return code.