--------------------------- Week 15-A Notes for DAT2330 --------------------------- -Ian! D. Allen - idallen@idallen.ca Remember - knowing how to find out the answer is more important than memorizing the answer. Learn to fish! RTFM! (Read The Fine Manual) These notes are largely based on lectures by Harold Smith: - DAT2330 - Harold Smith Class - Wed Feb 23, 2000 --------------------------------------------------------- Today: review the homework - "MVS JCL Example 4 Homework" --------------------------------------------------------- A useful approach to writing JCL on tests: Cross out every line in job specification as you add it to the JCL. Make sure all the lines are crossed out before you hand in your test. Draw a Flow Diagram if you find it useful. (It is never required.) Review ------ What is the difference between a PROC and a program? - proc is a set of JCL (it is text; it can't be executed as machine code) - program is machine code (binary; it can't be included as a PROC) - a PROC contains one or more steps that execute machine code programs Where does MVS find cataloged procedures? - these are specified by saying EXEC PROC= - in SYS1.PROCLIB Where does MVS find binary programs (e.g. IDCAMS, COBOL compiler, linker)? - these are specified by saying EXEC PGM= - in SYS1.LINKLIB How can I make EXEC PGM= find my own program in my own library? - use a JOBLIB or STEPLIB DD statement for your library Coding the JCL for Example 4 Homework ------------------------------------- No guesses were made in coding this job. Where information was missing in the job spec, we could find it by looking it up in the given PROC listing. Step One -------- //COBTSTH4 JOB 04W$HW4,'MY NAME',CLASS=D - CLASS= specifies the JES job queue - this is not a SYSOUT queue - total lines output looks like less than 5000 but more than 500 - we do use tapes - we will be coding a REGION that fits under 100M - based on the job requirements, we choose job CLASS=D Real World Suggestions (these were not given in the job spec): - these are not required on a test or exam; use them on the job if helpful - MSGCLASS= specifies sysout print queue for *JCL/JES* messages only - on the job, always send it to TSO if possible, to class A if not - TSO sysout queue is class D in the job spec: MSGCLASS=D - MSGLEVEL was not specified in job specification, so you can leave it out (use the system default). On the job, code whatever you think is reasonable. Since we already have the PROC listing, it might be better to code MSGLEVEL=(0,1); but, if you send the JCL to TSO using MSGCLASS=D and don't print it, no paper is wasted either way. You choose. //TESTGEN EXEC PGM=TSTGEN,PARM=(PAYROLL,HOURLY) //STEPLIB DD DSN=TEAM1.PVTLIB,DISP=(SHR,KEEP) - program TSTGEN (in step named TESTGEN): - this is a binary program, not a PROC - using your own program to generate test data for another program is common - need to test all your program boundary conditions - real data may not be varied enough for testing - the TSTGEN program uses PARMs for "command line parameters" - PARM always goes on an EXEC statement (after PGM or PROC) - the IDCAMS program uses DDname SYSIN to read its parameters (options) - IDCAMS option lines are "too long" to be written as PARM options - no need to qualify (with a step name) a PARM used on a PGM= - this is not a PROC; there is only one program being executed - there is only one binary program (PGM=) executing in one step here - need to get TSTGEN executable program from a private library - PGM= will look for programs in library given by JOBLIB or STEPLIB - PGM= will find the TSTGEN program in the given STEPLIB library - JOBLIB/STEPLIB libraries contain *executable* modules, not object files - object file libraries are used primarily by link-editors (linkers) - only one program (TSTGEN) comes from the private library of executables - use STEPLIB for the one step, not JOBLIB for the whole job - no need for COND on the EXEC statement of the first step of a job - there is no previous step for COND to check! //TSTOUT DD DSN=GENPAYHR,DISP=(NEW,PASS), // UNIT=DASD,SPACE=(4000,(125,4)) - we choose the output dataset name (this is not a "guess") - output DCB (DSORG, LRECL, BLKSIZE, and RECFM) is fully given in job spec - the TSTGEN program specifies the whole DCB for us - no need for DCB at all in the JCL - the program has it all - don't code things in the JCL that are already correct in the program - calculate SPACE needed for the NEW disk dataset: 10,000 records of 50 bytes each = 500,000 bytes 500,000 bytes divided by 4000 bytes in a block = 125 blocks (primary extent) - no secondary extent size suggested (on the job - ask around) - I picked a number less than 5% (probably won't grow dataset much) - use 10% on tests and exams if it isn't specified - need to specify UNIT because this is an uncataloged dataset Step Two -------- //CLG EXEC PROC=COBOLCLG,COND=(3,LT), - COND defaults to test against return codes of *all* previous steps - there is only one previous step at this point - COND is reversed (SKIP on true) - encode it as follows: English: Execute, provided that the TSTGEN program of the previous step did not set a return code greater than 3." Step 1: execute IF NOT RC > 3 (simplify the English) Step 2: execute IF RC <= 3 (change "NOT >" to opposite "<=") Step 3: execute IF 3 >= RC (swap: put number on left, RC on right) Step 4: skip IF 3 < RC (complement to make into "skip") Step 5: COND=(3,LT) --OR-- Step 1: execute IF NOT RC > 3 (simplify the English) Step 2: skip IF RC > 3 ("execute IF NOT" means "skip IF") Step 3: skip IF 3 < RC (swap: put number on left, RC on right) Step 4: COND=(3,LT) - Check it: decode the COND=(3,LT) back to English as follows: skip IF 3 < RC (turn COND into English) execute IF 3 >= RC (complement "skip" to be "execute") execute IF RC <= 3 (swap to put number on right) execute IF NOT RC > 3 (complement the inequality) Result: "Execute if return code is not greater than 3." - this COND applies to the entire PROC (all the internal steps) - COND: if the condition is TRUE, skip the *whole COBOLCLG proc* // PARM.COB2=(XREF,OBJ), - PARMs could be applied to pass options to any step in a proc - but the job spec says to only affect the compiler step, not all steps - the compiler is always the first step in a C.L.G. PROC - read the PROC to find the EXEC statements for the internal steps - the PROC step COB2 has first EXEC statement in it - this first step (first EXEC statement) must be the compiler - therefore: the compiler executes in PROC step name COB2 - therefore: add the compiler step name suffix to PARM --> PARM.COB2= - job spec says this PARM is to be completely over-riding - no need to copy the other PARM values from the PROC listing - NOTE: Just like DD statements, PARMs and other parameters coded on the EXEC statement must appear in the order that the internal steps appear in the PROC - all the COB2 parameters must come before the LKED parameters before all the GO parameters. // COND.GO=(4,LE,CLG.COB2), - job spec says to execute the GO step only if the compile step (internal PROC step name COB2) sets a code less than 4 - must affect only the GO step in the PROC, not all the steps - we code COND.GO= to set the COND on only the GO step in the PROC - this COND must check the return code from the compile step (only) - don't check all the previous steps (default); only check the compile step - need to code the specific step name to check as: mystepname.procstepname - step name is coded in the COND as: CLG.COB2 - the CLG is my step name; COB2 is the step name in the PROC I am using - COND is reversed (SKIP if true) - encode it as follows: English: Execute only if the compile step sets a condition code of less than 4" Step 1: execute IF RC < 4 (simplify the English) Step 2: execute IF 4 > RC (put the number on the left) Step 3: skip IF 4 <= RC (complement to make into "skip") Step 4: COND=(4,LE,CLG.COB2) (remember the step to test) - Check it: decode COND=(4,LE,CLG.COB2) as follows: skip IF 4 <= RC (write the COND as English) execute IF 4 > RC (complement to make "skip" into "execute") execute IF RC < 4 (swap to put the number on the right) "Execute this step if the return code of step CGL.COB2 is less than 4." // TIME.GO=(,30),REGION.GO=4M,ADDRSPC.GO= - used with a PROC, these EXEC parameters need step name .GO on the end - must affect only the GO step in the PROC, not all the steps - TIME.GO=(,30) or TIME.GO=(0,30) - you can use an explcit 0 minutes or use the default of 0 (leading comma) - remove ADDRSPC if/when you find it (legacy JCL) - specifying an empty value completely removes a parameter //COB2.SYSLIB DD DSN=TEAM1.SRCLIB,DISP=SHR - libraries are usually coded before regular input and output DD statements even though they are input DD statements (this is a style guideline - not a rule) - job spec says to use our own COBOL *source* library - it is the compiler program that will get source from a *source* library - source code is not an executable program - this library is not a linklib-style library of executable programs - source code is not object code - this is not an object library to be linked (not read by the linker) - this library is a library of *source code* - compilers do not read object modules; compilers read source code - Example: C language #include statements include source code - read the given PROC to locate the DDname for the source library: - locate the compiler step in the given PROC - the compiler is always the first step in a C.L.G. PROC - compiler runs in the PROC step named COB2 (read the PROC) - locate the source library DDname in the COB2 compile step - libraries are almost always coded using a DISP of SHR - library has DDname SYSLIB in COB2 step --> we code //COB2.SYSLIB DD to over-ride SYSLIB with our own library - True or False: mis-coding //COB2.SYSLOBXX will cause a run-time error from the COBOL complier saying it can't find DDname "SYSLIB" - Answer: FALSE (the PROC already supplies a SYSLIB for the compiler) The compiler may not find the necessary source code, since it will be reading the PROC-supplied system library and not our own library. The incorrect SYSLOBXX DDname will be ignored by the compiler. //COB2.SYSPRINT DD SYSOUT=D - job spec says hold compiler print output for TSO - to send compiler print output to TSO, we need to over-ride the default SYSOUT queue specification for the compiler set inside the PROC we are using - have to identify the DDname used by the compiler for print output - look in the PROC to find the step name that uses the compiler program - the compiler always runs in the first step in a C.L.G. PROC - we get the compiler step name from reading the PROC: COB2 - look in the COB2 step to discover where the PROC sends compiler output - the SYSOUT DDname for the compiler listing is given there as SYSPRINT - over-ride this SYSPRINT line using //COB2.SYSPRINT in our own JCL - True or False: Coding //COB2.SYSPRXXX will cause a run-time error from the COBOL complier saying it can't find DDname "SYSPRINT" - Answer: FALSE (the PROC already supplies a SYSPRINT for the compiler) The compiler output will appear on in the standard place set by the existing SYSPRINT line in the COB2 step of the PROC. The incorrect SYSPRXXX DDname will be ignored by the compiler. //COB2.SYSIN DD * [...instream COBOL source goes here...] /* - style: we prefer to put instream data last (of all the COB2 DD statements) - True or False: Coding //COB2.SYSXXX will cause a run-time error from the COBOL complier saying it can't find DDname "SYSIN" Answer: TRUE (the given PROC has no default SYSIN DDname in the COB2 step) The incorrect SYSXXX DDname will be ignored by the compiler. //LKED.SYSLIB DD DSN=Y2K.OBJLIB,DISP=SHR - job spec says over-ride (replace) the library used by the link editor - a linker library is not source code - a linker library is not a library of executable programs - a linker library contains object modules for linking into programs - read the given PROC to locate the step and DDname for the linker library - the linker is always the second program in a C.L.G. PROC - step LKED, DDname SYSLIB - we code this over-ride: //LKED.SYSLIB DD - the LKED step over-ride must come *after* the COB2 over-rides and *before* the GO step over-rides (obey MVS step-order rules for PROCs!) - True or False: Coding //LKED.SYSLXXX will cause a run-time error from the IBM Link-Editor saying it can't find DDname "SYSLIB" - Answer: FALSE (the PROC already supplies a SYSLIB for the linker) The linker may not find the necessary object modules, since it will be reading the PROC-supplied system library and not our own library. The incorrect SYSLXXX DDname will be ignored by the linker. //GO.DATOUT DD DSN=PAYHOUR,DISP=(NEW,CATLG), // BLKSIZE=4000,RECFM=FB, // UNIT=DASD,SPACE=(4000,(250,19)) - we choose the output dataset name (this is not a "guess") - catalog this dataset now, since we don't use it later in this job - check the given COBOL source to see what DCB the program specifies - don't specify DCB parameters that the COBOL already specifies - but always code RECFM if you have to code BLKSIZE - int(4K / 100) * 100 = 4000 bytes per block - 10,000 records of 100 bytes each = 1,000,000 bytes 1,000,000 bytes divided by 4000 bytes per block = 250 blocks (primary extent) - secondary extent size was not given; ask around for what to use - on a test/exam code 10% (25 blocks) if not given - I asked around the shop and was told to use 19 blocks //GO.SUMM DD DSN=SUMTAPE,DISP=(NEW,PASS), // BLKSIZE=2000,RECFM=FB, // LABEL=(,AL), // UNIT=TAPES,VOL=SER=123456 - we choose the output dataset name (this is not a "guess") - ANSI label tapes have a maximum 2k (2048 byte) blocksize limit - LRECL is 100 characters (read the COBOL fragment given in job spec.) - int(2K / 100) * 100 = 2000 bytes per block (ANSI) - no SPACE= needed for tapes (only use SPACE for NEW disk datasets) - must specify UNIT and VOL=SER= for uncataloged tapes - pass this uncataloged tape to the next step - coding "KEEP" would cause the tape to be dismounted - since the tape is uncataloged, it would not be found in the next step unless UNIT and VOL/SER were also given there //GO.DATIN DD DSN=GENPAYHR,DISP=(OLD,DELETE) - this is the input dataset PASSed in from the first step - PASSed datasets need nothing except DSN and DISP - job spec says to delete this dataset after its last use Step Three ---------- //SHOWTAPE EXEC PGM=IDCAMS,COND=(0,NE) //SYSPRINT DD SYSOUT=D //OUT DD SYSOUT=(C,,GRLN),COPIES=2 //IN DD DSN=SUMTAPE,DISP=(OLD,KEEP) //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* // - all previous steps must work correctly: calculate COND for this step English: "Execute as long as all previous steps have worked correctly" Step 1: execute IF RC = 0 (reword and simplify the English) Step 2: execute IF 0 = RC (put the number on the left) Step 3: skip IF 0 != RC (complement to make into "skip") Step 4: COND=(0,NE) - PASSed datasets need nothing except DSN and DISP - End of Job. To get a listing of just the JCL from this file, use the Unix command: $ grep '^/' thisfile Notes on Optimal Blocking ------------------------- SMS will let you leave out BLKSIZE if you run SMS in your MVS shop - but not all MVS shops run it! - leave out BLKSIZE only if SMS is running - 4K is a good compromise; but, it isn't always best - want one full track for best disk use - hence, "half-track" blocking is often suggested --------------------------- Extra Questions and Answers related to JCL Example 4 --------------------------- Here are some job specification statements with answers on how to code them. 1) How do I change the compiler output to go to spool queue B? Add this DD statement to our JCL: //COB2.SYSPRINT DD SYSOUT=B We know the step name and SYSPRINT DDname used by the compiler because we can read the PROC listing. (The compiler is always first in a C.L.G. PROC.) Our COB2 DD statement must come before any DD statements for the LKED or GO steps. (DD statements for PROCs must be in PROC step order.) 2) How do I change the linker output to go to spool queue C? Add this DD statement to our JCL: //LKED.SYSPRINT DD SYSOUT=C We know the step name and SYSPRINT DDname used by the linker because we can read the PROC listing. (The linker is second in a C.L.G. PROC.) Our LKED DD statement must come between any DD statements for the COB2 and GO steps. (DD statements for PROCs must be in PROC step order.) 3) How do I delete the REGION specification from the compiler? Add REGION.COB2= (equals nothing) to the EXEC PROC=COBOLCLG statement. This REGION.COB2 must come before any LKED or GO parameters on the EXEC statement for the PROC. 4) How do I change the linker memory to 32MB? Add REGION.LKED=32M to the EXEC PROC=COBOLCLG statement. This REGION.LKED must come between any parameters for the COB2 and GO steps. (Parameters must be in PROC step order.) 5) How do i change the source library used by the compiler to TEAM1.SRCLIB? Add this DD statement to our JCL: //COB2.SYSLIB DD DSN=TEAM1.SRCLIB,DISP=(SHR,KEEP) We know the step name and SYSLIB DDname used by the compiler because we can read the PROC listing. (The compiler is always first in a C.L.G. PROC.) Our COB2 DD statement must come before any DD statements for the LKED or GO steps. (DD statements for PROCs must be in PROC step order.) 6) How do I add the options OPT and LINUX to the linker? The linker (step two in the PROC, with program name IEWL) doesn't currently have any PARM options. Add PARM.LKED=(OPT,LINUX) to the EXEC PROC=COBOLCLG statement. This PARM.LKED must come between any parameters for the COB2 and GO steps. (Parameters must be in PROC step order.) The linker must be coded to read PARM options, otherwise these options will be ignored. 7) How do I add the options NODUMP and NOCHECK to the running COBOL program? The COBOL program (in the GO step) doesn't currently have any PARM options. Add PARM.GO=(NODUMP,NOCHECK) to the EXEC PROC=COBOLCLG statement. This PARM.GO must come after any parameters for the COB2 and LKED steps. (Parameters must be in PROC step order.) The COBOL program must be coded to read PARM options, otherwise these options will be ignored. 8) How do I code: The link-editor step should execute only if all previous steps have no errors? Translate an "execute" into a "skip" using simple steps: Step 1: execute IF RC = 0 (summarize and simplify the English) Step 2: execute IF 0 = RC (put number on left, RC on right) Step 3: skip IF 0 != RC (complement both sides to make into "skip") Step 4: COND=(0,NE) (this is the JCL form of the condition) We are applying this COND to only one of the steps in the PROC, not to all the steps. So we must qualify the COND as COND.LKED so that it gets applied only to the LKED step inside the PROC. The job specification says "all previous steps", so we do *not* use a third parameter to COND.LKED: Add COND.LKED=(0,NE) to the EXEC PROC=COBOLCLG statement. This COND.LKED must come between any parameters for the COB2 and GO steps. (Parameters must be in PROC step order.) 9) How do I code: The link-editor step should execute only if the compiler step has no errors? Translate an "execute" into a "skip" using simple steps: Step 1: execute IF RC = 0 (summarize and simplify the English) Step 2: execute IF 0 = RC (put number on left, RC on right) Step 3: skip IF 0 != RC (complement both sides to make into "skip") Step 4: COND=(0,NE) (this is the JCL form of the condition) We are applying this COND to only one of the steps in the PROC, not to all the steps. So we must qualify the COND as COND.LKED so that it gets applied only to the LKED step inside the PROC. The job specification says "the compiler step" (not "all steps"), so we must use a third parameter to COND.LKED to specify that only the compiler step should be tested: Add COND.LKED=(0,NE,CLG.COB2) to the EXEC PROC=COBOLCLG statement. CLG is the name we gave (see the JCL, above), in our JCL, to the step using the COBOLCLG PROC. (CLG identifies which PROC we are talking about.) COB2 is the internal step name, inside the COBOLCLG PROC, that our COND should check. This COND.LKED must come between any parameters for the COB2 and GO steps. (Parameters must be in PROC step order.) *** FIN *** EOF *** END OF DAT2330 JCL NOTES *** EOF *** FIN ***