The following sections describe typical application examples and show how you can use service-controlled queues and create the associated program units.
Example 1: Communication between two services in an application
The diagram shows the evaluation of a background job with the help of a temporary queue. The main service “Customer” in a call center searches for the required data by means of a background job and reads the results from a temporary queue or waits for the corresponding message if it is not yet available at the time of the DGET.
UTM application "Call Center"
Figure: Communication between two independent services with the help of a temporary queue
A temporary queue is created by means of QCRE NN. The name of the queue is returned in KCRQN. The background job “Search” is then created with FPUT, and the transaction is terminated immediately with PEND SP. The name of the queue is passed with FPUT.
The “Search” service reads the message with the name of the temporary queue and searches for the required data. Meanwhile, the main service, “Customer”, queries the result of background processing with DGET. Since the result is not yet available in this case, the current program unit of the main service terminates; openUTM waits for the arrival of the message. The function is implemented in such a way that there is no program unit active and no process linked for the main service in the wait time.
When the “Search” auxiliary service has obtained the required data, it creates a message for the temporary queue and terminates. The DPUT job is thus executed.
The main service is continued when the message arrives. It reads the result from the temporary queue and sends it to the client. It then deletes the temporary queue and terminates (the deletion does not take effect until the successful completion of the transaction).
To control the sequences executed in the program units, an auxiliary field called WaitForMsg
must be created in the KB communication area so that it can be accessed by all the service’s program units. If the return code 08Z is obtained repeatedly, superfluous waiting is avoided by means of a RSET call.
... QCRE NN FPUT with KCRN=search kb.WaitForMsg = 0 PEND SP with TAC2
... DGET queue if ( KCRCCC = "08Z" ) then if kb.WaitForMsg = 0 then kb.WaitForMsg = 1 PEND PA,<tac2> else RSET else processing QREL queue ... PEND FI
Example 2: “Pseudo dialogs” with remote transport system applications
Another application example is obtained by carrying out a simple modification of
example 1: a dialog or asynchronous service wants read access to a database in another application.
A communication partner of the type APPLI or SOCKET-USP replaces the auxiliary service of example 1. The FPUT call in the main service addresses the LTERM name of the remote application instead of an asynchronous TAC; apart from this change, the calls and processes involved in the two services remain unchanged. If the remote application is a UTM application, the TAC to be called in the remote application must be at the beginning of the FPUT message. The remote application must begin its reply message with the name of the queue in which the main service expects the reply.
openUTM determines the destination of the messages from the name of the queue alone. The name of the temporary queue must therefore not be the same as a TAC or LTERM name of the local application. Name clashes are avoided because the name of the temporary queue is assigned by openUTM (QCRE NN), and neither TAC nor LTERM names begin with a digit.
Example 3: Communication with more than one service
If a service wants to communicate with more than one auxiliary service simultaneously, what happens is similar to what happens in communication with only one auxiliary service. When the replies are read, however, it is important that all the replies are read; it may therefore be necessary to wait for all of these. You must ensure that each message is waited for no more than once.
To control the processes in the program units, auxiliary fields are created in the KB communication area in this example so that all the program units of the service can access them. As it is possible that not all the replies can be read in a program unit run, the browse function is used to implement a wait loop. The replies are not processed until the last message has arrived.
Figure: Communication of a main service with two auxiliary services by means of temporary queues
Auxiliary fields must be used for this communication, and loops must be programmed. The various steps are explained in the following table:
TAC1 program | Explanation |
---|---|
INIT | |
QCRE NN | Create temporary queue. The name of the queue is returned in KCRQN. |
FPUT KCRN=HTAC1 | Create messages for the auxiliary services. The name of the queue is passed in the message. |
kb.NrMsgs = 2 | Initialize fields in the KB program area. These fields control the sequence of execution in the follow-up programs. |
PEND SP KCRN=TAC2 | Terminate transaction. The asynchronous jobs are started. |
TAC2 program | Explanation |
INIT | |
Timeout = 0 | Initialize timeout field. |
for( kb.i < kb.NrMsgs AND Timeout = 0) DGET BF with length 0 | In a loop an attempt is made using DGET BF with waiting to wait for all replies without reading or deleting data; in other words, all messages are retained. Make sure that each message is not waited for more than once. |
if ( KCRCCC = "08Z" ) then Timeout = 1 PEND PA KCRN=TAC2 else kb.i = kb.i +1 kb.WaitForMsg = 0 | There must be a wait. The program run is then terminated with PEND PA; the current TAC is specified as the follow-up TAC. The counter is incremented when a reply arrives. The creation time and DPUT ID of the message are buffered |
if Timeout = 0 DGET FT DGET NT processing | All replies are read in full in two nested loops. Processing of the replies then begins. The result is sent to the client using MPUT. |
else RSET MPUT | At timeout, superfluous waiting is avoided by means of an RSET. |
QREL “queue” | Before the service terminates, the temporary queue is deleted again. |
Example 4: Sending asynchronous messages to UPIC clients
Asynchronous messages must not be directed at a LTERM partner of a UPIC client; with the help of service-controlled queues, however, asynchronous events or messages can also be delivered to a UPIC client. To do this, you either direct the asynchronous messages to the USER queue of the UPIC client or you generate a TAC queue additionally for each UPIC client. The UPIC client starts another dialog service in parallel with its normal dialog services. This dialog service assumes the task of waiting at this queue until a message arrives, reading it out and forwarding it to the UPIC client.
The following diagram shows how this is implemented using USER queues:
Figure: Sending of asynchronous messages to UPIC clients using USER queues
Example 5: Serialization of program units
If a program (segment) that is executed in both dialog and asynchronous services is to be serialized, you can use a TAC queue for serialization. TAC queues have an advantage over GSSBs (global secondary storage areas) in that waiting takes place outside the program unit context and the process is thus free for other things.
In the following example, a segment of a program unit that can run both in the dialog and asynchronously is secured against parallel processing by means of a TAC queue.
TAC tacqueue,TYPE=Q
Figure: Serialization of program units using TAC queues
A message is sent to the TAC queue by means of DPUT for the next service to execute the critical program segment. Only on successful completion of the transaction does the DPUT call take effect.
The mechanism described here must be initialized so that the critical program unit segment can be executed. This can be implemented at application startup, for example, by means of an MSGTAC program that responds to a start message (K050, K051) and creates a message for the TAC queue.
Example 6: Output of other TLS blocks in the dialog service
Accesses to TLS blocks of a different data station are only permitted in asynchronous services. The output of data from other TLS blocks from a dialog service to the data station is possible if example 1 is slightly modified:
The dialog service passes to the auxiliary service the name of the TLS block and of the LTERM. The auxiliary service reads the required data with a GTDA call and sends it to the temporary queue.
The dialog service reads the TLS data from the temporary queue and outputs it at the data station.
Example 7: Service-controlled queues as global storage areas
Only serial access to application-global storage areas (GSSBs, see "Global secondary storage area (GSSB)") is possible, i.e. areas of this kind are locked during read/write. If, instead of a GSSB, a temporary queue is used with the "browse" function, several services can then access the storage area in parallel.
Also, fewer restrictions apply to temporary queues than to GSSBs. The storage area of a temporary queue is not limited (GSSB: 32,767 bytes) and more queues than GSSBs are permitted (500,000 as opposed to 32,767).
Using a temporary queue it is possible, for example, to implement an online auction:
DPUT QT/QE puts the descriptions of the objects into a temporary queue one after the other. A fixed name is given to the queue. Later additions can be made to the queue.
DGET BF/BN allows those interested to read these descriptions; this can also be done in parallel by several services.
DGET PF/PN processes a description and therefore removes it from the queue, e.g. once an object has been sold in the auction.
The temporary queue is deleted with QREL at the end of the auction.
The number of messages in a temporary queue can be limited at generation time (KDCDEF QUEUE statement, QLEV operand). If only the latest messages are of interest, wrap mode can be selected (QUEUE statement, QMODE=WRAP-AROUND operand). Once the maximum number of messages has been reached, each new message causes the oldest message to be deleted.