| Keep Those Batch Jobs Running (Or How to Enjoy Your Off Time) |
|
|
|
| Programming - APIs | |
| Written by Bruce Vining | |
| Wednesday, 03 September 2008 | |
|
With the QUSLJOB API and my MONBCH program working for you, you can relax when you're away from the office.
My recent series of articles prompted the following note from reader Jerry G.:
"I enjoy reading your articles as a learning exercise.... Would you consider demonstrating an API example to monitor jobs [in order to] notify [someone of] a troubled state like MSGW?"
In a subsequent article, we'll look at a V6R1 enhancement that allows us to easily send the text of the message to the *DTAQ (in addition to the job information, which is available on earlier releases). This enhancement allows the operator to know not only the specific message that needs to be responded to, but also the replies available. From here, it would not be a large leap to enable the operator to respond to the message using a handheld device. So if you haven't ordered V6R1, now is the time to do it!
The program we will use, Monitor Batch (MONBCH), is shown below.
h dftactgrp(*no)
dMonBch pr extpgm('MONBCH') dMonBch pi
dSetup pr * dDelay pr dProcessMsgW pr
dListJob pr extpgm('QSYS/QUSLJOB') d SpcName 20 const d Format 8 const d JobName 26 const d Status 10 const d QUSEC likeds(QUSEC) options(*nopass) d JobType 1 const options(*nopass) d NbrKeyFlds 10i 0 const options(*nopass) d KeyFlds likeds(KeyFlds) options(*nopass) d ContinHdl 48 const options(*nopass)
dSndDtaQMsg pr extpgm('QSYS/QSNDDTAQ') d DtaQName 10 const d DtaQLib 10 const d DataLen 5 0 const d Data 65535 const options(*varsize) d KeyLen 3 0 const options(*nopass) d KeyValue 65535 const options(*varsize :*nopass) d Asynch 10 const options(*nopass) d JrnEntry 10 const options(*nopass)
/copy qsysinc/qrpglesrc,qusgen /copy qsysinc/qrpglesrc,qusljob /copy qsysinc/qrpglesrc,qusec
dGenHdr ds likeds(QUSH0100) d based(GenHdrPtr)
dLstEntry ds likeds(QUSL020001) d based(LstPtr)
dAttrEntry ds likeds(QUSLKF) d based(AttrPtr)
dKeyFlds ds d KeyValues 10i 0 dim(25)
dUsrSpcName ds d Name 10 inz('MONBCHLJOB') d Library 10 inz('QTEMP')
dJobsToList ds d JobName 10 inz('*ALL') d JobUser 10 inz('*ALL') d JobNbr 6 inz('*ALL')
dPSDS sds 429 qualified d Line 21 28 d MsgID 40 46 d ExcpDta 91 170 d JobName 244 253
dDtaQMsg s 256 dLstCount s 10i 0 dAttrCount s 10i 0 dAttrValue s 100 based(AtrValPtr) dNbrKeyFlds s 10i 0 dContinue s n inz(*on) dMonBchCtl s 1 dtaara('VINING/MONBCHCTL')
dDtaQName c 'MESSAGES' dDtaQLib c 'VINING'
/free
monitor;
GenHdrPtr = Setup();
dow Continue; ListJob( UsrSpcName :'JOBL0200' :JobsToList :'*ACTIVE' :QUSEC :'B' :NbrKeyFlds :KeyFlds :*blanks);
// Check to see if the list is complete if (GenHdr.QUSIS = 'C') or (GenHdr.QUSIS = 'P');
// Get to the first list entry and process the list LstPtr = GenHdrPtr + GenHdr.QUSOLD;
for LstCount = 1 to GenHdr.QUSNBRLE; // Get first attribute and process all returned if LstEntry.QUSJIS = ' '; AttrPtr = LstPtr + %size(QUSL020001); for AttrCount = 1 to LstEntry.QUSNBRFR; AtrValPtr = AttrPtr + %size(QUSLKF); select; when AttrEntry.QUSKF = 0101; if %subst(AttrValue :1 :AttrEntry.QUSLD00) = 'MSGW'; ProcessMsgW(); endif; endsl; AttrPtr += AttrEntry.QUSLFIR; endfor; endif; LstPtr += GenHdr.QUSSEE; endfor; Delay(); else; dsply 'MONBCH is unable to access batch job information.'; *inlr = *on; return; endif; enddo;
*inlr = *on; return;
on-error; DtaQMsg = 'Job ' + %trimr(PSDS.JobName) + ' failed at statement ' + PSDS.Line + ' with message ' + PSDS.MsgID + ': ' + PSDS.ExcpDta; SndDtaQMsg( DtaQName :DtaQLib :%len(%trimr(DtaQMsg)) :DtaQMsg);
return;
endmon;
/end-free
*****************************************************************
pProcessMsgW b
dProcessMsgW pr dProcessMsgW pi
/free
DtaQMsg = 'Job ' + %trimr(LstEntry.QUSJNU00) + ' is waiting on a message.'; SndDtaQMsg( DtaQName :DtaQLib :%len(%trimr(DtaQMsg)) :DtaQMsg);
return;
/end-free
pProcessMsgW e
*****************************************************************
pDelay b
dDelay pr dDelay pi
dSleep pr 10u 0 extproc('sleep') d Seconds 10u 0 value
dTimeToEnd c 'E' dSecsPerMin c 60 dMinsToDly c 15
/free
in MonBchCtl; if MonBchCtl = TimeToEnd; Continue = *off; return; endif;
Sleep(SecsPerMin * MinsToDly);
in MonBchCtl; if MonBchCtl = TimeToEnd; Continue = *off; endif;
return;
/end-free
pDelay e
*****************************************************************
pSetup b
dSetup pr * dSetup pi *
dCrtUsrSpc pr extpgm('QSYS/QUSCRTUS') d SpcName 20 const d SpcAttr 10 const d SpcSiz 10i 0 const d SpcVal 1 const d SpcAut 10 const d SpcTxt 50 const d SpcRpl 10 const options(*nopass) d QUSEC likeds(QUSEC) options(*nopass) d SpcDmn 10 const options(*nopass) d SpcTfrSiz 10i 0 const options(*nopass) d SpcOptAln 1 const options(*nopass)
dRtvSpcPtr pr extpgm('QSYS/QUSPTRUS') d UsrSpcName 20 d UsrSpcPtr * d QUSEC likeds(QUSEC) options(*nopass)
dUsrSpcPtr s *
/free &nbs | |


