23
Mon, Dec
1 New Articles

Tips and Techniques: Use JOBDs to Store Library Lists

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

Nearly 20 years ago, I asked IBM to add the ability to create named library lists on the System/38. My reasoning was that in CL you often needed to set the library list based on the environment of the application. For example, if I was running accounting applications, I might want the accounting library list; for the order-entry application, I might need the order-entry library list.

The other day I was lurking in the Discussion Forum on my Web site, and someone asked about using an old QUSRTOOL (which is now a commercial application) to retrieve the library list of a job description. The tool didn't work any longer because, apparently, the format of the spool file of the DSPJOBD command had changed. (Are there really still tools out there that use spool files as an information resource for CL tools? Is this 1986 or 2006? But I digress.)

Anyway, the idea of retrieving the library list from a job description was compelling to me. I've had a RTVJOBD subprocedure in RPG xTools for a few years, but I never thought about using the JOBD object as a storage media for library lists.

This concept works perfectly in practice. Create a job description and assign a library list on the LIBL parameter. For example, to create an accounts payable library list in the library named QGPL, use the following CRTJOBD command:

CRTJOBD JOBD(QGPL/APLIBL) TEXT('A/P Library list') +
 INLLIBL(QUSRSYS QGPL QTEMP XTOOLS ISOCKETS APLIB) 

I wrote a simple CL command named RTVJOBD that returns the library. To call it from CL, use the following CL statements:

 TESTJOBD:   PGM 
             DCL        VAR(&LIBL) TYPE(*CHAR) LEN(2750) 
             DCL        VAR(&LIBLCNT) TYPE(*INT) LEN(2) 
             MONMSG     MSGID(CPF0000) 
             RTVJOBD    JOBD(QGPL/APLIBL) RTNLIBL(&LIBL) + 
                          RTNLIBLCNT(&LIBLCNT) 
             SNDPGMMSG  MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&LIBL)
 ENDPGM:     ENDPGM 

The variable &LIBL retrieves the library list from the job description. The optional library count parameter returns the number of libraries on the library list. The CL variable &LIBLCNT is declared as a 2-byte integer and receives the count from the RTVJOBD command.

To make the RTVJOBD command work, the Retrieve Job Description API (QWDRJOBD) is called. Unfortunately, IBM foolishly inserts a named constant with the name of the API into the QSYSINC source member that contains the API's data structure. Therefore, we have to make up an alternate name to call the prototype for QWDRJOBD. I chose RTVJOBDAPI. The prototype source code for this API follows:

      **  Retrieve Job Description
     D*QWDRJOBD        PR                  ExtPgm('QWDRJOBD')
     D RtvJobDAPI      PR                  ExtPgm('QWDRJOBD')
     D  szRtnBuffer               65535A   OPTIONS(*VARSIZE)
     D  nRtnBufLen                   10I 0 Const
     D**  Specify 'JOBD0100'
     D  apiFormat                     8A   Const
     D  JobD                         20A   Const
     D  api_error                          LikeDS(QUSEC)

The QWDRJOBD API returns the entire job description information, including the library list. But to make things work correctly, we have to ensure that the return structure is large enough to handle the fixed values returned by the API as well as the variable length elements, such as the library list. This means we need to either create one huge data structure or hope IBM never changes the output positions. Or we can do it the right way.

The right way is to (unfortunately) call the API twice. While I don't agree with having to do this, it is the only way to make sure the return buffer we provide to the API is large enough to receive the library list entries.

The first call to the API would be as follows:

D JobDInfo        DS                  LikeDS(QWDD0100)

C                   eval      APIErrDS= *ALLX'00'
C                   eval      APIErrDS.QUSBPRV = %size(APIErrDS)
C                   eval      JobDInfo = *ALLX'00'
C                   callp     RtvJobDAPI(JobDInfo : %size(JobDInfo):
C                                     'JOBD0100': szJOBD : APIErrDS)

This call retrieves the job description information, but the QWDD0100 data structure in the QSYSINC source member does not have space for the library list. So the library list is not returned. What is returned, however, is the so-called "Bytes Available" subfield. Since our return structure is named JOBDINFO, the subfield name is JobDInfo.QWDBAVL.

This field contains the number of bytes required to return the entire job description structure, including the library list. To make this work, we need to allocate storage for the return data. To do this, we use the %ALLOC operation, as follows:

D JobD            DS                  LikeDS(QWDD0100)
D                                     Based(pJobD)

C                   eval      pJobD = %Alloc(JobDInfo.QWDBAVL)
C                   eval      JOBD = *ALLX'00'
 **  Second call: Get the library list.
C                   callp     RtvJobDAPI(JOBD : JobDInfo.QWDBAVL :
C                                     'JOBD0100': szJOBD : APIErrDS)

Once this part of the routine is performed, we have enough storage to hold the entire job description. The JOBD data structure is based on the QWDD0100 data structure in QSYSINC. Therefore, it does not contain library list subfields. Instead, it contains the number of library names retrieved and the offset to the list of library names.

To access the library list, I declare two based variables. One is an array of 11-byte character elements. The second is a fixed-length field with a length of 2750. These two fields overlay one another in memory (they're both based on the same pointer). Therefore, the library list is accessible either as an array or as a character string.

We have to do a little math to get to the library list. Since only the library names on the library list are returned (not the full 2750-byte library list area), we have to make sure we retrieve only the library names that are returned rather than blindly copy 250 library names. To do this, pointer math and a %SUBST built-in function are used, as follows:

     D LibList         S             11A   Based(pLIBL) DIM(250)
     D LibL            S           2750A   Based(pLIBL)

      /free
        pLibl = pJobD + JobD.QWDOILL;
        rtnLibl = %subst(LIBL:1:JobD.QWDNLILL*%size(LibList));
      /end-free

The first assignment calculates the location of the library list in the API return buffer. Since the field LIBL is being copied to the value returned to the CL program that calls this program, only the number of library names times 11 is returned. The second assignment using the %SUBST built-in function performs this copy.

The RTVJOBD Command

The CL command RTVJOBD wraps the code featured in this article in an easy-to-use CL command that accepts three parameters.

  • JOBD—The job description whose library list is retrieved.
  • RTNLIBL—A CL variable that receives the library list. This must be large enough to handle the number of libraries returned. A fixed-length CL variable of 2750 bytes is large enough for today's library maximums. If you know the library list is 25 or fewer, a CL variable with a length of 275 bytes will be good enough.
  • RTNLIBLCNT—A CL variable that receives the number of library names returned. This parameter must be defined as a CL variable with TYPE(*INT) and LEN(2).

The command definition source code for the RTVJOBD command is available on the RPGIV.com downloads page. To compile it, use the following CRTCMD statement:

CRTCMD CMD(RTVJOBD) PGM(RTVJOBD) ALLOW(*IPGM *BPGM *IMOD *BMOD)

The RPG IV source code for the RTVJOBD program (used as the command processing program) is also available on the RPGIV.com downloads page. The compiler parameters are stored in the Header specification for this source member, so PDM option 14 or other methods should compile it without the need to prompt the CRTBNDRPG command.

The RTVJOBD command could easily be enhanced to include the ability to return any of the other attributes of the QWDRJOBD API.

Finally, after 20 years, I've found a way to store library lists in an object. The irony is that the QWDRJOBD API was introduced in OS/400 V2R2.

Bob Cozzi is a programmer/consultant, writer/author, and software developer of the RPG xTools, a popular add-on subprocedure library for RPG IV. His book The Modern RPG Language has been the most widely used RPG programming book for nearly two decades. He, along with others, speaks at and runs the highly-popular RPG World conference for RPG programmers.

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: