Week 12 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 - Wed Feb 3, 2000 --------------------------------------- MVS JCL Example 2 and attached homework --------------------------------------- Using IDCAMS ------------ - what are the IDCAMS control statements used for? - tell the IDCAMS program what to do - chooses among many possible options - similar to command line arguments and flags - IDCAMS could take parameters; but, there are too many - instead, read a dataset containing the options - dataset always comes on DDname SYSIN - we usually write JCL to make SYSIN connect to instream data - real-world use may have 10-15 lines of control statements - what DDnames are used in the copy (IBM calls it "REPRO") step? - you get to pick the two DDnames used by IDCAMS - the two DDnames are given in the IDCAMS "REPRO" control statement - IDCAMS will expect to find those two DDnames in the JCL - if you make a spelling error, you won't know until IDCAMS runs - IDCAMS prints a report of what it did (or did not do) on DDname SYSPRINT - real-world use would probably be to hold this for TSO viewing - make sure the operation worked Review: Compile, Link, and Go ----------------------------- - what step name and DDname is needed for the instream COBOL source program? - not specified in the job specifications - we have to ask or guess - choosing the right step name is a JCL issue - choosing the right DDname within the step is a run-time issue - to see the step name, we will need to set MSGLEVEL to get maximum JCL information about the proc printed from our test run - we want to see the JCL inside the proc, to see the step names hiddin therein - running the compiler will tell us what the correct DDname is - we guess at "COMP" for the step and "SYSIN" for the DDname: COMP.SYSIN - the "COMP" part of the name was chosen by the author of the COBOLCLG proc - the "SYSIN" part of the name was chosen by the author of the COBOL compiler program itself - since the compiler is an IBM utility, we guess at "SYSIN" - guessing the wrong step name will generate a JCL error - guessing the wrong DDname will generate a run-time error from the compiler - what part of our CLG job wants to read dataset TAPEDATA? - not the compiler (review: what does compiler do) - not the linker (review: what does linker do) - must be the "go" step (where my compiled program executes) - what is the internal step name of this "go" step in the COBOLCLG proc? - what internal step name is used in the COBOLCLG proc to execute my program? - not specified in the job specifications - we have to ask or guess - set MSGLEVEL to display contents of proc and then run the job - guessing the wrong step name will generate a JCL error - JCL listing will show proc, from which we can read the right step name - fix the JCL and resubmit Note that you can't "watch the program run" as you do with Unix, Windows - batch programming only - prepare the JCL and send it off - it works or fails! New Parameters -------------- New keyword parameters for the JOB card: - MSGCLASS=, MSGLEVEL=, PRTY=, TYPRUN= MSGCLASS (p.69) - specifies which sysout spool queue to use for JES/JCL messages - installation default usually sends output to queue for the "A" printer - may need to spool to TSO queue (especially if we know job will fail) - choose letter closest to A for best turn-around time - we choose sysout class "dog" ("D") for this job because we know the job will fail (because we are guessing at some step and DDnames) MSGLEVEL (p.74) - level of JOB processing detail coming from JES and JCL - this does not affect output from any programs run by the JCL - default is set by each MVS shop (differs from shop to shop) - (1,1) is maximum (uses positional parameters) - (,1) means use default for 1st parameter (see Chapter 4 syntax) - we choose verbose level (1,1) so that we see proc listing - we could use (1,0) and still would see the proc listing - once we know the correct proc step names, we can choose the bare minimum set out in the first paragraph of the job specification: (0,0) PRTY (p.292) - choose your priority among various CLASS= jobs - not strictly FIFO - actual value depends on MVS version, e.g. 0 to 14 or 15, with 15 highest - some account codes cannot use some priorities - some priorities may increase the cost of your job run - we are asked to choose a "medium-high" priority: e.g. 11 (out of 15) TYPRUN (p.75) - SCAN: used to scan JCL for JCL errors (verify correct JCL) - the job is not actually run - HOLD: can be used to hold a job in the input queue - the job is not run until released - need to use this for the homework JCL assignment New keyword parameters for the DD card: - DCB=(DSORG=,LRECL=,BLKSIZE=,RECFM=) - LABEL=(,AL) - UNIT= - VOL=SER= (see the text; all are described in the commentary below) Detecting Errors ---------------- There are two major types of errors: JCL errors and run-time errors. - coding TYPRUN=SCAN will not find run-time errors - it only finds errors in the JCL, not in the instream data JCL Errors: - syntax errors; misspelled JCL parameters; etc. - a wrong step name in a compound DDname when using a proc is a JCL error - the JCL processor detects that your step name doesn't match any step name in the proc when it fetches the proc from SYS1.PROCLIB Run-Time Errors: - you have to *run some program* to detect an input or DDname error - run the compiler; run IDCAMS; run your COBOL program; etc. - run-time error: IDCAMS control statement errors (input error) - run-time error: errors in spelling of DDnames - instream data (including IDCAMS instream control statements) are not subject to JES or JCL rules or syntax checking - instream data is not read by the JCL processor; it cannot cause a JCL error - instream data is read by some *program*, and only when the program *runs* - instream data can only cause run-time errors - a wrong DDname is a run-time error, not detected by the JCL processor - you must run the program to have the program look for its DDnames Coding the JCL for Example #2 ----------------------------- - UPPER CASE ONLY, etc. - continuation lines: start with "// ", indent to 16 or less. - remember the trailing commas on lines being continued - one missing comma throws the job out - don't indent past column 16 - some posted examples violate this rule so that they read more clearly to the novice eye - don't code this way! - review previous examples Step One -------- In what order do we write DD statements? - output before input (but obey MVS rules for proc's) - professors want instream DD statements last - put biggest instream last Title comments have been omitted from this JCL to keep it short. Guesses are documented using comments before the associated statement. Commentary is listed after the step: //* NOTE: I AM USING MSGLEVEL=(1,0) BECAUSE OF GUESSES IN STEP TWO. //* WHEN THE JOB IS WORKING, I WILL CHANGE IT TO MSGLEVEL=(0,0). //* I ALSO USE THE 'HOLD' QUEUE (MSGCLASS=D) BECAUSE OF THE GUESSES. //* WHEN THE JOB IS WORKING, I WILL DELETE MSGCLASS AND LET IT PRINT. //CBLTSTE2 JOB 2000EX,'MY NAME',CLASS=D, // MSGCLASS=D,MSGLEVEL=(1,0), // PRTY=11 //MAKETAPE EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=D //OUTDD DD DSN=MYTSTDAT,DISP=(NEW,PASS), // DCB=(DSORG=PS,LRECL=80,BLKSIZE=4080,RECFM=FB), // UNIT=SCRATCH //SYSIN DD * REPRO INFILE(INDD) OUTFILE(OUTDD) /* //INDD DD * ... Many test records go here. The syntax of these lines is dictated ... by the input requirements of the COBOL program reading them. /* - style: choose a good job name and step name - JOB CLASS= - this job class is not a sysout print queue class! - job classes change from MVS shop to MVS shop - and from example to example and from test to test - check the list of classes specified for this example - based on resource needs, we choose class "dog" ("D") for this job - JOB MSGCLASS= - this job class *is* a sysout print queue class (for the JCL listing)! - we are going to ask to hold the JCL listing for viewing by TSO; because, we are making some (probably wrong) guesses at step and DDnames - the hold queue class is "D" for this example - when the job is working, we can let it print (remove MSGCLASS) - MYTSTDAT: we choose an output dataset name for the new temporary tape - DCB parameter block describes the characteristics of the new dataset - DCB only needed for a new dataset that does not exist yet - existing datasets keep DCB in dataset label - SYSOUT is a print queue; doesn't need a DCB - defaults apply where program doesn't specify all of DCB - IDCAMS copies input DCB to output DCB if you don't specify - we concentrate on 4 DCB subparameters: DSORG, LRECL, BLKSIZE, RECFM - look up each of these new parameters in the book - always write them in this order: DSORG, LRECL, BLKSIZE, RECFM - professor requires the above exact order to these four parameters! - logical order; but, MVS doesn't care about keyword parameter order - DSORG: tapes must be specified as physical sequential (PS) - LRECL: the input is instream data, so we use a record length of 80 - instream data is always 80 characters (LRECL=80) [punch cards!] - BLKSIZE: pick largest multiple of LRECL that fits output medium block size - tape inter-block gap takes sizeable space; don't want a lot of them - why not use really huge block sizes to minimize inter-block gaps? - uses up too much memory - block size less than or equal to 4K fits in IBM paging buffer nicely - therefore: output block must be multiple of LRECL (80) less than 4K (4096) - choose largest multiple of LRECL that fits in 4K - Formula: int(4096 / 80) * 80 = 4080 - RECFM: we have fixed length records with blocking: FB - (Note: The test data is supposed to be 100-byte records; but, IDCAMS can only create 80-byte records from instream data. We ignore the incorrect output format, to get practice using IDCAMS. In the real world, you would use some other program to generate the test data.) - UNIT: we must specify onto what kind of device we wish to write our NEW data - tape drive 3480 is a possible tape UNIT; but, it's too specific - use MVS system-defined "device group names" instead - chosen by system programmers at sysgen time - consult shop for names (will differ from shop to shop) - group SCRATCH was specified as appropriate UNIT for a temporary tape - no need for VOL or SER parms since we use *any* tape (UNIT=SCRATCH) - no need for tape LABEL parm if using standard IBM tape labels (we are) - Note: this new temporary tape is PASSed and not put in the system catalog - when this job ends, there is no way of finding this tape again, which is okay, since it's a temporary tape and will be re-used IDCAMS DCB handling ------------------- IDCAMS defaults its output DCB specifications to be equal to input specs - this is almost always terrible when copying instream data to disk or tape! - instream input data has the following DCB: DCB=(DSORG=PS,LRECL=80,BLKSIZE=80,RECFM=F) [not FB!] - writing a tape with these default DCB parms would waste a *lot* of tape - remember to re-block your IDCAMS output when reading from instream! - specify DCB parameters for the output DD statement when using IDCAMS - you never need to specify DCB for an input dataset or an existing output dataset (the DCB is kept in the label of the dataset) - you must specify the DCB for a dataset that doesn't already exist Finding Uncataloged Datasets ---------------------------- In all our previous examples, all dataset names were always cataloged: - the name of the dataset was put into the system catalog along with the location (UNIT, VOL, SER) of the dataset - when you reference a cataloged name in your JCL, the system can find out the UNIT (e.g. disk or tape) and VOL=SER (which disk or which tape) based on stored catalog information for the dataset name - you never need to code UNIT or VOL=SER for a cataloged dataset If a dataset name is *not* in the system catalog, you must specify UNIT and VOL=SER so that the system can find it. Once an uncataloged dataset is found in a JCL job step, it can be PASSed to a following job step without requiring UNIT and VOL=SER again (see p.121 for other retained parameters). If you forget where an uncataloged dataset is (unknown UNIT or unknown VOL=SER), you've lost it until you tell the systems people to go find it for you! Cataloged datasets are easier to use in JCL; but, you are charged a space and time fee for each catalog entry. Step Two -------- MVS rules require us to order DD statements for a proc in same order as the internal steps in the proc. Find out the step names! We have to guess the proc step names here, since they weren't provided in the spec: //CLG EXEC PROC=COBOLCLG //* NOTE: I AM GUESSING BOTH OF THE PROC STEP NAMES; THEY WERE NOT PROVIDED. //* I AM ALSO GUESSING THE COMPILER INPUT DDNAME; IT WAS NOT PROVIDED. //COMP.SYSIN DD * ...cobol program source goes here... /* //GO.PRINTOP DD SYSOUT=B //GO.MSTOUT20 DD DSN=TSTOUT,DISP=(NEW,PASS), // DCB=(BLKSIZE=4000,RECFM=FB), // UNIT=SCRATCH //GO.TAPEDATA DD DSN=MYTSTDAT,DISP=(OLD,DELETE) //GO.LSTIN DD DSN=PRODLIST,DISP=(OLD,KEEP), // LABEL=(,AL),UNIT=SYSSQ,VOL=SER=201111 - style: choose a good step name - style: document your guesses, so you know what to change when it fails - MSTOUT20 DCB: look inside COBOL program source to see what the author decided for the output data format (output DCB parameters): - COBOL program itself specifies DSORG ("is sequential") - no need for us to code DSORG in JCL - COBOL program itself specifies LRECL ("record contains") - no need for us to code LRECL in JCL - "block contains 0 records" means let JCL set the block size - don't want to hard code the size inside the COBOL program - want to choose best block size based on output device characteristics - choose largest multiple of LRECL that fits in output device block - Formula: int(4096 / 100) * 100 = 4000 - therefore: we only need to code BLKSIZE and RECFM in the DCB - no need for VOL or SER parms since we use *any* tape (UNIT=SCRATCH) - the operator will find us a scratch tape to use - we will catalog this tape at the end of the job when we are done - this tape will become one of "our" tapes (billed to us) - the specifications don't give the name of this output dataset; we invent one: "TSTOUT" - TAPEDATA: the MYTSTDAT dataset name is not in the system catalog; but, it was PASSsed from a previous step, so UNIT and VOL=SER are remembered - input datasets and passed datasets don't need to specify DCB - much of DCB is kept in dataset label for existing datasets - see p.121 for list of retained catalog and passed parms - only need to code DSN and DISP for this uncataloged input dataset - specification says to delete the tape after the job ends - this is the last step using the tape; we delete it here - LSTIN: the PRODLIST dataset is an uncataloged ANSI (non-IBM) tape dataset - the exact location of the uncataloged PRODLIST dataset must be specified - need to specify UNIT and VOL=SER to find it - VOL takes keyword subparameters - you can reorder them - don't need parentheses if using only one subparameter (Chapter 4) - the type of non-IBM LABEL must be specified - ANSI: American National Standards Institute - non-IBM standard; used to share tapes with non-IBM sites - LABEL parameter takes positional parameters! - cannot reorder the parameters, need leading commas - need second parameter to set ANSI Labels: LABEL=(,AL) - you must specify LABEL to *read or write* a non-IBM tape! (you can't store the type of the tape in the label, because you need to know the type of the tape to even read the label) - the specification doesn't say what to do with this tape when we're done, so we do the safe thing and KEEP it Start of Step Three ------------------- Use IDCAMS to copy the tape to the printer hold spool queue. We know that IDCAMS needs four DDnames for a copy (REPRO) operation. //VERIFYCP EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=D //OUT DD SYSOUT=D //IN DD DSN=TSTOUT,DISP=(OLD,CATLG) //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* // - style: choose a good step name - style: output DD before input DD - style: instream DD come last - we send the IDCAMS control message printout to the same hold queue - no need to code DCB for a PASSed or input dataset - PASSed dataset UNIT and VOL=SER are remembered between steps (p.121) - no need to code location of dataset - The specifications say to catalog the tape; we do this in the last step that uses the tape. (If we did it in an earlier step, it would cause the tape to be dismounted and put in storage. The operator would have to go back to storage to get the tape out for the next step that used it. This is annoying.) - putting the name TSTOUT in the catalog means future references to this name don't need to specify UNIT or VOL=SER (parms will be in the catalog). (Real cataloged dataset names are much longer!) 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 2 Homework" question; we will review it next class.