19
Fri, Apr
5 New Articles

The API Corner: Determining Whether Jobs Are Currently Active

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

Build your own API using the List Jobs System API.

 

I was recently asked by Mark H. if there's an easy way to determine whether a given job, using only a simple job name such as DAYEND rather than a qualified job name such as 123456/ABC/DAYEND, was currently active on the system. From my point of view, it's easy enough to call some system APIs to determine this, but he would prefer for application developers to just make a simple call to a function that, at a minimum, returns a yes or no type of response with no additional fuss. So today we'll be looking at how to package our use of system APIs within a *SRVPGM exported function that meets this requirement. In other words, we'll build our own API, over the system APIs, that will return an indicator value of *on if the specified job is active, otherwise *off to indicate the job is not currently active.

 

To accomplish this task, we'll define the function JobActive. JobActive requires one input parametera Char(10) job nameand returns an indicator. This function will enable the application developer to condition the running of the application, based on whether or not DAYEND is running, with code such as this:

 

 /free                                                 

                                                       

  if JobActive('DAYEND');                              

     // Do what is appropriate

     // (ENDJOB, retry in X minutes, etc)                            

  else;                                               

     // Do what is appropriate

     // (SBMJOB, continue running, etc)                    

  endif;                                              

                                                       

 /end-free   

 

To simplify life for our application developers, we'll also provide a source member in QRPGLESRC named JobChksPR. This member will provide the prototype for JobActive and can be copied into the application source using a directive such as /copy qrpglesrc,jobchkspr. This is the source for JobChksPR:

 

/if not defined(JobChks_Prototypes)                      

                                                          

d JobActive       pr              n                       

d  JobName                      10a   const               

                                                          

/define JobChks_Prototypes                               

/endif                               

 

To implement JobActive, we will use the List Job (QUSLJOB) API. As we will in the future be adding additional exports and capabilities we will use the rather generic name of JOBCHKS (Job Checks) for our *SRVPGM and module source. The initial source for JOBCHKS is this:

 

h nomain                                                               

                                                                        

d GetJobList      pr                                                   

d  JobName                      10a   const                            

d  Status                       10a   const                            

                                                                        

 /copy qrpglesrc,JobChksPR                                             

                                                                        

 *************************************************************          

                                                                        

d CrtUsrSpc       pr                  extpgm('QUSCRTUS')               

d  QualUsrSpcN                  20a   const                            

d  XAttr                        10a   const                            

d  IntSize                      10i 0 const                            

d  IntValue                      1a   const                            

d  PubAut                       10a   const                             

d  TxtDesc                      50a   const                            

d  ReplaceOpt                   10a   const options(*nopass)           

d  ErrCde                             likeds(QUSEC) options(*nopass)   

d  Domain                       10a   const options(*nopass)          

d  TfrSize                      10i 0 const options(*nopass)          

d  OptSpcAlgn                    1a   const options(*nopass)          

                                                                       

d LstJobs         pr                  extpgm('QUSLJOB')               

d  QualUsrSpcN                  20a   const                           

d  Format                        8a   const                           

d  QualJobName                  26a   const                           

d  Status                       10a   const                           

d  ErrCde                             likeds(QUSEC) options(*nopass)  

d  JobType                       1a   const options(*nopass)          

d  NbrFldsRtn                   10i 0 const options(*nopass)          

d  FldKeys                      10i 0 const options(*nopass)          

d  CntHandle                    48a   const options(*nopass)          

                                                                       

d RtvUsrSpcPtr    pr                  extpgm('QUSPTRUS')              

d  QualUsrSpcN                  20a   const                           

d  UsrSpcPtr                      *                                    

d  ErrCde                             likeds(QUSEC) options(*nopass)  

                                                                       

 ***********************************************************    

                                                                 

d JobHdrPtr       s               *                             

d LJobHdr         ds                  likeds(QUSH0100)          

d                                     based(JobHdrPtr)          

                                                                 

d ErrCde          ds                  qualified                 

d  Hdr                                likeds(QUSEC)             

d  MsgDta                      256a                             

                                                                 

 /copy qsysinc/qrpglesrc,qusec                                  

 /copy qsysinc/qrpglesrc,qusgen                                 

                                                                 

 ***********************************************************    

                                                                 

p JobActive       b                   export                    

d JobActive       pi              n                             

d  JobName                      10a   const                     

                                                                 

 /free                                                        

                                                               

  QUSBPrv = 0;                                                

  ErrCde.Hdr.QUSBPrv = %size(ErrCde);                          

                                                               

  if %subst(JobName :1 :1) = '*';                       

     return *on;                                             

  endif;                                                      

                                                               

  GetJobList(JobName :'*ACTIVE');                             

                                                               

  return (LJobHdr.QUSNbrLE <> 0);                             

                                                               

 /end-free                                                    

                                                               

p JobActive       e                                           

                                                               

 ***********************************************************

                                                             

p GetJobList      b                                             

d GetJobList      pi                                           

d  JobName                      10a   const                    

d  Status                       10a   const                    

                                                                

 /free                                                         

                                                                

  // Get addressability to Job List *USRSPC                    

                                                                

  RtvUsrSpcPtr('JOBLIST   QTEMP' :JobHdrPtr :ErrCde);          

                                                                

  if ErrCde.Hdr.QUSBAvl = 0;                                    

     // All is OK                                        

                                                          

  else;                                                  

     // Assume UsrSpc not found, so create it            

                                                          

     CrtUsrSpc('JOBLIST   QTEMP' :'JobList' :4096        

               :x'00' :'*ALL' :'Used by JobChks'         

               :'*YES' :QUSEC :'*DEFAULT' :0 :'1');      

                                                          

     RtvUsrSpcPtr('JOBLIST   QTEMP' :JobHdrPtr :QUSEC);  

  endif;                                                 

                                                          

  LstJobs('JOBLIST   QTEMP' :'JOBL0100'                   

          :(JobName + '*ALL      ' + '*ALL  ')           

          :Status :QUSEC);                               

                                                          

 /end-free                                               

                                                          

p GetJobList      e                                   

 

Before reviewing the JobActive procedure, let's look at the GetJobList procedure, where the real work within JOBCHKS is done and which is called by JobActive. The GetJobList procedure defines two input parameters. The first is the job name we're interested in; the second is the status of the job that we want to work with. The value of status can be *ACTIVE, *JOBQ, *OUTQ, or *ALL and is set by the caller of GetJobList (JobActive in our case). GetJobList utilizes the List Job API which, like other list APIs, uses a user space to return the result list of the API call. So the first piece of work in GetJobList is to attempt to retrieve a pointer to the user space QTEMP/JOBLIST, using the Retrieve Pointer to User Space (QUSPTRUS) API, and assign the pointer value to the variable JobHdrPtr.

 

If an error is encountered accessing the pointer value (that is ErrCde.Hdr.QUSBAvl, Bytes available of the API error code structure, is not 0), GetJobList attempts to create the QTEMP/JOBLIST user space using the Create User Space (QUSCRTUS) API and then again attempts to access the pointer using the QUSPTRUS API. Note that on the initial call to QUSPTRUS, the error code parameter used is ErrCde, while the call to QUSCRTUS, and the second call to QUSPTRUS, uses QUSEC as the error code parameter. When using ErrCde as the error code parameter, we are telling the called API that any errors encountered (like the user space not being found) will be handled by the caller (us). When using QUSEC as the error code parameter, we are telling the called API that any errors encountered (like being unable to create the user space) should be returned as escape messagesessentially ending our program with a highly visible error message to the user. So on the initial call to GetJobList, within the current job, the user space will not exist and GetJobList will create it. If for some reason the user space cannot be created, the system will send an appropriate CPF escape message.

 

If no error is encountered when initially accessing the pointer (ErrCde.Hdr.QUSBAvl is 0)implying that this is not the initial call to GetJobList within the jobGetJobList will just re-use the existing user space.

 

At this point, the user space QTEMP/JOBLIST exists and the variable JobHdrPtr is set to the initial byte of the user space. GetJobList now calls the List Job API. While the QUSLJOB API supports up to nine parameters, GetJobList needs only the first five. The first parameter identifies the user space to return the results of the API call to and is set to the user space JOBLIST in QTEMP. The second parameter identifies the type of job information to be returned in the user space and is set to the format name JOBL0100. JOBL0100 returns the least amount of information about the jobs found and since, as you'll see shortly, we don't really care about the job information at all, is used to minimize the work being done by the API. The third parameter identifies the job name we're interested in and is set to the JobName passed to GetJobList concatenated with a job user value of *ALL and a job number of *ALL. This indicates we want all jobs with the specified job name, regardless of the user the job is running under and the job number. The fourth parameter is the status of the jobs that we're interested in. This value comes from the caller of GetJobList and, in the case of JobActive, will be set to '*ACTIVE', indicating we only want active jobs, not jobs on a job queue waiting to run or jobs that have completed and have spooled output. The fifth parameter is the error code parameter and is set to QUSEC, indicating that any errors encountered by the API should be returned as escape messages.

 

If no error in running the QUSLJOB API is encountered, GetJobList then returns to its callerin the current case, JobActive.

 

