Hello everyone and welcome to this post about Data Queues objects on IBM i. This will be the first of a series of three posts about data queues. In this first post I will talk about how to work with data queues in CL Programs. In the second post I will use an ILE RPG program and finally in the third post I will use IBM i Services.
Data queues are one of the most efficient and elegant interprocess communication (IPC) mechanisms on IBM i. They provide a fast, flexible way to exchange messages between jobs or between different parts of the same application. While most developers use RPG or COBOL to interact with data queues, Control Language (CL) also provides native support to work with them—often overlooked but highly effective for system utilities, job orchestration, and messaging workflows.
In this post, we’ll take a deep dive into how to use data queues from CL programs. We’ll cover queue creation, sending and receiving messages, and best practices when integrating data queues into CL-based architectures.
A data queue is an object of type *DTAQ
that allows programs to enqueue and dequeue data records. Think of it as a high-performance FIFO (first-in, first-out) buffer managed by the system. Each entry in the queue can have a fixed or variable length, and can be processed asynchronously.
Data queues are especially valuable in:
According to how entries can be retrieved data queues can be FIFO (First In First Out), LIFO (Last In First Out) or KEYED.
The type of the data queue can be *STD (standard), *DDM (remote) or *DSP (to use with a display file).
In this section I will show which data queue operations can be performed with commands and APIs or IBM i Services. In this post I will only talk about commands and APIs. Stay tuned because part three of the series will be all about IBM i services.
As I’ve said before a data queue is an object of type *DTAQ
so it can be created and deleted and this can only be done with commands and those, along with WRKDTAQ, are the only commands available for working with data queues.. All other operations are performed via APIs or IBM i services.
There are several APIs to work with data queues so you can perform operations other than create or delete a data queue. An API is a program that performs an operation and that has input and output parameters. IBM has a Web page called API Finder where you can search IBM i APIs by name, category and so on. You can visit the Web page clicking here. This Web page is a must if you are going to work with APIs. You will see which parameters the API has, which of them are input or output, the type and any other consideration to use the API.
I will list all the data queues APIs and a brief description of what each one does and I will explain some of them deeper in the examples.
It is now time to go through a complete example using Control Language.
Management ask for a program that prints orders once they are completed. To accomplish this task IT department is going to develop two programs. The first program will send the order number to a data queue once it is completed and continues with other things or processing more orders. The second program, asynchronously, will read the order number from the data queue and call a program passing the order number as a parameter and print the order. This second program will run in batch and wait forever for an order to arrive. To end this second program the first one must send a “flag” that causes the second program to finish.
To keep things simple in the example, the first program will have a screen where you can type an order number and the flag to end the second program.
First of all a data queue is needed to store the order numbers in the same sequence they have been processed. The command to create this data queue is:
CRTDTAQ DTAQ(*CURLIB/ORDERNUM) TYPE(*STD) MAXLEN(5) SEQ(*FIFO) SIZE(*MAX16MB 1) AUTORCL(*YES) TEXT('Order numbers to print')
This command will create the ORDERNUM data queue in the current library. The type is standard which means is local. The maximum length of an entry is five characters. The entries are retrieved in the same order as they have been sent. The maximum size of the data queue will be 16 MB and it will have 1 initial entry so its initial size will be 5 bytes. Auto reclaim is set to *YES so the storage allocated for the data queue is automatically reclaimed when the data queue is empty and it will have the initial number of entries again, one in this case.
This simple screen file is used to send order numbers to the data queue. You can see the code below. I am not going to explain the entire screen file I will just list all the components that will be used in the CL program.
SNDDTAQD:
A CA03(03)
A CA06(06)
A R SNDORDNUM
A 1 2SYSNAME
A 1 33'Send Order Number'
A DSPATR(UL)
A COLOR(RED)
A 1 70DATE(*YY)
A EDTCDE(Y)
A PGMNAM 10 O 2 2
A 2 72TIME
A 7 6'Order number. . . :'
A ORDNUM 5 I 7 26
A MESSAGE 66 O 12 9DSPATR(HI)
A 23 2'F3=Exit'
A COLOR(BLU)
A 23 11'F6=Send Flag and Exit'
A COLOR(BLU)
Things to consider:
Function Keys
Record Formats
Variables
Program SNDDTAQC will use the screen SNDDTAQD to get the order number to send to the data queue. There will be another program called RCVDTAQC that will be used to retrieve the order number from the data queue and process it.
RCVDTAQC will wait for an order number to arrive in the data queue. If the user presses function key F3, SNDDTAQC will terminate, but RCVDTAQC will continue waiting for an order number because the termination flag is not sent with F3. If the user presses function key F6, SNDDTAQC will also terminate; however, before doing so, it will send the character string END
to RCVDTAQC, which will interpret it as a termination flag and end its execution
SNDDTAQC:
PGM
DCLF FILE(SNDDTAQD)
DCL VAR(&QNAME) TYPE(*CHAR) LEN(10) VALUE(ANTDTAQ)
DCL VAR(&QLIB) TYPE(*CHAR) LEN(10) VALUE(ANTDTAQLIB)
DCL VAR(&QDATALEN) TYPE(*DEC) LEN(5 0) VALUE(5)
DCL VAR(&QDATA) TYPE(*CHAR) LEN(5)
SNDRCVF RCDFMT(SNDORDNUM)
DOWHILE (*NOT &IN03)
IF &IN06 (DO)
CHGVAR VAR(&QDATA) VALUE('END')
CALL QSNDDTAQ (&QNAME &QLIB &QDATALEN &QDATA)
RETURN
ENDDO
CHGVAR VAR(&QDATA) VALUE(&ORDNUM)
CALL QSNDDTAQ (&QNAME &QLIB &QDATALEN &QDATA)
CHGVAR VAR(&MESSAGE) VALUE('Order number' *BCAT &ORDNUM *BCAT 'processed.')
SNDRCVF RCDFMT(SNDORDNUM)
ENDDO
ENDPGM
Explanation:
Line 1: Program starts
Line 2: Declaration of the screen file SNDDTAQD.
Line 3: Name of the data queue. In this case ANTDTAQ.
Line 4: Library of the data queue. In this case ANTDTAQLIB.
Line 5: Length of the data to send to the data queue. Must be the same as the value specified in the MAXLEN parameter of the CRTDTAQ command.
Lines 6: Variable to hold the data to send to the data queue.
Note: These four variables correspond to the first four parameters of the QSNDDTAQ API which are mandatory.
Line 7: The screen is written and waiting for and order number or a function key.
Line 8: While F3 is not pressed…
Line 9 – 13: If F6 is pressed ‘END’ character string is assigned to &QDATA variable and sent to the data queue. Then SNDDTAQC program ends.
Line 14: The value of &ORDNUM from the screen file is assigned to &QDATA.
Line 15: The value of &QDATA is sent to the data queue.
Lines 16: A message with the order number processed is assigned to &MESSAGE screen field.
Line 17: The screen is written so the message can be viewed and it will wait for another order number or a function key.
Line 18: DOWHILE loop ends.
Line 19: Program ends.
Program RCVDTAQC will run in batch mode, waiting indefinitely for an order to arrive. Once an order number is placed in the data queue, it will retrieve and process it, sending a message to the user running the program to confirm that the order has been processed. If the order number is the character string END
—the termination flag—the program will end.
RCVDTAQC:
PGM
DCL VAR(&QNAME) TYPE(*CHAR) LEN(10) VALUE(ORDERNUM)
DCL VAR(&QLIB) TYPE(*CHAR) LEN(10) VALUE(ASALCEDO1)
DCL VAR(&QDATALEN) TYPE(*DEC) LEN(5 0)
DCL VAR(&QDATA) TYPE(*CHAR) LEN(5)
DCL VAR(&WAIT) TYPE(*DEC) LEN(5 0) VALUE(-1)
DCL VAR(&USER) TYPE(*CHAR) LEN(10)
RTVJOBA USER(&USER)
DOWHILE (1=1)
CALL QRCVDTAQ (&QNAME &QLIB &QDATALEN &QDATA &WAIT)
IF (&QDATA = 'END') (DO)
SNDMSG MSG('Program RCVDTAQC ended. END flag received.') +
TOUSR(&USER)
RETURN
ENDDO
SNDUSRMSG MSG('Order number' *BCAT &QDATA *BCAT 'has been printed.') +
MSGTYPE(*INFO) TOUSR(&USER)
ENDDO
ENDPGM
Explanation:
Line 1: Program starts
Line 2: Name of the data queue. In this case ANTDTAQ.
Line 3: Library of the data queue. In this case ANTDTAQLIB.
Lines 4: Length of the data received from the data queue. It is an output parameter.
Line 5: Variable to hold the data to received from the data queue.
Line 6: Variable to specify the time that the API will be waiting for a data to arrive. The time is in seconds and if you put a negative number the API will be waiting indefinitely.
Line 7: Variable to hold the user that runs the program that will be used to send the messages.
Line 8: Command to retrieve Job attributes, in this case the user that runs the program.
Line 9: Infinite loop.
Line 10: The API will wait for a data to arrive or if any data is in the data queue it will extract it and store it in &DATA. &DATALEN will store the length of the data read.
Line 11 – 15: If &QATA is equal to END, the end flag, the program will send a message indicating that is ended and then it will end.
Line 16: If &QDATA contains an order number, it will send a message indicating that the order has been printed (normally, this is where the call to the RPG program that prints the order would be coded).
Line 18: Infinite loop ends.
Line 19: Program ends.
It’s time to test the application. First, I will run SNDDTAQC, enter three order numbers, and then exit the program with F3, which means the end flag will not be sent.
Next, I will run RCVDTAQC in batch mode. The three order numbers will be processed from the data queue, and the program will remain active in batch since the end flag has not been received.
Finally, I will run SNDDTAQC again, this time sending two additional order numbers. However, I will exit with F6, which triggers the sending of the end flag. As a result, RCVDTAQC will process the new order numbers and then terminate once the end flag is detected.
So I run CALL SNDDATQC and I get a screen to enter the order numbers. I will enter numbers 11111, 22222 and 33333. Every time I enter an order number I get a confirmation message in the screen. I end the program with F3 so no confirmation flag is sent.
Now I’m going to submit to batch the program RCVDTAQC.
At this stage, three order numbers are present in the data queue. When the program is executed, it will process these entries and issue a separate message for each order to the user executing the program.
Running DSPMSG command you can view those messages.
Program RCVDTAQ is still running in batch because the end flag has not been sent yet.
The final step in testing the application is to send two additional order numbers and then end the program with F6, which sends the end flag.
As a result, as shown in the image, new messages appear in the message queue displaying the additional order numbers, and the receipt of the end flag indicates that program RCVDTAQC has terminated.
I hope you found this post useful. Stay tuned — part two, covering the use of Data Queues with ILE RPG, will be published shortly.