Administering an IBM i: how the system works Chapter 4 of 10

The library list

Reviewed on Verified on IBM i 7.5

Log in to save

Libraries are one level deep and do not contain other libraries. The obvious question follows: how does a program find a file if nobody tells it which library it is in?

The answer is the library list: an ordered list of libraries belonging to the job, not to the program. When an object is named without saying where it lives, the system looks through the libraries in the list, one after another, stopping at the first that contains it.

This is where the hierarchy that seemed to be missing went. It is also the origin of nearly every problem that starts with "it works in my environment".

The four parts

The list is not flat: it has up to four parts, and only the first is always there.

  1. System part. Holds the libraries the system needs. It comes from the system value QSYSLIBL, which as shipped contains QSYS, QSYS2, QHLPSYS and QUSRSYS and can hold up to fifteen. For a single job it is changed with CHGSYSLIBL.
  2. Product libraries. Up to two, managed by the system: it puts them in and takes them out when a command or menu needs them. Not yours to touch.
  3. Current library. Exactly one. It is where a program created without naming a library ends up; if the job has none, QGPL is used. Changed with CHGCURLIB.
  4. User part. The list proper, where the application libraries sit, up to 250. Its starting value depends on how the job is born (next section); the system value QUSRLIBL, up to twenty-five libraries, is used when the job description says *SYSVAL.

A change to QSYSLIBL or QUSRLIBL applies to jobs started afterwards, not to those already running.

To see your own job's:

DSPLIBL
SELECT ORDINAL_POSITION, SYSTEM_SCHEMA_NAME, TYPE, TEXT_DESCRIPTION
  FROM QSYS2.LIBRARY_LIST_INFO
 ORDER BY ORDINAL_POSITION

The TYPE column says which part each library belongs to: SYSTEM, PRODUCT, CURRENT or USER.

And another job's, which is the one you need when investigating:

WRKJOB JOB(123456/MARIO/CLOSE) OPTION(*LIBL)

Only for an active job: a finished job's list is gone.

Where it comes from

And here is where the misunderstandings live, because the initial user part does not always come from the same place.

  • An interactive session takes it from its job description (INLLIBL parameter), and during the day it is often edited by hand with ADDLIBLE.
  • A job submitted with SBMJOB, if nothing is said, inherits the submitter's list: the default of INLLIBL is *CURRENT. With INLLIBL(*JOBD) it takes it from the job description the job uses instead, with *SYSVAL from QUSRLIBL.
  • A schedule entry (ADDJOBSCDE) has no library list parameter: the job takes it from its job description, which by default is the user profile's.

Warning

this is the classic cause of "it works when I run it and not at night". The same program, submitted from a session, inherits that session's list, including libraries added by hand; scheduled, it gets the job description's, which is often shorter. The error talks about an object not found and it looks as if something is missing: the library is there, but not in that job's list. You check with DSPJOBD on the description the job really uses, not on your own session.

There is a way to leave nothing to chance, and that is declaring the list on the command that submits:

SBMJOB CMD(CALL PGM(PRODLIB/CLOSE))  +
       JOB(CLOSE)                     +
       JOBD(PRODLIB/BATCHJOBD)        +
       INLLIBL(PRODLIB DATALIB QGPL QTEMP)

The ambiguity risk

If two libraries in the list contain an object with the same name, the first one wins. Silently: no warning, no trace in the job log, no way to notice unless you go looking.

This is how the worst incidents start, because the symptom is not an error but a wrong result. A test file left in a library put at the top of the list "just for a moment" makes the month-end close run against test data, and the program has no way of knowing.

Tip

the defence that holds up over the years is not a shorter library list but qualifying objects in programs — writing PRODLIB/ORDERS instead of ORDERS wherever the choice must not depend on the environment. It costs some flexibility and removes an entire class of failures. Where flexibility genuinely is needed — because the same program has to run against test and production — the library list is the right tool, but then the choice is declared rather than inherited by accident.

Changing it

For the current job only:

ADDLIBLE LIB(TESTLIB) POSITION(*FIRST)
RMVLIBLE LIB(TESTLIB)
CHGCURLIB CURLIB(MYLIB)

Permanently, by changing the job description jobs take it from:

CHGJOBD JOBD(PRODLIB/BATCHJOBD) +
        INLLIBL(PRODLIB DATALIB QGPL QTEMP)

Warning

a JOBD is often shared by many jobs. Removing a library from it breaks them all at once, and the resulting error talks about a missing object: the symptom, not the cause. Before changing a job description it is worth knowing who uses it: WRKJOBSCDE for schedules, and user profile JOBDs with SELECT AUTHORIZATION_NAME, JOB_DESCRIPTION_NAME, JOB_DESCRIPTION_LIBRARY_NAME FROM QSYS2.USER_INFO. The library must be asked for alongside the name: a job description without its library is ambiguous, which is exactly the ambiguity this chapter is about.

The limit

The user part goes up to 250 libraries, QUSRLIBL up to 25, QSYSLIBL up to 15. These are not constraints you meet in practice, and a long list is a problem in its own right: it multiplies the chances of ambiguity.

Sources

Back to the guide index

← Back to blog

Comments

No comments yet. Be the first to comment!

You need an account to comment. Log in · Sign up