Now let's take a look at the JobActive procedure. After setting the two instances of the API error code structure QUSEC and ErrCde to appropriate values (send escapes and not send escapes, respectively), JobActive checks to see if a special value (a job name starting with an asterisk) was specified by the application developer. Reviewing the QUSLJOB API documentation you will find that the job name parameter of the API supports three special values. These values ('*', '*CURRENT', and '*ALL') make no sense within the context of JobActive. The special values '*' and '*CURRENT' essentially indicate to test the current job, which will always be active, while the special value '*ALL' is to test for any job being active, which will always be the case. So rather than wasting our time getting the list, we'll just return *on (yes, you're active) and be done with it.

 

Note that this handling of special values is not quite "right." As written, JobActive is assuming that the special value being passed in by the application developer is one of the special values defined by the QUSLJOB API. That is, if the application developer codes JobActive('*INVALID'), they will also get *on returned by the procedure. But as I have no desire today to get into message handling (though you'll find plenty of previous articles that I've written on how to send an error message) and this article is on QUSLJOB rather than how to properly validate input parameter values, I'm leaving it in the current "not quite right" condition.

 

If the job name is not a special value, JobActive then calls GetJobList to request a list of all *ACTIVE jobs with the specified job name. As mentioned previously, we really don't care about the jobsjust whether or not there are any. So upon return from GetJobList, JobActive simply returns an indicator based on the number of entries returned (LJobHdr.QUSNbrLE) not being equal to 0. If not 0, then *on is returned, otherwise *off.

 

Assuming that the above source is stored in member JOBCHKS of source file QRPGLESRC, you can create the JOBCHKS module using this command:

 

CRTRPGMOD MODULE(JOBCHKS)

 

As my intention is to add more exports to JOBCHKS as time goes on, and I don't care for the hassle of working with system-generated signatures as these enhancements are made, let's explicitly define the exports and signature to be associated with the *SRVPGM. The following export specifications should be stored in member JOBCHKS for source file QSRVSRC.

 

StrPgmExp  PgmLvl(*Current) Signature('JOBCHKS')    

  Export     Symbol("JOBACTIVE")                    

EndPgmExp           

 

This source indicates that we will be exporting the function JOBACTIVE and that the signature for the *SRVPGM is to be hard-coded as JOBCHKS. We can now create the JOBCHKS *SRVPGM with the following command.

 

CRTSRVPGM SRVPGM(JOBCHKS)

 

Having created the *SRVPGM, now let's create a *BNDDIR, named SOMETOOLS, that application developers can reference when using functions exported by JOBCHKS. To do this, run the following commands.

 

CRTBNDDIR BNDDIR(SOMETOOLS)  

ADDBNDDIRE BNDDIR(SOMETOOLS) OBJ((JOBCHKS))

 

We're now ready to start using the JobActive function within our application code. The following program, named UseJobChks, demonstrates what is needed.

 

h dftactgrp(*no) bnddir('SOMETOOLS')                  

                                                       

d UseJobChks      pr                                  

d  JobName                      10a   const           

                                                       

d UseJobChks      pi                                  

d  JobName                      10a   const           

                                                       

 /copy qrpglesrc,JobChksPR                            

                                                       

 /free                                                 

                                                       

  if JobActive(JobName);                              

     dsply 'It is active';                            

  else;                                               

     dsply 'Not active right now';                    

  endif;                                              

                                                       

  *inlr = *on;                                     

  return;                                          

                                                    

 /end-free                                         

 

The sample program source and flow is as follows:

  1. An H-spec referencing the new *BNDDIR SOMETOOLS
  2. The definition of one input parameterthe job name to be tested
  3. A /copy of the prototypes for JOBCHKS
  4. Running of the JobActive function, passing it the job name to be tested
  5. DSPLYing a message based on the setting of the returned indicator
  6. Returning to the caller

 

To compile our sample program, you can use this command:

 

CRTBNDRPG PGM(USEJOBCHKS)

 

To test the UseJobChks program with a job name of NotHere, you can do this:

 

CALL PGM(USEJOBCHKS) PARM(NOTHERE)  

 

Assuming there are no jobs on the system named NotHere, this will result in the following message:

 

DSPLY  Not active right now           

 

Testing using the program with a job name of SCPF using

 

CALL PGM(USEJOBCHKS) PARM(SCPF) 

 

is likely to return the message

 

DSPLY  It is active    

 

And testing with CALL PGM(USEJOBCHKS) PARM(DAYEND) will return the message appropriate for whether or not DAYEND is currently running on the system.

 

Taking it a step further, let's say you have a set of related jobs (named DAYEND1, DAYEND2, DAYENDY, and DAYENDZ) and you want to know if one or more of these jobs is currently in an active status. What would be needed in order to check all four of these jobs? Assuming that the only job names that start with DAYEND are those that you're interested in, then you could simply use the following call:

 

CALL PGM(USEJOBCHKS) PARM(DAYEND*)

 

The QUSLJOB API supports generic job names, so to check if any jobs starting with the name DAYEND' are active, you just append the trailing asterisk to the job name and let UseJobChks, JobActive, and GetJobList pass that name, as is, to the QUSLJOB API.

 

Hopefully, you will agree that, from an application developer point of view, determining if a job is active or not is rather straightforward. And even building the *SRVPGM wasn't all that difficult.

 

Next month, we'll be providing additional exports and capabilities in JOBCHKS, so keep your source around for awhile.

 

As usual, if you have any API questions, send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.

 

Bruce Vining

Bruce Vining is president and co-founder of Bruce Vining Services, LLC, a firm providing contract programming and consulting services to the System i community. He began his career in 1979 as an IBM Systems Engineer in St. Louis, Missouri, and then transferred to Rochester, Minnesota, in 1985, where he continues to reside. From 1992 until leaving IBM in 2007, Bruce was a member of the System Design Control Group responsible for OS/400 and i5/OS areas such as System APIs, Globalization, and Software Serviceability. He is also the designer of Control Language for Files (CLF).A frequent speaker and writer, Bruce can be reached at This email address is being protected from spambots. You need JavaScript enabled to view it.. 


MC Press books written by Bruce Vining available now on the MC Press Bookstore.

IBM System i APIs at Work IBM System i APIs at Work
Leverage the power of APIs with this definitive resource.
List Price $89.95

Now On Sale

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$0.00 Raised:
$

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: