|
|
![]() |
|
|
Batch Jobs Can Talk Back by John Chadwick Users demand a quick turnaround on their batch jobs. But how do they know when the batch job is done? It may produce a report, but there can be a lag time before it actually prints, and you don't want impatient users submitting the same job over and over, as if that will help. The 20th answer was that users would get a cryptic system message once a batch job had finished, which they probably 'wouldn't understand. The new way is slick and easy. The modern age has arrived!
An E-Mail Surprise A surprise was sent to my e-mail inbox in the form of Shannon O'Donnell's article "Back to Basics: Self-Updating Display File," about attaching, of all things, a data queue to a display file. He showed how a data queue could be used to add entries to a subfile, one by one, as the user watches (in awe, no doubt!). It occurred to me that this same little gem was the answer to a problem that's been on my back burner for years. When an interactive job submits a print or post process to batch, where the interactive job remains active for the user to continue performing asynchronous operations, I want the user to know when the submitted job is complete. And I want the interactive job to tell him--via my message subfile--right away and automatically. The message should just appear, like magic! (Don't even suggest a break message; they're rude!) Of course, the message must also be informative--for instance, "Invoice 5362 for The XYZ Company has been printed," and not "Job 004532/CHADWICJ/PRINTINV has completed successfully." The Data Queue A quick refresher. You'll need a non-keyed data queue with a minimum length of 80 bytes. At runtime, it must be attached to the display file that is to receive the message from the submitted batch job. A good name for this data queue would contain the interactive job's number. Since more than one user could be involved, you'll attach the queue to the display file with the OVRDSPF command:
DCL VAR(&JOBNBR) TYPE(*CHAR) LEN(6)
DCL VAR(&DTAQNM) TYPE(*CHAR) LEN(10)
RTVJOBA NBR(&JOBNBR)
CHGVAR VAR(&DTAQNM) VALUE ('DQ' *CAT &JOBNBR)
CRTDTAQ DTAQ(CHADWICK/&DTAQNM) MAXLEN(100)
OVRDSPF FILE(PAP100D) DTAQ(&DTAQNM)
Do not put the data queue in QTEMP; the batch job needs to add an entry to it. Also, be sure to pass the data queue name from the CL to the online program and from there on to the batch job. Your online program will need to monitor the data queue all the time, so that as soon as the batch job adds the completion message to the queue, it becomes available to display on the screen (more on loading the message to the queue, below). As Shannon taught us, the system will also write an entry to the queue whenever the user presses a transmission key--like the Enter key or the F key--so your program needs some minor surgery. The RPG Code As simple as monitoring the data queue is, I have put all the code for it in a small program that is generic enough to be used by every program that you want to have displaying messages from any batch job, and it isn't tied to a specific data queue. I've named it PSYNCMSG. This program accepts three parameters: the data queue name and two flags named P@DspFlg and P@ScrnRead. The display flag simply tells the calling program whether the user took some action on the screen, or that a message was received in the data queue (the message you'll load to the data queue via the submitted job, when it's complete). The screen read flag is set by the caller (your online program) and indicates whether your program just read from the screen or is just returning control back to this one to monitor the data queue again. More on this flag later. Here is the important code for PSYNCMSG:
C If DqDlen <> 0
C If %Subst(Dqdata:1:5) = '*DSPF'
C Eval P@DspfFlg = *ON
C Else
C Eval P@DspfFlg = *OFF
C If P@ScrnRead
C call 'QMHRMVPM' rmvpm
C Eval P@ScrnRead = *off
C Endif
C Eval msg_data = Dqdata
C Call 'QMHSNDPM' sndpm
C Endif
C Endif
The code that receives an entry from the data queue is not shown, but you can go back and read Shannon O'Donnell's article for a code sample. What's not shown is that the code for receiving the data queue is set up so that it's wait value is –1 (which will cause it to wait forever). When an entry is received from the queue, the code above is executed. The system will load the value "*DSPF" as the data queue entry whenever the user presses a transmission key. Then the flag P@DspfFlg is set to inform your program, and this program returns control to it. If it's not *DSPF, then the big moment has arrived! The Payoff! Of course, you'll modify the submitted job to load a completion message to the data queue as one of its last steps. Use the QSNDDTAQ API (again, check out Shannon's article) and pass it the name of the data area that your online job passed to your batch job and load up any message that suits your needs. Now we can inform the expectant user. The display flag is set off, so your program won't try to process screen input. Next, your program's message queue is cleared if your program indicated that it called this program after writing a screen. This will ensure that the batch message appears first in your message subfile and would normally be done in your program. Then the message in the data queue entry is sent (in this case, as the message data for message CPF9898) to your program's queue. I took the easy way out and assumed the message queue to use is one up from this program. If your program doesn't have a message file, just pass the data queue entry value back to your program instead. (Remember, the message hasn't displayed on the screen yet; this program just writes it to the online program's message queue.) Our work is done here; now on to the modifications needed for your online program. Things are pretty simple here, too. There's just one tiny little thing. You need to break up your EXFMT's into their component parts, which is not a big deal. Write the message subfile control record and your main record format, then call the PSYNCMSG program described above. Immediately afterward, you'll check to see if it loaded a message to your program queue or if it is just letting you know the user performed some action. If the message came through from the batch program, just write your message subfile control record to display it. Otherwise the user pressed a function key or the Enter key, so turn on the screen-read flag for the next call to the data queue monitor program, read the contents of the screen, then process the user's request as you normally would. All that the data queue does for you is let you know the user took some action; you have to read the screen to see what he wants. In the BATCHS SR, I test an input field, and if it's "M", I submit the job that sends the completion message to the data queue being monitored. C *INKC DOUEQ*ON C MOVE *ON *IN35 C WRITEMSGCTL C WRITEMENU C CALL 'PSYNCMSG'PARML C DSPFFL IFEQ *OFF C MOVE *OFF *IN35 C MOVE *ON *IN36 C WRITEMSGCTL C ELSE C MOVE *OFF *IN35 C MOVE *OFF *IN36 C MOVE *ON SCRNRD C READ MENU 21 C EXSR BATCHS C ENDIF C ENDDO Finished! Unless, of course, you were wondering about indicators 35 and 36. They're important. Condition the INVITE keyword on *IN35 at the file level in your DDS. Without it, your screen will remain input-inhibited forever. *IN36 needs to condition the PUTOVR keyword on the record formats that are displayed with the message subfile. That's it. And if you want to get carried away, you could have every online program call the message queue monitor program. That way, even if the user goes into a different program before the batch job is finished, he could still be notified. It should work on your CL menu program displays, as well. Wrapping It All Up By the way, I first used this technique on a native program originally written (on the S/36) with the display file specified as combined, primary, and program-described, with detail time output to the screens. I changed the file to full-procedural and added the loop (above) around the mainline. All the detail output to the screens was changed to Exception time, with one except name, and an EXCPT was issued to it in place of a Write. You can write a message subfile control record this way as well. John Chadwick is a project leader for DMC Consulting in Toledo, Ohio.
|
Editors
Contact the Editors |
|
Last Updated: 11/7/02 Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |