04
Mon, Nov
5 New Articles

Line Up for Data Queues

General
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Simplify your interactive applications by using data queues

Brief: Data queues can be used to pass asynchronous data between programs. They are ideal for passing data to a background task. You'll learn how to define and program data queues, recognize their strengths and pitfalls and use them for slick interactive sorts.

You may have heard that data queues are the fastest way to get data between programs. But, why and how would you use them as you design a system? In this article, you will see several examples of data queues in action. These examples will allow you to see how they work and will give you ideas about how you can use data queues to design more efficient applications.

Data queues are similar to other queues (i.e., output, job, message queues) with which most of you have probably had experience. A queue simply accepts items to be processed whether or not the processing will occur immediately or later. Data queues accept data that can be processed any way that you care to process it and at any time.

What Are Data Queues?

Data queues act as repositories of data. Think of a data queue as a tank of gasoline that serves several pumps at a gas station. The tanker truck from the oil company periodically fills the tank, and customers draw from the tank by pumping the gasoline into their cars. All pumps are serviced with equal priority-the gasoline is used whenever a particular user needs it.

Similarly, programs can send data to a data queue and let it accumulate there. Other programs can receive data from the data queue at any time-perhaps more than one program at the same time, until the data in the data queue is exhausted. Once a data record is received from a data queue, the data queue "forgets" that record.

Data queues are objects of type *DTAQ that can contain data. A data queue can be manipulated by many programs at the same time. Like data areas (*DTAARA), data queues do not allow DDS to define fields; therefore, the data contained in data queues is flat. However, data queues are more like files in that they can contain many records.

Data Queue Attributes

Data queues come in three flavors: *FIFO, *LIFO and *KEYED. *FIFO (first-in, first-out) means that records are taken out of the data queue in the same order in which they were placed, while *LIFO (last-in, first-out) is the reverse order. V2R1.0 introduced *KEYED, which lets you receive records sequentially or randomly by key.

Besides type, data queues have a record length that you must specify when you create the data queue. If the data queue is *KEYED, you must also specify the length of the key.

Creating and Deleting Data Queues

As you might expect, you create and delete data queues with the Create Data Queue (CRTDTAQ) and the Delete Data Queue (DLTDTAQ) commands. Surprisingly, there's no Change Data Queue (CHGDTAQ) or Display Data Queue (DSPDTAQ), although there's a Work with Data Queues (WRKDTAQ) command.

The CRTDTAQ command has the following parameters:

Data queue (DTAQ), to supply the qualified name of the data queue you want to create.

Maximum entry length (MAXLEN), to define the record length. It can be any number between 1 and 64512, and has no default value.

Sequence (SEQ), which lets you choose between *FIFO, *LIFO and *KEYED. The default value is *FIFO.

Key length (KEYLEN), valid only for *KEYED data queues, specifies the length of the key field (maximum length is 256). This key field is stored as a separate entity and is not included as part of the record space allocation, unless you specifically make it part of the record.

Text (TEXT), which allows you to enter a description of the data queue.

Force to auxiliary storage (FORCE), which lets you force each record into DASD as soon as it is sent to the data queue (*YES) or remain in memory (*NO). The default is *NO. You may want to set this value to *YES if you can't afford to lose data during a power failure.

Include sender ID (SENDERID), which lets you splice an identification to each record in the data queue. This identification contains the complete qualified job name and the user profile name of the sender. This sender ID is not part of the record, so you don't have to allocate space for it in MAXLEN.

Public authority (AUT), to indicate what authority to the data queue the public should be given. The default is *LIBCRTAUT.

Sending, Receiving and Clearing

You must use the QSNDDTAQ Application Program Interface (API) to send data to a data queue. QSNDDTAQ expects either four or six parameters: four if the data queue is *FIFO or *LIFO, six if *KEYED. 1 shows an example in RPG, using six parameters. If your data queue is not *KEYED, drop the last two parameters.

You must use the QSNDDTAQ Application Program Interface (API) to send data to a data queue. QSNDDTAQ expects either four or six parameters: four if the data queue is *FIFO or *LIFO, six if *KEYED. Figure 1 shows an example in RPG, using six parameters. If your data queue is not *KEYED, drop the last two parameters.

