Return codes and COND
Every step leaves a return code. COND lets later steps look at those
codes and decide whether to run. It is also the most misread parameter in
JCL, because it works backwards.
COND=(code,operator)
//POST EXEC PGM=PAYPOST,COND=(8,LE)
Read it as: skip this step if 8 LE the return code of any
earlier step. That is, skip if 8 ≤ RC, so the step runs only while every
earlier RC is below 8.
The code comes first and the RC comes last, so say it out loud as "code operator RC":
| COND | Step is skipped when a previous RC is | So it runs when all RCs are |
|---|---|---|
(0,NE) |
anything but 0 | 0 |
(4,LT) |
5 or more | 0–4 |
(8,LE) |
8 or more | 0–7 |
(8,GT) |
0–7 | 8 or more |
(4,EQ) |
exactly 4 | anything but 4 |
Operators are GT, GE, EQ, NE, LT and LE. A step that is
skipped is flushed. It has no return code, doesn't count in later
tests, and the job log says so:
IEF142I PAYJOB VALIDATE - STEP WAS EXECUTED - COND CODE 0008
IEF202I PAYJOB POST - STEP WAS NOT RUN BECAUSE OF CONDITION CODES
IEF142I PAYJOB ALERT - STEP WAS EXECUTED - COND CODE 0000
The test looks at every previous step that ran, not only the one
just before. That's why ALERT above uses COND=(8,GT). Had POST run
and ended with RC 0, the test 8 GT 0 would be true and ALERT would be
skipped too, which is exactly right: if posting happened, there's
nothing to alert about.
After an abend
When a step abends, the system flushes every following step, whatever
its COND says, except:
COND=EVEN: run this step even if an earlier step abended.COND=ONLY: run this step only if an earlier step abended.
//CLEANUP EXEC PGM=IEFBR14,COND=EVEN
//BACKOUT EXEC PGM=PAYBACK,COND=ONLY
A JCL error is different: it stops the job there and then. No later
step runs, EVEN and ONLY included.
The job's MAXCC
The job log ends with the highest return code of any step:
$HASP395 PAYJOB ENDED - MAXCC=0008
Schedulers use it to decide whether the job "worked". Many sites treat MAXCC 4 as success and 8 as a failure that stops the schedule.
More than the simulator does
Real COND can name a step, COND=(4,LT,VALIDATE), so only that
step's RC is tested. It can hold up to eight tests,
COND=((8,LE),(4,EQ,STEP1)), and the step is skipped if any is
true. COND on the JOB statement applies to every step. Modern JCL
also has IF/THEN/ELSE/ENDIF, which reads the right way round:
// IF (VALIDATE.RC < 8) THEN
//POST EXEC PGM=PAYPOST
// ELSE
//ALERT EXEC PGM=PAYALERT
// ENDIF
Many shops prefer IF for new jobs, but you'll maintain plenty of
old jobs full of COND, so you must be able to read both.
On the job
When someone asks "why didn't step 5 run last night?", open the job
log, find the IEF202I line, then list the RCs of every step before
it and test each against the COND. Nine times out of ten, a
warning RC 4 from a step nobody was watching tripped a (0,NE).
Your task
The payments job has three steps, but right now every step runs every
night. Add COND parameters so that:
| Step | Program | Runs when |
|---|---|---|
VALIDATE |
PAYVAL |
always (it's first) |
POST |
PAYPOST |
VALIDATE ended with RC below 8 |
ALERT |
PAYALERT |
VALIDATE ended with RC 8 or more |
PAYVAL ends with RC 0 when every payment is valid, RC 4 when some are
invalid (the valid ones still get posted), and RC 8 when there is
nothing valid to post.
Don't change the DD statements or the step names. When POST is
skipped, BANK.PAYMENTS.POSTED must not be created.