--------------------------- Week 14-B 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 - Thu Feb 17, 2000 SEE ALSO: Practice Lab #2. --------------------------------------- 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 to change "skip" to "execute"): 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 to change "skip" to "execute"): 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 to change "skip" to "execute"): 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 * or /* needed) - PARM parameters (options) are not used by IDCAMS - IDCAMS always reads a SYSIN dataset to get its options; because, the IDCAMS 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 - 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 - don't waste expensive computer resources (don't bankrupt your boss) 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 ------------------------------------------ For parameters on the EXEC statement, 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; 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 either 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 by any *one* program - NOTE: *not* the total number, only the *maximum* number - NOTE: must be *simultaneous* use by a single *program* - the *maximum* memory used in any one step NOTE: *not* the sum total of all memory, only the *maximum* memory Steps containing programs hidden inside PROCs are considered separate programs 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 internal 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 03F$EX4,'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), // DCB=(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 (only guesses need comments) - 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 about DDname order for programs 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; 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; we are *not* adding it to the whole PROC, only to the GO step - 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, and state which program will detect the 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 - MVS rules! put DDname in PROC step order! //GO.TESTPRT DD SYSOUT=E,HOLD=YES - put simple sysout DD statements first (prefer output before input) - 400 lines for laser printer is still class E - send the output to the laser printer; but, hold for TSO //GO.TESTOUT DD DSN=OUTFILE,DISP=(NEW,PASS), // DCB=(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 Exam Question: How many DDnames are required by the COBOL compiler used in the above step? Answer: 4 (Four) - 3 in the PROC and one from your own JCL: - SYSPRINT - SYSLIB - SYSLIN - SYSIN <-- this one isn't in the PROC; you must supply 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.