Similarly, you can use an API named QRCVDTAQ to receive data from a data queue. QRCVDTAQ expects either five or 10 parameters. If your data queue is *KEYED or if you are using sender IDs (see following section), you must supply 10 parameters. In all other cases, supply the first five parameters only. 2 provides an RPG example using 10 parameters.

Similarly, you can use an API named QRCVDTAQ to receive data from a data queue. QRCVDTAQ expects either five or 10 parameters. If your data queue is *KEYED or if you are using sender IDs (see following section), you must supply 10 parameters. In all other cases, supply the first five parameters only. Figure 2 provides an RPG example using 10 parameters.

To clear a data queue, you'll need to use another API, QCLRDTAQ. QCLRDTAQ only expects two parameters, both 10 characters long: the name of the data queue and the name of the library where it resides. See 3.

To clear a data queue, you'll need to use another API, QCLRDTAQ. QCLRDTAQ only expects two parameters, both 10 characters long: the name of the data queue and the name of the library where it resides. See Figure 3.

Receiving Sender IDs

When you use QRCVDTAQ to receive data from a data queue that includes sender IDs, you must receive the sender ID into a character field that is at least 44 characters long. The sender ID identifies the user and the job that sent a particular record to the data queue. You may want to use the sender ID if you want to track transactions by job or user.

The character field that receives the sender ID contains six subfields that I have been able to identify after doing some experimentation. Here they are:

 
 1-8:        Not used. 
 9-18:       Job name. 
 19-28:      Job user. 
 29-34:      Job number. 
 35-44:      User profile name. 
 Beyond 44:  Blank. 

Theory in Practice

Enough about theory. Now that I have presented the foundation, we can see how to put data queues to work. My background is in the manufacturing industry, so my first example is set in a manufacturing environment.

Imagine a busy manufacturing plant where trucks come and go all day long-some delivering raw materials into the Receiving department, others picking up final assemblies from the Shipping department. These receipts and shipments have to be reported to the computer as inventory transactions.

At the same time, Inventory Control may have six data entry clerks constantly engaged in entering inventory transactions of other types, such as production receipts, material movements, transfers, scraps, and so on. Yet more people in the Sales department can also report inventory transactions when they sell products to their customers.

The inventory transaction entry would have to update several files: inventory balances, inventory master, sales order, purchase order, shop order, work order, material allocations, requirements and even a transaction history file, which could have half a million records, with five or six logicals (with immediate access path maintenance) built on top.

