Week 14-B 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 Spring 2002 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) - only use DCB for a NEW dataset that doesn't have a DCB - cataloged datasets never need UNIT or VOL (just DSN and DISP) - only need UNIT (and maybe VOL) for uncataloged datasets - 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 final block the first time the dataset is written - 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 - HOWEVER: you must obey the JCL syntax rules (8 chars or less) - choosing output dataset names is not "guessing"; it is *choosing* - you can't pick a wrong output dataset name, only a bad dataset name - HOWEVER: you must obey the JCL syntax rules (8 chars or less) - 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 - the job spec says to over-ride the SYSPRINT destination for the compiler with our own SYSPRINT DD statement that holds the output for TSO - this is an "over-ride"; it replaces the existing SYSPRINT DD statement in the PROC - we can only do this if we know the step name and DDname in the PROC that we want to over-ride - calculate the best block sizes for the output datasets - block size was *NOT* set in the COBOL program; must be in the JCL - only specify DCB info that is missing or is different from that set by the program creating the dataset - the job spec says the combined record length written to datasets TESTOUT and DATABACK is the sum of the lengths of the input datasets; so the combined LRECL is the sum 155+90=245 bytes - job spec says this LRECL is set by the executing COBOL program; therefore, do *NOT* specify LRECL=245 in the JCL - choose a correct BLKSIZE parameter for records of 245 bytes: - standard blocksize (max 4K): integer(4094/245)*245=3920 - BLKSIZE=3920 for the output disk dataset - ANSI blocksize (max 2K): integer(2048/245)*245=1960 - BLKSIZE=1960 for the output ANSI tape dataset - calculate the SPACE parameter for disk dataset TESTOUT - block size for a disk is always the IBM standard, max 4K - we calculated (above) BLKSIZE=3920 for LRECL=245 - we have about 6000 records of 245 bytes ==> 1,470,000 bytes of data 1,470,000 bytes divided by 3920 = 375 blocks (of 3920 bytes) primary extent is 375 blocks - NOTE: always round up any fraction for SPACE - secondary extent size is given as 10% of 375 blocks ==> 38 blocks - NOTE: always round up any fraction for SPACE - SPACE=(3920,(375,38)) - use your best estimate when you don't know what to code for secondary extents - estimate how this will dataset grow in future - on the job, ask around for how fast the dataset grows - a known-size, one-shot dataset won't grow; code conservatively - make the secondary extents small - datasets that will grow a lot need more liberal space allocation - make the secondary extents larger - watch out for the limit on secondary extents: 15 - if your shop uses the Storage Management Subsystem (SMS), you get over a hundred secondary extents - we do not use SMS in this course; always assume a limit of 15 - Exercise: calculate the maximum size of the $CHOOSE1 dataset // SPACE=(4030,(231,10)) - maximum size is 1 primary extent of 231 blocks plus 15 secondary extents of 10 blocks each (each block is 4030 bytes) Answer: (231+(10*15)) blocks of 4030 bytes = 381 blocks of 4030 bytes = 1,535,430 bytes - Exercise: calculate the maximum size of the $CHOOSE2 dataset // SPACE=(4050,(134,10)) - maximum size is 1 primary extent of 134 blocks plus 15 secondary extents of 10 blocks each (each block is 4050 bytes) Answer: (134+(10*15)) blocks of 4050 bytes = 284 blocks of 4050 bytes = 1,150,200 bytes - Exercise: calculate the maximum size of the TESTOUT dataset // SPACE=(3920,(375,38)) - maximum size is 1 primary extent of 375 blocks plus 15 secondary extents of 38 blocks each (each block is 3920 bytes) Answer: (375+(38*15)) blocks of 3920 bytes = 945 blocks of 3920 bytes = 3,704,400 bytes - Exercise: calculate the maximum size of the DATABACK dataset Answer: unlimited (this is a tape dataset; SPACE is not used and you can write as many tapes as you can pay for) How many programs will execute in this job? Answer: Six. IDCAMS, IDCAMS, compiler, linker, cobol executable, IDCAMS --------------------------------------- MVS JCL Example 4 and attached homework --------------------------------------- Review of Virtual Memory concepts (for new REGION parameter) - jargon: Unix/Microsoft => swap file; MVS => page dataset - review: page fault - review: 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= - COND specifies to check the return code of some previous step(s) and skip execution of this step if the given condition is true - 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 much legacy JCL without IF/ELSE - program/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 program return codes in the JES/JCL listing - if you don't specify which step's return code to test, COND tests the return code of *all* the previous steps - never use COND on the first step of a job (nothing to check!) - COND applied to a PROC step skips the whole PROC (all the internal steps) - NOTE: the COND condition code is reversed from what you expect - true condition of COND means *skip* the step - false condition of COND means *execute* the step - 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 steps to construct a JCL COND parameter from a job spec: English job spec: Execute this step if the return code of every previous step is greater than or equal to five. Step 1: "execute if return code is >= 5" (summarize the English) Step 2: "execute if 5 <= return code" (swap the clauses) Step 3: "skip if 5 > return code" (negate both sides) Step 4: COND=(5,GT) (code it) PARM= - use PARM to pass parameters (options) to an executing program - PARM 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 a SYSIN dataset to get its options; because, the options can be many many lines - too long for a PARM - 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 compound PARM name, using a step name *after* the word PARM: PARM.COB2=, PARM.LKED=, PARM.GO=, etc. - Note: this is backwards from the way compound DDnames are constructed: COB2.SYSIN, LKED.SYSLIB, GO.INPUT, etc. - a PARM over-ride means *throwing away* existing PROC 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, where the stepname comes *before* the period and the program DDname, 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 gives the dataset name of a library where the EXEC statement should search for the program name given after the PGM= keyword - 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 programs in the default system library that is searched by EXEC (SYS1.LINKLIB) - 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; some compilers have source libraries - second PROC step is is link (LKED) - LKED.SYSLIB is a library of object modules (compiled code) - linkers read object code modules and link them with libraries - third PROC step executes my program (GO) - the 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 for you - 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 (15) - output is on COB2.SYSLIN (the only non-sysout output file!): - check the SPACE specifications in the PROC: SPACE=(4080,(100,100)) - 1 primary extent: 100 blocks of 4080 bytes - 15 secondary extents: 15 times 100 blocks of 4080 bytes = 1 * (100*4080) plus 15 * (100*4080) = (1+15) * (100*4080) = 16 * 408000 = 6,528,000 bytes What is the maximum size of the linker output executable program? - maximum size is limited by number of extents allowed (15) - output is on LKED.SYSLMOD (the only non-sysout output file!): - check the SPACE specifications in the PROC: SPACE=(1024,(500,100,1)) - 1 primary extent: 500 blocks of 1024 bytes - 15 secondary extents: 15 times 100 blocks of 1024 bytes = 1 * (500*1024) plus 15 * (100*1024) = (500+(100*15)) * 1024 = 2,048,000 bytes In which sysout queue will I see my errors if I misspell things? e.g. mis-spell: PRTY, REPRO, some COBOL code, linker SYSLIB ? - PRTYX -> JCL error -> JCL sysout queue is set by MSGCLASS= - REPROX -> IDCAMS run-time error -> IDCAMS output //SYSPRINT DD SYSOUT= - COBOL code -> compiler run-time error -> compiler //SYSPRINT DD SYSOUT= - SYSLIBX -> linker run-time error -> linker output //SYSPRINT DD SYSOUT= Step One -------- //CBLTSTE4 JOB 4000EX,'MY NAME',CLASS=E - need low-priority class E to handle large volume of print lines - 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 - turn off unnecessary proc listing (we already have the proc listing!) - add MSGLEVEL=(0,1) - 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 for a JCL error - code the TSO hold queue for MSGCLASS so I can look at the JCL listing via TSO instead of getting hard copy //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 (it was not given in job spec) - a choice does not need a comment - use TSO hold class for IDCAMS status/error messages - this information was not given in the job spec; choose something - you could also use SYSOUT queue "A" (not many lines) - IDCAMS defaults output DCB to be the same as the input DCB - DSORG and LRECL are correct; do not specify them in the JCL - need bigger output block size to avoid poor disk utilization - int(4K / 80) * 80 = 4080 optimum disk block size - always specify RECFM with BLKSIZE - 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 (always round UP!) blocks for primary extent estimate 5 blocks for each secondary extent (best estimate of growth) //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* //IN DD * [...1000 records of instream test data go here...] /* - put small instream data before large instream data - 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= - job spec says 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) - translate the English job spec into a COND statement carefully: Engl: "execute as long as every previous step has executed with no errors" Step 1: "execute if return code is = 0" (summarize the English) Step 2: "execute if 0 is = return code" (swap the clauses) Step 3: "skip if 0 is != return code" (negate both sides) Step 4: COND=(0,NE) (code it) Result: "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 back into English (to verify): 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 compiler PARM 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 the one 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=, - this is legacy JCL that should be removed - locks your program into 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 (as above) - the .GO is necessary to tell the JCL in which step to use the ADDRSPC // COND.GO=(4,LT,CLG.COB2) - job spec says that the test step in the PROC (named GO) should be executed only if the compile step in the PROC (named COB2) sets a condition code of 4 or less - we must add a COND parameter to the GO step in the PROC - 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). - translate the English job spec into a COND statement carefully: English: "execute only if condition code is 4 or less" Step 1: "execute if return code is <= 4" (summarize the English) Step 2: "execute if 4 is >= return code" (swap the clauses) Step 3: "skip if 4 is < return code" (negate both sides) Step 4: COND=(4,LT,CLG.COB2) (code it) Result: "is 4 less than the return code of the CLG.COB2 step"? - condition is reversed - true means skip the step, false means execute - COND translation back into English (to verify): 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 Next come all the DD statements for this procedure, in PROC order. //* 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 - DAT2330 Winter 2002 does not cover the DEST= parameter; omit it. //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 the given COBOL source to find the 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) - NEW disk datasets also need SPACE as well as DCB info - calculate SPACE primary extent using 5000 records of 100 bytes - 5000 records of 100 bytes is 500,000 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 EXEC 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) - if STEPLIB is not used, EXEC looks for programs in SYS1.LINKLIB - D is the sysout TSO hold queue - a passed dataset needs nothing but DSN and DISP - we were told to catalog this dataset - translate the English job spec into a COND statement carefully: English: "execute as long as no previous step has set a condition code of 4 or more" Simplify: "execute if no condition code >= 4" Simplify: "execute if condition code < 4" Step 1: "execute if return code is < 4" (summarize the English) Step 2: "execute if 4 is > return code" (swap the clauses) Step 3: "skip if 4 is <= return code" (negate both sides) Step 4: COND=(4,LE) (code it) Result: "is 4 less than or equal to the return code of any previous step"? - condition is reversed - true means skip the step, false means execute - COND translation back into English (to verify): 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.