Week 14 Notes for DAT2330 - Ian Allen Supplement to Text, outlining the material done in class and lab. Remember - knowing how to find out the answer is more important than memorizing the answer. Learn to fish! RTFM![*] ([*] Read The Fine Manual) ==================================== MVS - O/S 390 - Job Control Language ==================================== -IAN! idallen@ncf.ca July 2001 These notes are largely based on lectures by Harold Smith: - DAT2330 - Harold Smith Class - Thu Feb 17, 2000 Notes on Winter 2000 Lab assignment #2 -------------------------------------- This description and JCL from last year was provided as an extra example for this term, to give you more practice at reading JCL job descriptions. - input datasets never need DCB (DCB is in the dataset label) - cataloged datasets never need UNIT or VOL (just DSN and DISP) - passed datasets don't need anything other than DSN and DISP - ANSI tapes always need LABEL the *first* time you access them in a JOB - PASSed datasets (including PASSed ANSI tapes) only need DSN and DISP - when calculating SPACE, make sure you round UP when dividing the size of the data by the block size - if you don't, your data will use up one secondary extent for the partially filled block - choosing your own job and step names is not "guessing"; it is *choosing* - you can't pick wrong job or step names, only bad names - choosing output dataset names is not "guessing"; it is *choosing* - you can't pick a wrong output dataset name, only a bad dataset name - there is only one *guess* in lab2: the DDname for the output labels - if this guess is wrong, the job will fail at run time - document your guesses using JCL comments - use your best estimate when you don't know what to code for secondary extents - estimate how this will dataset grow in future - a known-size, one-shot dataset won't grow; code conservatively - datasets that will grow need more liberal space allocation - watch out for the limit on secondary extents: 15 (unless using SMS) --------------------------------------- MVS JCL Example 4 and attached homework --------------------------------------- Review of Virtual Memory concepts (for new REGION parameter) - jargon: Unix/Microsoft => swap file; MVS => page dataset - page fault - least recently used (LRU) - dirty bits (can't throw away changed pages) - working set - amount of memory required by a program while it *runs* - usually smaller (maybe much smaller) than entire occupied address space - thrashing - too much paging - probably too many programs in real memory - don't make I/O buffers "a little bigger" than 4k (wastes space) - I/O buffers should fit *inside* the 4K block New Parameters -------------- For //stepname EXEC ... COND= PARM= REGION= TIME= New item: specifying STEPLIB after an EXEC statement. New item: specifying JOBLIB after a JOB statement. Details: COND= - this is the most complex JCL parameter to learn - most shops now have IF/THEN/ELSE; but, you can learn that on your own - you will encounter legacy JCL or shops without IF/ELSE - specifies to check the return code of some previous step(s) - step return codes of zero are successful (just like Unix) - non-zero is bad, bigger numbers are worse (similar to Unix) - msglevel=(1,1) shows return codes in the JES/JCL listing - never use COND on the first step of a job (nothing to check!) - COND on an EXEC statement skips a step if the given condition is true - COND applied to a PROC step skips the whole PROC (all the internal steps) - *** NOTE ***: the condition code is reversed from what you expect - true condition of COND means *skip* the step - false condition of COND means *execute* the step - if you don't specify which step's return code to test, COND tests the return code of *all* the previous steps - Example: COND=(0,NE) COND translation: IF 0 is != to the return code of any previous step THEN skip this step Simpler English (apply negation to both sides): IF 0 is = to the return code of every previous step THEN execute this step Simpler English (switch the clauses): IF the return code of every previous step is = to 0 THEN execute this step - Example: COND=(4,LE) COND translation: IF 4 is <= the return code of any previous step THEN skip this step Simpler English (apply negation to both sides): IF 4 is > the return code of every previous step THEN execute this step Simpler English (switch the clauses): IF the return code of every previous step < 4 THEN execute this step - Example: COND=(3,LT) COND translation: IF 3 is < the return code of any previous step THEN skip this step Simpler English (apply negation to both sides): IF 3 is >= the return code of every previous step THEN execute this step Simpler English (switch the clauses): IF the return code of every previous step <= 3 THEN execute this step - reverse the logic to construct a JCL COND parameter: Step 1: "execute if return code is >= 5" Step 2: "execute if 5 <= return code" Step 3: "skip if 5 > return code" Step 4: COND=(5,GT) PARM= - use PARM to pass parameters (options) to an executing program (PGM=) - is used by programs that have small amounts of data to pass in - simpler to use than instream data (no DD * needed) - PARM parameters (options) are not used by IDCAMS - IDCAMS always reads SYSIN dataset to get its options - why are there two ways of specifying options to programs? - PARM is slightly more efficient than DD (no dataset needed) - but: long PARM makes for very long JCL lines (may be hard to read) - therefore: PARM is used for "short" options; DDnames for "long" options - IDCAMS has a lot of options: uses SYSIN DDname to read "long" options Using PARM with a PROC: - your JCL may over-ride an existing PARM= contained in a step inside a PROC - how do you specify which step inside the PROC to over-ride? - specify a step name *after* the word PARM: PARM.COB2=, PARM.LKED=, PARM.GO=, etc. - an over-ride means *throwing away* existing PARM options - no way to say "add this PARM to the existing PARM in the PROC" - you have to copy existing options out of the proc into your own JCL if you want to *add* your own PARM options - you must be able to read a PROC to do this correctly - just like DD statements, PARMs must appear in the order that the internal steps appear in the PROC (text p.249) - all the COB2 PARMs must come before the LKED PARMs before all the GO PARMs. REGION= - the amount of memory the program in this step requires - why would one want a *smaller* virtual memory address space? - smaller page tables - 16 terabytes mapped out in page tables is big! - limit damage done by looping requests for memory - cut off requests for memory above a limit TIME= - limit the CPU time of the step - e.g. of your runaway program - probably not useful on steps that execute system utilities - the utility isn't likely to have a bug that will loop Applying parameters to steps inside a PROC ------------------------------------------ Unlike DDnames, the stepname for a parameter variable over-ride (e.g. PARM=, TIME=, etc.) comes *after* the parameter name! Remember the two different orders for over-riding things in PROCs: * PROC DDnames put the step name *before* the DDname: DDnames: //COMP.SYSIN, //LKED.SYSLIB, //GO.TAPEOUT, etc. * PROC parms put the step name *after* the parm name: Parameters: PARM.COMP=, REGION.LKED=, TIME.GO=, etc. Just like DD statements, PARMs must appear in the order that the internal steps appear in the PROC (text p.249) - all the compile PARMs must come before the link PARMs before all the go PARMs. Choosing a JOB CLASS= --------------------- You must code the CLASS= parameter on the JOB statement based on the expected resources used by your job. Depending on the resource limits of your job classes, chosing a job CLASS is determined by ether the *maximum* or the *total* resources used by your job. CLASS is determined by: - the sum *total* number of print (SYSOUT) lines, in all steps, no matter whether the lines are sent to a real printer or back to you via to TSO - the sum *total* amount of computer time used, in all steps - the *maximum* number of tape drives being used simultaneously in any *one* step - NOTE: *not* the total number, only the *maximum* number - the *maximum* memory used in any one step NOTE: *not* the sum total of all memory, only the *maximum* memory Steps hidden inside PROCs are considered separate steps for these calculations - don't add up all the tapes inside a PROC and count them all as required in "one" step! Keep all the steps separate. Specifying STEPLIB (or JOBLIB) ------------------------------ STEPLIB says where PGM= in a step should look for a program - similar to Unix search path (environment variable $PATH) JOBLIB does the same, but for *all* the steps in the *whole* JOB - choose JOBLIB if you find you're coding the same STEPLIB in all steps Why use step or job libraries? - because you can't put your team's stuff in the system library - you need to add your library to the libraries searched by PGM= Coding the JCL for Example #4 ----------------------------- This is a three-step job: one IDCAMS, one CLG proc, one private program How can you look at the contents of a system PROC? - you could list a dataset in the library SYS1.PROCLIB using TSO or IDCAMS - you could use MSGLEVEL=(1,0) to list the contents of all PROCs used Look at the given PROC listing for this example: - first PROC step is compile (COB2) - COB2.SYSLIB is a library of COBOL source (COBOL.SRCLIB) - compilers read source code - second PROC step is is link (LKED) - LKED.SYSLIB is a library of object modules (compiled code) - linkers read object code modules - third PROC step executes my program (GO) - third step loads my linked program and runs it Know how to read a JCL refer-back: - no DSN given for COB2.SYSLIN output DDname (!) - system invents a temporary DSN - next step "refers back" to temp name using: DSN=*.COB2.SYSLIN - referback means: "use the same dataset that was specified in step COB2 using DDname SYSLIN" - GO step uses referback too: PGM=*.LKED.SYSLMOD - referback means: "use the same dataset that was specified in step LKED using DDname SYSLMOD" - DNS=&&GOSET(GO) means a temporary partitioned dataset (DSORG=PO) - partitioned datasets (DSORG=PO) not covered in this course - you can only refer back to a dataset in the current job! What is the maximum size of the compiler output object file? - maximum size is limited by number of extents allowed - output is on COB2.SYSLIN (the only non-sysout output file!): - check the SPACE specifications in the PROC - primary extent: 100 blocks of 4080 bytes - secondary extents: 15 times 100 blocks (of 4080 bytes) = (100 * 4080) + (15 * (100 * 4080)) = 6,528,000 bytes - SMS increases number of extents to over a hundred What is the maximum size of the linker output executable program? - maximum size is limited by number of extents allowed - output is on LKED.SYSLMOD (the only non-sysout output file!): - check the SPACE specifications in the PROC - primary extent: 500 blocks of 1024 bytes - secondary extent: 100 blocks of 1024 bytes = (500 * 1024) + (15 * (100 * 1024)) = 2,048,000 bytes - SMS increases number of extents to over a hundred In which sysout queue will I see my errors if I misspell things? e.g. mis-spell: PRTY, REPRO, COBOL code, linker SYSLIB ? - PRTY -> JCL error -> JCL sysout queue is set by MSGCLASS= - REPRO -> IDCAMS run-time error -> IDCAMS output //SYSPRINT DD SYSOUT= - COBOL code -> compiler run-time error -> compiler //SYSPRINT DD SYSOUT= - SYSLIB -> linker run-time error -> linker output //SYSPRINT DD SYSOUT= Step One -------- //CBLTSTE4 JOB 4000EX,'MY NAME',CLASS=E,MSGCLASS=D, // MSGLEVEL=(0,1),TYPRUN=SCAN - need low-priority class E to handle large volume of print lines - may as well turn off proc listing (not specified) - Real World Suggestion: - JCL scan (TYPRUN=SCAN) a class E job first, since it may wait a long time - don't want to wait for a day and then have the job fail - I code the TSO hold queue for MSGCLASS (not specified) so I can look at the JCL listing via TSO //MAKEDATA EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=D //OUT DD DSN=TESTDATA,DISP=(NEW,PASS), // BLKSIZE=4080,RECFM=FB, // UNIT=DASD,SPACE=(4080,(20,5)) - we choose the output dataset name (not given in job spec) - IDCAMS defaults DSORG and LRECL to be same as input DCB; both are ok - need bigger output block size to avoid poor disk utilization - int(4K / 80) * 80 = 4080 optimum disk block size - must code SPACE for a new output DASD (disk) dataset - job spec says 1000 records (of 80 bytes each) 1000 * 80 = 80,000 bytes of data 80,000 / 4080 = 20 (round UP!) blocks for primary extent estimate 5 blocks for each secondary extent (best estimate of growth) - use TSO hold class for IDCAMS status/error messages (not specified) //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* //IN DD * [...1000 records of instream test data go here...] /* - put small instream before large instream - this is style: MVS doesn't care Second Step ----------- See descriptions of New Parameters: COND, PARM, REGION, TIME //CLG EXEC PROC=COBOLCLG,COND=(0,NE), COND= - this step depends on the success of the previous step (IDCAMS) - IDCAMS might fail (memory error, typing error, JCL error, etc.) - this COND applies to the entire proc (skips the whole CLG step) - this COND checks *all* previous steps (but there is only one) - unspecified step means test the return code of any (all) previous steps - "is zero not equal to the condition code of any previous step"? - condition is reversed - true means skip the step, false means execute - COND translation: IF 0 is != to the return code of any previous step THEN skip this step Simpler English (apply negation to both sides): IF 0 is = to the return code of every previous step THEN execute this step Simpler English (switch the clauses): IF the return code of every previous step is = to 0 THEN execute this step // PARM.COB2=(XREF,LIST,OBJ), PARM= - job spec says to add XREF to existing PARM= list for compiler only - do not add it to all the steps in the PROC, just the compiler step - look at the PROC: the compiler step is named COB2 - must copy existing options out of PROC and add our own - look in PROC and find PARM=(LIST,OBJ) in COB2 step - copy these two PARMs to our new PARM to make three - this only works if the compiler was written to read PARMs for options - compiler could be written to read options from, say, DDname SYSIN2 - author of program decides which way to do it (PARM vs. DDname) - the .COB2 is necessary to tell the JCL in which step to use the PARM - NOTE: Just like DD statements, PARMs must appear in the order that the internal steps appear in the PROC (text p.249) - all the COB2 PARMs must come before the LKED PARMs before all the GO PARMs. // TIME.GO=(1,30), - spec says to limit time of test step to 1 min 30 secs - the .GO is necessary to tell the JCL in which step to use the TIME - leaving off .GO step will limit time of *whole* proc (not each step) // REGION.GO=64M, - the .GO is necessary to tell the JCL in which step to use the REGION - look inside proc listing and see REGION=1024k (1MB) on the GO step - job spec says my program requires 64MB of virtual memory - need to over-ride this REGION parameter on the GO step in my own JCL // ADDRSPC.GO=, - locks your program in to real memory (displacing other jobs) - does so even if operator goes for coffee and your program waits! - OK for time-critical programs that can't wait for paging - usually something to remove if you find it - nullifying a parameter means setting it empty - the .GO is necessary to tell the JCL in which step to use the ADDRSPC // COND.GO=(4,LT,CLG.COB2) - the .GO is necessary to tell the JCL in which step to use the COND - this COND.GO affects only the COND of the GO step inside the COBOLCLG PROC - my program (the one I am compiling and linking) runs in the GO step - this COND depends on the return code of step COB2 in the PROC that is executed in our step named CLG - this is written as: CLG.COB2 (mystepname.procstepname) - the CLG.COB2 step is the compile step inside the PROC - therefore: this COND determines whether the program in the GO step of this procedure (our compiled program) will run, based on the return code of the program in internal step COB2 of step CLG (the compiler). - the COND conditions are reversed: IF 4 is < the return code of the compiler THEN skip this step Simpler English (apply negation to both sides): IF 4 is >= the return code of compiler THEN execute this step Simpler English (switch the clauses): IF the return code of compiler <= 4 THEN execute this step //* DDNAME SYSIN IS A GUESS. IT WAS NOT IN THE SPECIFICATIONS. //* THE COMPILER IS AN IBM PROGRAM; IT ALMOST CERTAINLY READS FROM SYSIN. //* AN INCORRECT GUESS HERE WILL PRODUCE A RUN-TIME ERROR //* (WHEN THE COMPILER RUNS AND CANNOT FIND THE RIGHT DDNAME). //COB2.SYSIN DD * [...COBOL source goes here...] /* - use JCL comments to document your guesses on tests and exams - JCL comments can be mixed case; they don't have to be UPPER CASE - always state whether an incorrect guess will cause a JCL error or a run-time error //LKED.SYSLIB DD DSN=TEAM1.MODLIB,DISP=(SHR,KEEP) - job spec says to change library to TEAM1.MODLIB - share it and KEEP it! - the LKED proc step over-ride must appear *after* COB2 and *before* GO //GO.TESTPRT DD SYSOUT=A,DEST=MVS1.LESLIE - put simple sysout DD statements first (prefer output before input) - 400 lines is still sysout class A //GO.TESTOUT DD DSN=OUTFILE,DISP=(NEW,PASS), // BLKSIZE=4000,RECFM=FB, // UNIT=DASD,SPACE=(4000,(125,10)) - we choose the output dataset name (not given in job spec) - can't catalog this dataset yet; we need it next step - read COBOL source to find the DDname TESTOUT - don't specify DCB parameters already given in the COBOL program - choose best block size for output medium (4K maximum block size) - calculate SPACE primary extent using 5000 records of 100 bytes - 500,000 / 4000 = 125 blocks primary - estimate 10 blocks for each secondary extent (not specified) //GO.TSTIN DD DSN=TESTDATA,DISP=(OLD,KEEP) - job spec doesn't say what to do with this dataset - do the safe thing; KEEP it Third Step ---------- //VIEWDATA EXEC PGM=PGMVIEW,COND=(4,LE) //STEPLIB DD DSN=TEAM1.LINKLIB,DISP=(SHR,KEEP) //OUTPUT DD SYSOUT=D //INPUT DD DSN=OUTFILE,DISP=(OLD,CATLG) - STEPLIB says where PGM= should look for the non-system program PGMVIEW - we look for PGMVIEW in the private TEAM1.LINKLIB program library - similar to Unix search path (environment variable $PATH) - D is the sysout TSO hold queue - a passed dataset needs nothing but DSN and DISP - we were told to catalog this dataset - COND: job spec: "execute if previous return codes are not 4 or more" Step 1: "execute if return code is < 4" Step 2: "execute if 4 > return code" Step 3: "skip if 4 <= return code" Step 4: COND=(4,LE) - decoding: the COND conditions are reversed: IF 4 is <= the return code of any previous step THEN skip this step Simpler English (apply negation to both sides): IF 4 is > the return code of every previous step THEN execute this step Simpler English (switch the clauses): IF the return code of every previous step < 4 THEN execute this step // End of job. To get a listing of just the JCL from this file, use the Unix command: $ grep '^/' thisfile Do the "MVS JCL Example 4 Homework" question; we will review it next class.