It's a bleak scenario. The system would be so overburdened with file I/O that performance would suffer substantially. Here's a place where data queues can greatly improve performance. Simply speaking, we would have a batch job running all day long, receiving inventory transactions from a data queue and performing all file maintenance, including the addition of new transactions to the history file (4a illustrates this system's use of data queues). Since the file updates are handled by a separate batch job, the data entry people can run simplified, faster-responding versions of the interactive entry programs which validate entries and send the transactions to the data queue. This approach relieves the QINTER subsystem from performing heavy file I/O, a task that can be better achieved by QBATCH. Bottom line-the users are going to be happier with their response time and the programming is simplified.

It's a bleak scenario. The system would be so overburdened with file I/O that performance would suffer substantially. Here's a place where data queues can greatly improve performance. Simply speaking, we would have a batch job running all day long, receiving inventory transactions from a data queue and performing all file maintenance, including the addition of new transactions to the history file (Figure 4a illustrates this system's use of data queues). Since the file updates are handled by a separate batch job, the data entry people can run simplified, faster-responding versions of the interactive entry programs which validate entries and send the transactions to the data queue. This approach relieves the QINTER subsystem from performing heavy file I/O, a task that can be better achieved by QBATCH. Bottom line-the users are going to be happier with their response time and the programming is simplified.

Learning by Example

There's nothing like a good example to help you visualize a technique, so I'll present a simplified version of the above scenario. Let me begin this presentation by defining ITH, the Inventory Transaction History file (4b). I'm keeping the file layout simple for this example. In a real-life situation, you would want to add many more fields. The interactive portion consists of a display file (4c), a record layout for our data queue (4d) and an RPG program (4e). The batch portion consists of a CL program (5a) and an RPG program (5b). Enter the code and compile each piece following the instructions given at the bottom of each figure.

There's nothing like a good example to help you visualize a technique, so I'll present a simplified version of the above scenario. Let me begin this presentation by defining ITH, the Inventory Transaction History file (Figure 4b). I'm keeping the file layout simple for this example. In a real-life situation, you would want to add many more fields. The interactive portion consists of a display file (Figure 4c), a record layout for our data queue (Figure 4d) and an RPG program (Figure 4e). The batch portion consists of a CL program (Figure 5a) and an RPG program (Figure 5b). Enter the code and compile each piece following the instructions given at the bottom of each figure.

Starting the Batch Job

First, submit program INV002CL to batch with the following command:

SBMJOB CMD(CALL INV002CL)

INV002CL creates data queue INVTRNDQ as *FIFO, having a record length of 42. We're also requesting to include the identification of the sender. Then it overrides file ITH to FRCRATIO(1) and calls RPG program INV002RG, the file update program. The FRCRATIO(1) override forces the program to write each record one at a time instead of blocking them and delaying the actual physical update. This enables you to peek with DSPPFM and see the progress of INV002RG.

INV002RG adds records to ITH by entering an infinite loop. At the top of the loop it calls QRCVDTAQ to receive a transaction record from the data queue. It uses 10 parameters because we're using sender IDs in the data queue. Notice, in particular, that the inventory transaction is received into field DQDTA, which is a data structure externally defined by INV001DD (4d); this data structure provides a record layout for the data queue.

INV002RG adds records to ITH by entering an infinite loop. At the top of the loop it calls QRCVDTAQ to receive a transaction record from the data queue. It uses 10 parameters because we're using sender IDs in the data queue. Notice, in particular, that the inventory transaction is received into field DQDTA, which is a data structure externally defined by INV001DD (Figure 4d); this data structure provides a record layout for the data queue.

If the data queue is empty at the moment, DQ#LEN is set to zero. In this case, the program checks the system time; if it's past 9:00 p.m., it leaves the infinite loop and ends the program on its own accord. On the other hand, if it received a record from the data queue, the data contained in the queue fields are validated for accuracy and then moved into the ITH fields and we WRITE to the file. Then the process continues.

Starting the Interactive Job

To enter inventory transactions, you must CALL program INV001RG. In a real- life situation, you would use a command or issue the CALL command from a menu.

As you can see in 4e, program INV001RG is very simple. In a real-life scenario, you would want to include some validity checks for the user input. INV001RG uses an externally described data structure to provide a record layout to the data queue. INV001RG uses QSNDDTAQ to send the transaction data to the data queue, listing only four parameters since the data queue is not *KEYED.

As you can see in Figure 4e, program INV001RG is very simple. In a real-life scenario, you would want to include some validity checks for the user input. INV001RG uses an externally described data structure to provide a record layout to the data queue. INV001RG uses QSNDDTAQ to send the transaction data to the data queue, listing only four parameters since the data queue is not *KEYED.

Try it out. Sign on to two sessions. In session A, submit the batch job by submitting (CALL INV002CL) if you haven't done it already, then CALL INV001RG. Key in one transaction and press Enter (INV001RG performs no data validation so you can enter anything). Now go to session B and run the Display Physical File Member (DSPPFM) command on file ITH. Your transaction will already be there! Repeat the process; each time, DSPPFM will show the latest transaction in ITH.

To end this example, press F3 to end interactive program INV001RG. Batch program INV002CL will end at 9:00 p.m. automatically, but you can cancel it manually if you'd like: run WRK-SBMJOB, then select Option 4, press F4, and specify OPTION(*IMMED).

Reviewing the Process

How does it work? The interactive portion (program INV001RG) sends a transaction to the data queue but doesn't update any files. The batch program (which is running all day long) is continually attempting to receive transactions from the data queue. It keeps trying until a transaction arrives. When this happens, it updates the files (in our simplified example, that's ITH only).

The data queue has provided a vehicle to pass data from the interactive job to the batch job. Because the data queue can be accessed from any job (it's not in QTEMP), there can be any number of interactive jobs sending inventory transactions to the data queue; the batch job will process them all in the sequence they were entered (the data queue is *FIFO).

Example of Keyed Data Queues

Keyed data queues are slick. As you have seen, *FIFO data queues can be read forward; *LIFO data queues can be read backwards. *KEYED data queues can be read randomly by key or sequentially by key in any order.

You're already familiar with the concept thanks to your experience in languages like RPG: you can read a file sequentially by key if you declare the file as keyed (K in column 31 of the F-spec) and use SETLL and READ in your C- specs. Or you can read it randomly by key by using CHAIN instead of READ. Keyed data queues let you do the same thing. As an example of using a keyed data queue, I'll use an interactive program to sort records before presenting them on the screen.

Imagine having a database file that contains one record per employee in your office, containing the employee's first and last name, title and phone extension number. Now you want to be able to display the whole list in a subfile, but resequence the records on demand by any of the four fields mentioned. You want to be able to press a function key and have the records redisplayed in a different sequence.

You could have a physical file and three logicals, but then you would have four files in your interactive program, creating complicated code to read one file (and not the others) depending on the sequence requested by the user. Maintaining multiple logical files which are only used in a single, perhaps infrequently used, application would also add substantial system overhead. Another approach would be to end the program, run OPNQRYF, and restart the program when a new sequence is requested. This also complicates the program's logic to some extent.

Use a keyed data queue instead! Since keyed data queues let you receive records sequentially by key, they provide automatic sorting of all the records you send to them. It's like being able to sort a file inside your RPG program.

The Solution

File OFCEMP (6a) contains only four fields. In a real application, you may want to draw the data from your employee master file, which would have many more fields. This file is indexed by last name and first name, although this is not vital.

File OFCEMP (Figure 6a) contains only four fields. In a real application, you may want to draw the data from your employee master file, which would have many more fields. This file is indexed by last name and first name, although this is not vital.

CL program OFC001CL (6b) starts the process by creating data queue OFCEMP in QTEMP. The data queue is created as *KEYED. The total record length is 54 (total of all four fields we want to display), and the key length is 20 since the widest field that we may select as the key has a length of 20 (OETITL).

CL program OFC001CL (Figure 6b) starts the process by creating data queue OFCEMP in QTEMP. The data queue is created as *KEYED. The total record length is 54 (total of all four fields we want to display), and the key length is 20 since the widest field that we may select as the key has a length of 20 (OETITL).

Display file OFC001DF (6c) defines the F6 key to sort the employee database; you move the cursor to the column containing the field by which you want to sort, press F6, and the file is sorted. It uses the CSRLOC keyword to position the cursor on output-that way the cursor stays in the same position it was before you pressed F6, even though there are no input fields on the screen.

Display file OFC001DF (Figure 6c) defines the F6 key to sort the employee database; you move the cursor to the column containing the field by which you want to sort, press F6, and the file is sorted. It uses the CSRLOC keyword to position the cursor on output-that way the cursor stays in the same position it was before you pressed F6, even though there are no input fields on the screen.

RPG program OFC001RG (6d) begins execution at the *INZSR subroutine. It positions the cursor at row 3, column 16 (the first name column of the subfile) and runs subroutine SORT.

RPG program OFC001RG (Figure 6d) begins execution at the *INZSR subroutine. It positions the cursor at row 3, column 16 (the first name column of the subfile) and runs subroutine SORT.

SORT first clears the data queue by calling QCLRDTAQ, then clears the subfile. Next, it reads all records in the OFCEMP file, sending each record to the data queue. Notice that I have coded a SELEC group which assigns a different value to KEYFLD depending on the position of the cursor. Actually, only the column number has any bearing: if less than 16, KEYFLD receives the extension number; if less than 35, it receives the first name; if less than 53, it receives the last name; otherwise, it receives the title. Thus we send the employee record to the data queue, but specifying a different field as the key field. Lastly, the data queue is read sequentially by key, writing each record into the subfile.

Control is then transferred to the mainline, which displays the subfile. If the user moves the cursor and presses F6, OFC001RG determines the position of the cursor via the INFDS of the display file and runs SORT all over again.

With the small file (30 records), performance was excellent. If you decide to implement this technique with your large files, performance may be a consideration.

How It Works

Subroutine SORT is the place where everything happens. All I've done is read the file sequentially (in arrival sequence-not even by key) and write each record into the data queue, repeating one of the four fields as the key field (KEYFLD). Which field is used depends on the position of the cursor. Because the data queue is keyed, I must use six parameters when I call QSNDDTAQ.

Then I turn around and read the data queue sequentially by key. This is done by specifying 'GE' as the order in which I want to receive the records and specifying *BLANK as the key value. Consequently, the data queue will issue the record that has the lowest key. Since records are automatically deleted from the data queue when QRCVDTAQ receives them, the next loop through QRCVDTAQ (again using 'GE' and *BLANK) will receive the next record in ascending value of the key field. The records come out of the queue in alphabetic sequence. If I had specified 'LE' for the order and *HIVAL (or all 9's) for the key value, the records would have come out in descending order.

Try it out! Enter the source code in Figures 6a to 6d and compile them as indicated at the bottom of each figure. Then use DFU or SQL to add a few records to OFCEMP. To use DFU, for example, run the Update Data (UPDDTA) command. Then CALL OFC001CL to start the demo.

Drawbacks of Data Queues

Data queues provide the fastest method to pass information between jobs, but they do have a few problems that I'd like to submit to you:

You can't display their contents because there's no Display Data Queue (DSPDTAQ) command. QUSRTOOL provides one, but it doesn't work. When I tested it, it only displayed the first character of each record instead of the whole record. I'm convinced it's a bug somewhere.

Since entries are automatically deleted the moment they're received with QRCVDTAQ, there's a potential for losing data if the program that receives the record from the data queue aborts before making use of it. The record would be lost and there's no way to retrieve it. Commitment control won't help because data queues are not files.

As you send records to data queues, the size of the *DTAQ object in-creases. When records are received from the data queue, the object does not shrink. If the Display Object Description (DSPOBJD) command shows an abnormally large size for a data queue, you should delete it and re-create it or use the Reorganize Data Queues command I've created (see page 66).

The Queue Review

You have seen how much you can accomplish with data queues. They provide an excellent vehicle for program-to-program transferral of data without overburdening your system. While they are not a drop-dead-if-you-don't-use-'em technique, data queues do have a place in modern, structured programming and can improve the performance of your system considerably.


Line Up for Data Queues

Figure 1 Using QSNDDTAQ in RPG

 
  Figure 1:  Using QSNDDTAQ in RPG 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 
  C                     CALL 'QSNDDTAQ' 
  C                     PARM           DTAQ   10 
  C                     PARM           DQLIB  10 
  C                     PARM           LEN     50 
  C                     PARM           DATA 
  C                     PARM           KEYLEN  30 
  C                     PARM           KEY 
  DTAQ:         Data queue name 
  DQLIB:        Data queue library name 
  LEN:          Record length 
  DATA:         Record data.  Must be of the length indicated by LEN. 
 
  Optional Parameters 
 
  KEYLEN:          Key length, if *KEYED. 
  KEY:          Key value, if *KEYED.  Must be of the length 
            indicated by KEYLEN. 

Line Up for Data Queues

Figure 2 Using QRCVDTAQ in RPG

 
  Figure 2:  Using QRCVDTAQ in RPG 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 
  C                     CALL 'QRCVDTAQ' 
  C                     PARM           DTAQ   10 
  C                     PARM           DQLIB  10 
  C                     PARM           LEN     50 
  C                     PARM           DATA 
  C                     PARM           WAIT    50 
  C                     PARM           ORDER   2 
  C                     PARM           KEYLEN  30 
  C                     PARM           KEY 
  C                     PARM           SNDLEN  30 
  C                     PARM           SNDID 
  DTAQ:         Data queue name 
  DQLIB:        Data queue library name 
  LEN:          Length of record received. 
                Set to zero if no record was received. 
  DATA:         Data received.  Must be of the length indicated by LEN. 
  WAIT:         Seconds to wait for a record.  Zero means no wait. 
                A negative number means to wait indefinitely. 
 
  Optional Parameters 
 
  ORDER:        Order to receive by key, if *KEYED.  Can be EQ, NE, 
                LT, LE, GT or GE. 
  KEYLEN:       Key length, if *KEYED. 
  KEY:          Key value, if *KEYED.  Must be of the length 
                indicated by KEYLEN. 
  SNDLEN:       Length of SNDID field.  44 is recommended. 
  SNDID:        Field to receive sender ID.  Character, 44 bytes 
                is recommended. 

Line Up for Data Queues

Figure 3 Example of QCLRDTAQ in RPG

 
  Figure 3:  Example of QCLRDTAQ in RPG 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 
  C                     CALL 'QCLRDTAQ' 
  C                     PARM           DTAQ   10 
  C                     PARM           DQLIB  10 

Line Up for Data Queues

Figure 4A Inventory System (unable to display graphic)


Line Up for Data Queues

Figure 4B Physical file ITH

 
       A          R ITREC 
       A            ITITEM        15          TEXT('ITEM NUMBER') 
       A            ITQTY          7P 0       TEXT('TRANSACTION QUANTITY') 
       A                                      EDTCDE(J) 

Line Up for Data Queues

Figure 4C Display file INV001DF

 
       A                                      DSPSIZ(24 80 *DS3) 
       A                                      REF(ITH) 
       A                                      PRINT 
       A                                      CA03(03 'Exit') 
       A                                      CA12(12 'Cancel') 
        * 
       A          R ENTRY 
       A                                      BLINK 
       A                                  1 27'Enter Inventory Transactions' 
       A                                      DSPATR(HI) 
       A                                  4  2'Enter a transaction:' 
       A                                      COLOR(BLU) 
       A                                  6 10'Item number' 
       A                                  6 35'Quantity' 
       A            EITEM     R        B  7 10REFFLD(ITITEM) 
       A            EQTY      R        B  7 34REFFLD(ITQTY) 
       A                                 23  2'F3=Exit   F12=Cancel' 
       A                                      COLOR(BLU) 

Line Up for Data Queues

Figure 4D DDS INV001DD for Data Queue

 
       A                                      REF(ITH) 
        * 
       A          R DQREC 
       A            DQITEM    R               REFFLD(ITITEM) 
       A            DQQTY     R               REFFLD(ITQTY) 

Line Up for Data Queues

Figure 4E RPG program INV001RG

 
       FINV001DFCF  E                    WORKSTN 
        * 
       IDQDTA     E DSINV001DD 
        * 
       C           'FOREVER' DOWEQ'FOREVER' 
       C                     EXFMTENTRY 
       C           *IN03     IFEQ *ON 
       C           *IN12     OREQ *ON 
       C                     LEAVE 
       C                     ENDIF 
        * Move data entry fields to subfields of DQDTA structure 
       C                     MOVE EITEM     DQITEM 
       C                     Z-ADDEQTY      DQQTY 
        * Send DQDTA structure to data queue 
       C                     CALL 'QSNDDTAQ' 
       C                     PARM 'INVTRNDQ'DQ#NAM 10 
       C                     PARM '*LIBL'   DQ#LIB 10 
       C                     PARM 19        DQ#LEN  50 
       C                     PARM           DQDTA 
        * Erase entry fields 
       C                     MOVE *BLANK    EITEM 
       C                     Z-ADD*ZERO     EQTY 
       C                     ENDDO 
        * 
       C                     MOVE *ON       *INLR 

Line Up for Data Queues

Figure 5A CL program INV002CL

 
   INV002CL:   PGM 
 
               DCL        VAR(&RTNLIB) TYPE(*CHAR) LEN(10) 
 
               RTVOBJD    OBJ(INV002CL) OBJTYPE(*PGM) RTNLIB(&RTNLIB) 
               CRTDTAQ    DTAQ(&RTNLIB/INVTRNDQ) MAXLEN(19) SEQ(*FIFO) 
               MONMSG     MSGID(CPF0000) 
 
               OVRDBF     FILE(ITH) FRCRATIO(1) 
               CALL       PGM(INV002RG) 
 
               ENDPGM 

Line Up for Data Queues

Figure 5B RPG program INV002RG

 
       FITH     O   E                    DISK                      A 
        * 
       IDQDTA     E DSINV001DD 
        * 
       C           'FOREVER' DOWEQ'FOREVER' 
        * Get transaction request from data queue 
       C                     CALL 'QRCVDTAQ' 
       C                     PARM 'INVTRNDQ'DQ#NAM 10 
       C                     PARM '*LIBL'   DQ#LIB 10 
       C                     PARM 19        DQ#LEN  50 
       C                     PARM           DQDTA 
       C                     PARM 300       DQ#WT   50 
        * If none retrieved, check system time to end program 
       C           DQ#LEN    IFEQ *ZERO 
       C                     TIME           SYSTIM  60 
       C           SYSTIM    IFGT 210000 
       C                     LEAVE 
       C                     ENDIF 
       C                     ELSE 
        * Else, write transaction to history file and continue 
       C                     MOVE DQITEM    ITITEM 
       C                     Z-ADDDQQTY     ITQTY 
       C                     WRITEITREC 
       C                     ENDIF 
       C                     ENDDO 
        * 
       C                     MOVE *ON       *INLR 

Line Up for Data Queues

Figure 6A Physical file OFCEMP

 
  Figure 6a:  Physical File OFCEMP 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
  A                                      UNIQUE 
  A          R OEREC 
  A            OELNAM        15          TEXT('Last name') 
  A            OEFNAM        15          TEXT('First name') 
  A            OETITL        20          TEXT('Title') 
  A            OEEXTN         4S 0       TEXT('Phone extension number') 
  A                                      EDTCDE(3) 
  A          K OELNAM 
  A          K OEFNAM 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
 
  To compile:  CRTPF FILE(xxx/OFCEMP) SRCFILE(xxx/QDDSSRC) 

Line Up for Data Queues

Figure 6B CL program OFC001CL

 
  Figure 6b:  CL Program OFC001CL 
 
   OFC001CL:   PGM 
 
               DLTDTAQ    DTAQ(QTEMP/OFCEMP) 
               MONMSG     MSGID(CPF0000) 
               CRTDTAQ    DTAQ(QTEMP/OFCEMP) MAXLEN(54) SEQ(*KEYED) + 
                            KEYLEN(20) 
               CALL       PGM(OFC001RG) 
 
               ENDPGM 
 
  To compile:  CRTCLPGM PGM(xxx/OFC001CL) SRCFILE(xxx/QCLSRC) 

Line Up for Data Queues

Figure 6C Display file OFC001DF

 
  Figure 6c:  Display File OFC001DF 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
  A                                      DSPSIZ(24 80 *DS3) 
  A                                      PRINT 
  A                                      CA03(03 'Exit') 
  A                                      CA06(06 'Sort') 
  A                                      CA12(12 'Cancel') 
  A                                      REF(OFCEMP) 
   * 
  A          R EMPRCD                    SFL 
  A            $EXTN     R        O  4  8REFFLD(OEEXTN) 
  A            $FNAM     R        O  4 16REFFLD(OEFNAM) 
  A            $LNAM     R        O  4 35REFFLD(OELNAM) 
  A            $TITL     R        O  4 53REFFLD(OETITL) 
   * 
  A          R EMPCTL                    SFLCTL(EMPRCD) 
  A                                      BLINK 
  A                                      CSRLOC(CSRROW CSRCOL) 
  A                                      OVERLAY 
  A  81                                  SFLDSP 
  A  81                                  SFLDSPCTL 
  A N81                                  SFLCLR 
  A N80                                  SFLEND 
  A                                      SFLSIZ(0300) 
  A                                      SFLPAG(0018) 
  A            CSRROW         3  0H 
  A            CSRCOL         3  0H 
  A                                  1 29'Display Office Employees' 
  A                                      DSPATR(HI) 
  A                                  3  5'Extension' 
  A                                      DSPATR(HI) 
  A                                  3 16'First Name' 
  A                                      DSPATR(HI) 
  A                                  3 35'Last Name' 
  A                                      DSPATR(HI) 
  A                                  3 53'Title' 
  A                                      DSPATR(HI) 
   * 
  A          R FKEYS 
  A                                      LOCK 
  A                                 23  2'F3=Exit   F6=Sort (cursor sensitiv- 
  A                                      e)   F12=Cancel' 
  A                                      COLOR(BLU) 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
 
  To compile:  CRTDSPF FILE(xxx/OFC001DF) SRCFILE(xxx/QDDSSRC) 

Line Up for Data Queues

Figure 6D RPG program OFC001RG

 
  Figure 6d:  RPG Program OFC001RG 
 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
  FOFC001DFCF  E                    WORKSTN 
  F                                        SFLRRNKSFILE EMPRCD 
  F                                              KINFDS INFDS 
  FOFCEMP  IF  E                    DISK 
   * 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
  IINFDS       DS 
  I                                    B 370 3710CURSOR 
   * 
  IDQDTA     E DSOFCEMP 
  I              OELNAM                          LNAM 
  I              OEFNAM                          FNAM 
  I              OETITL                          TITL 
  I              OEEXTN                          EXTN 
   *======================================================= 
  C           'FOREVER' DOWEQ'FOREVER' 
  C                     EXFMTEMPCTL 
  C                     SELEC 
  C           *IN03     WHEQ *ON                        Exit 
  C           *IN12     OREQ *ON                        Cancel 
  C                     LEAVE 
  C           *IN06     WHEQ *ON                        Sort 
  C           CURSOR    DIV  256       CSRROW 
  C                     MVR            CSRCOL 
  C                     EXSR SORT 
  C                     ENDSL 
  C                     ENDDO 
  C                     MOVE *ON       *INLR 
   *======================================================= 
  C           *INZSR    BEGSR 
  C                     WRITEFKEYS 
  C                     Z-ADD3         CSRROW 
  C                     Z-ADD16        CSRCOL 
  C                     EXSR SORT 
  C                     ENDSR 
   *======================================================= 
  C           SORT      BEGSR 
   * Clear data queue 
  C                     CALL 'QCLRDTAQ' 
  C                     PARM 'OFCEMP'  DQ#NAM 10 
  C                     PARM '*LIBL'   DQ#LIB 10 
  C                     MOVE *OFF      *IN81 
  C                     WRITEEMPCTL 
  C                     MOVE *ON       *IN81 
   * Read database file, writing to data queue 
  C                     Z-ADD*ZERO     RRN     40 
  C           'FOREVER' DOWEQ'FOREVER' 
  C                     ADD  1         RRN 
  C           RRN       CHAINOFCEMP               99 
  C           *IN99     IFEQ *ON 
  C                     LEAVE 
  C                     ENDIF 
   * Key depends on position of cursor 
  C                     SELEC 
  C           CSRCOL    WHLT 16 
  C                     MOVELOEEXTN    KEYFLD 20 
  C           CSRCOL    WHLT 35 
  C                     MOVELOEFNAM    KEYFLD 
  C           CSRCOL    WHLT 53 
  C                     MOVELOELNAM    KEYFLD 
  C                     OTHER 
  C                     MOVELOETITL    KEYFLD 
  C                     ENDSL 
  C                     MOVE OELNAM    LNAM 
  C                     MOVE OEFNAM    FNAM 
  C                     MOVE OETITL    TITL 
  C                     Z-ADDOEEXTN    EXTN 
  C                     CALL 'QSNDDTAQ'                 Send 
  C                     PARM           DQ#NAM 
  C                     PARM           DQ#LIB 
  C                     PARM 54        DQ#LEN  50 
  C                     PARM           DQDTA 
  C                     PARM 20        DQ#KL   30 
  C                     PARM KEYFLD    DQ#KEY 20 
  C                     ENDDO 
   * Read data queue sequentially by key, writing to subfile 
  C                     SUB  1         RRN 
  C           1         DO   RRN       SFLRRN  40 
  C                     CALL 'QRCVDTAQ'                 Receive 
  C                     PARM           DQ#NAM 
  C                     PARM           DQ#LIB 
  C                     PARM 54        DQ#LEN 
  C                     PARM           DQDTA 
  C                     PARM *ZERO     DQ#WT   50 
  C                     PARM 'GE'      DQ#ORD  2 
  C                     PARM 20        DQ#KL   30 
  C                     PARM *BLANK    DQ#KEY 
  C                     PARM 44        DQ#SL   30 
  C                     PARM *BLANK    DQ#SND 44 
  C                     Z-ADDEXTN      $EXTN 
  C                     MOVE FNAM      $FNAM 
  C                     MOVE LNAM      $LNAM 
  C                     MOVE TITL      $TITL 
  C                     WRITEEMPRCD 
  C                     ENDDO 
  C                     ENDSR 
  ... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+ ...8 
 
  To compile:  CRTRPGPGM PGM(xxx/OFC001RG) SRCFILE(xxx/QRPGSRC) 
BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: