Keep Those Batch Jobs Running (Or How to Enjoy Your Off Time) PDF Print E-mail
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?"

I think this is an excellent idea! In this article, we'll look at how to use the List Job (QUSLJOB) API to monitor batch jobs and, if any job is found to be waiting on a message, to then send a generic message to a *DTAQ, identifying the job that is waiting for a reply. Though not shown in this article, a second program could monitor this *DTAQ and then perform operations such as sending a break message to the operator, paging the operator, setting off an alarm, sending a text message to someone's phone, sending an email, and so on.

 

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