--------------------------- Week 12-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 - Wed Feb 3, 2000 --------------------------------------- MVS JCL Example 2 and attached homework --------------------------------------- Using IDCAMS ------------ - IDCAMS is an IBM standard utility found on every MVS system - it can do dozens of operations and has its own mini-control language - what are the IDCAMS *control* statements used for? - tell the IDCAMS program what to do - the control statements choose among many possible options - similar to command line arguments and flags - IDCAMS could take parameters; but, there are too many - instead, it reads a dataset (file) containing the command options - dataset always comes on DDname SYSIN (compiled into IDCAMS) - we usually write JCL to make SYSIN connect to "instream data" so that the control statements appear in the JCL stream - real-world IDCAMS use may have 10-15 lines of control statements that do many different things to many datasets - in this course, we only use the REPRO "copy" function - what DDnames are used in the copy (IBM calls it "REPRO") step? - you get to pick the two DDnames used by IDCAMS for input/output - 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 - this will cause a run-time error, not a JCL error - spelling errors in DDnames are only discovered at run time - IDCAMS prints a report of what it did (or did not do) on DDname SYSPRINT - to make sure the operation worked and say how much was copied - less than 100 lines (more like 10 to 20 for a simple REPRO) - specification doesn't say what to do with this status report output - real-world use would probably be to hold this for TSO viewing - use the best SYSOUT queue (for less than 100 lines) Review: Compile, Link, and Go ----------------------------- - we must supply COBOL source code to which program? - to the compiler (the first step in a standard CLG PROC) - what step name and DDname is needed to supply the instream COBOL source code to the compiler in the first step? - not specified in the job specifications - we have to ask or guess - choosing the right step name is a JCL issue (the JES JCL processor has to match the step name with the PROC) - we can do a test run to generate a listing of the PROC so that a fixed second run will use the correct internal step name - choosing the right DDname within the step is a run-time issue (when the program runs, it opens its DDnames) - no way to look inside the compiler to see what the DDname is; must run the compiler and look at the error message it generates when it asks to read the COBOL source as input - to see the step names hidden inside a PROC, we will need to set MSGLEVEL on the JOB card to get maximum JCL information about the PROC printed from our test run - we want to see the *all* the JCL inside the proc, to see the step names - don't set MSGLEVEL to suppress PROC listing! - 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 must match the hidden internal step name coded by the author of the system COBOLCLG proc that we are using - the "SYSIN" part of the name must match the DDname chosen by the author of the COBOL compiler program itself - since the compiler is an IBM utility, we guess at DDname "SYSIN" - guessing the wrong step name will generate a JCL error - guessing the wrong DDname will generate a run-time error from the compiler (but we won't see the run-time error until we fix the JCL error!) - what part of our CLG job wants to read dataset TAPEDATA? - not the compiler (review: what does a compiler do and what does it read?) - not the linker (review: what does linker do and what does it read?) - must be the "go" step (where my compiled COBOL 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 - JCL listing will show proc, from which we can read the right step name - guessing the wrong step name will generate a JCL error - read the PROC listing, 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 -------------- (see the "weekly.txt" file under JCL Notes) New keyword parameters for the JOB card: - MSGCLASS=, MSGLEVEL=, PRTY=, TYPRUN= MSGCLASS - 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") to hold this output because we know the job will fail (because we are guessing at some step and DDnames) - we want to look at the output via TSO, fix the JCL, and resubmit MSGLEVEL - level of JOB processing detail coming from JES and JCL - this does not affect output (SYSOUT) from any programs run by the JCL - only affects output of the actual JES/JCL/allocation messages - default is set by each MVS shop (differs from shop to shop) - MSGLEVEL uses two positional parameters - (1,1) is maximum output (including PROC listings) - we choose verbose level (1,1) so that we see PROC listing - we could also 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) - don't use (0,0) for the first run or you won't see the PROC listing and you won't be able to fix the step names in your JCL! PRTY - choose your priority among various jobs having the same CLASS= - not strictly a FIFO queue (JES and operator may shift jobs around) - actual value depends on MVS version; high numbers are higher priority - remember which version of JES uses which high priority! - JES2 uses 0 to 15 - JES3 uses 0 to 14 - some account codes may be restricted from using some priorities - some priorities may increase the cost of your job run TYPRUN - SCAN: used to scan JCL for JCL errors (verify correct JCL) - the job is not actually run - does not find any run-time errors (e.g. DDname errors) - HOLD: can be used to hold a job in the input queue - the job is not run until released - need to use this parameter for the homework JCL assignment New keyword parameters for the DD card: - DCB=(DSORG=,LRECL=,BLKSIZE=,RECFM=) - LABEL=(,AL) - UNIT= - VOL=SER= (see the IBM JCL Reference Manual; 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 errors in the instream data that may be read by a program when it runs JCL Errors: - syntax errors; misspelled JCL parameters; names too long; 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 error 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 - incorrectly matching DDnames can only cause run-time errors - BUT: a DDname that is too long (more than 8 chars) would be a JCL error 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 continuation lines past column 16 - some posted examples from previous years may violate this rule so that they read more clearly to the novice eye - don't code this way! (if you find a posted example from this term that violates this rule - tell me and I'll go fix it) - review previous examples In what order do we write DD statements? - style: output before input (but obey MVS rules for over-riding PROC's) - professors prefer instream DD statements last (but obey PROC rules) - put biggest instream last (but obey PROC rules) Guesses are documented using comments before the associated statement. Commentary on the JCL is listed after the step, below: JOB Card -------- //* There are some Real World Suggestions that apply to this step; //* see the commentary below for explanations of these. //* //CBLTSTE2 JOB 03F$EX2,'MY NAME',CLASS=D,MSGLEVEL=(0,0),PRTY=11 - style: choose a good job name - choosing a good name is a *choice*, not a *guess* - JOB CLASS= - this JOB class is not a SYSOUT print queue class! - this CLASS tells JES about all the resources used by the whole job - JOB classes (letters) change from MVS shop to MVS shop - and from example to example and from test to test - do not write these classes on your test crib sheets - check the list of classes specified for this example - based on resource needs, we choose class "Dog" ("D") for this job - JOB MSGCLASS= - MSGCLASS *is* a SYSOUT print queue class (for the JCL listing)! - the specifications say to use minimal messages (0,0); but, this is not how we would do the first run of this job! - we would code (1,0) for the first run; see Real World, below - JOB PRTY= - we are asked to choose a "medium-high" priority: e.g. 11 (out of 15) - "medium" would be approximately 7, so "medium-high" would be about 11 Real World Suggestions (not given in job specification) - these are suggestions, not given in the job specification, that you would probably do "on the job" to make your life easier - following Real World suggestions are not required on tests or exams - on a text or exam code exactly what the specification requires, even if it may cause Real World problems - Suggestion: add MSGCLASS=D to the JOB card - hold the JCL listing for viewing by TSO; because, we are making some (probably wrong) guesses at step and DDnames - don't want to print a failed job on paper; send it to TSO instead - the SYSOUT hold queue class is "Dog" ("D") for this example - when the job is working, we can let it print (remove MSGCLASS) - Suggestion: use MSGLEVEL=(1,0) to see the PROC listing - we are making some guesses about the step names used inside the PROC - we should get a PROC listing, to find out what the real step names are - without the PROC listing, we can't fix our incorrect step guesses! - when we know the correct PROC step names, return to using job spec (0,0) Step One -------- //MAKETAPE EXEC PGM=IDCAMS //SYSPRINT DD SYSOUT=A //OUT DD DSN=MYTSTDAT,DISP=(NEW,PASS), // DCB=(BLKSIZE=4080,RECFM=FB), // UNIT=SCRATCH //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* //IN DD * ... Many test records go here. The syntax of these lines is dictated by ... the input requirements of the COBOL program that will be reading them ... from tape in the next step. /* - style: choose a good step name (*not* STEP1) - choosing a good name is a *choice*, not a *guess* - this step executes a *program* (a standard IBM utility), not a PROC - no need to code the step name in front of any DDnames - DSN=MYTSTDAT: we choose an output dataset name for the NEW temporary tape - a name we choose is *not* a "guess"; it is a *choice* - we are not *guessing* this name; we are choosing it and as long as it is syntactically correct it can't be wrong (it is not a *guess*) - DCB: Data Control Block - a DCB parameter block describes the characteristics of the NEW dataset - recall that previous examples used existing datasets where the DCB information was already created and kept with the dataset in the "label" - we concentrate on 4 DCB subparameters: DSORG, LRECL, BLKSIZE, RECFM - look up each of these new parameters in the IBM JCL Reference Manual - we usually write them in this order: DSORG, LRECL, BLKSIZE, RECFM - a logical order; but, MVS doesn't care about keyword parameter order - you can optionally omit the DCB=() around these subparameters (the sub-parameters were promoted to parameters some years ago) - DCB is only needed for a NEW dataset that does not exist yet - existing datasets keep their DCB inside the dataset "label" - no need to specify DCB for existing datasets, only NEW ones - DD SYSOUT= statements are print queues; they don't normally need a DCB - some DCB defaults apply when a program doesn't specify all of a DCB - IDCAMS copies all of the input DCB to the output DCB if you don't specify - COBOL programs have clauses that set some or all DCB parameters - DSORG: - Data Set ORGanization: MVS has many types of dataset organization - tapes must be specified as DSORG physical sequential (PS) - DSORG=PS is the only DSORG we use in this course - since we are using IDCAMS, and IDCAMS by default copies the input DCB to the output DCB, and the DSORG of the input (instream data) is the same as the DSORG of the output (tape), we do not code DSORG in the JCL - LRECL: the input is instream data, so we use a record length of 80 - instream data is always 80 characters (LRECL=80) [punch cards!] - since we are using IDCAMS and the input LRECL is the same as the output LRECL, we do not code LRECL in the JCL - 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 in I/O buffers - devices have an upper limit on block size, different for each device - IDCAMS would copy the input DCB BLKSIZE to the output DCB BLKSIZE - instream data has BLKSIZE=80; it has one 80-character record per block - but BLKSIZE=80 is terrible for a tape! Huge waste between blocks! - must "re-block" the data for the output tape - a block size less than or equal to 4K fits in IBM paging buffer nicely - output block must be multiple of LRECL (80) less than 4K (4096) - choose the largest multiple of LRECL that fits in 4K - Formula: integer(4096 / 80) * 80 = 4080 - no fractional block sizes! use the integer part only! - RECFM: - RECord ForMat: the format of the records in the dataset - we are defining fixed length records with blocking: FB - the other less common use is RECFM=F (no blocking used, e.g. instream) - IDCAMS input instream data is in format RECFM=F - we must code FB for our output tape dataset, to over-ride the IDCAMS use of F from the instream data dataset - because we are re-blocking the data, we must code FB for output - UNIT: we must specify onto what kind of device we wish to write our NEW data - tape drive type "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 when MVS was installed - consult shop for names (names will differ from shop to shop) - group SCRATCH was specified as an appropriate UNIT for a non-specific tape - a non-specific tape is one that doesn't have a volume or tape number yet - no need for VOL or SER parms since we use *any* tape (UNIT=SCRATCH) - operator will select a tape for us from the SCRATCH pile - no need for tape LABEL parm if using standard IBM tape labels (we are) - remember: a dataset "label" is a reserved part of a dataset storing information about how the dataset is organized - 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 (Data Control Block) 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 - the tape would have too many inter-block gaps! - 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 because the DCB is kept in the label of the dataset - you must only specify the DCB for a NEW output dataset that doesn't already exist (or that you are re-creating as you write it) 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 in the later steps. The dataset behaves as if it were a cataloged dataset; but, only if you PASS it from step to step. PASSed datasets are as easy to use as cataloged datasets - you only need to use DSN= and DISP= to access them. 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. We use JCL comments to document our guesses: //* NOTE: I am guessing both of the PROC step names; they were not provided. //* Incorrect step names will trigger JCL errors. //* I am also guessing the compiler input DDname; it was not provided. //* An incorrect compiler input DDname will trigger a run time error //* by the COBOL compiler when it runs and cannot open the right DDname. //* //CLG EXEC PROC=COBOLCLG //COMP.SYSIN DD * ...my 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 (Remember: a choice is not a guess) - style: document your guesses, so you know what to change when it fails - always state whether the guess causes a JCL or run-time error - we must code one DD statement for the compler input (COMP.SYSIN) and three DD statements for the running program: - 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 - no fractional block sizes! use the integer part only! - therefore: we only need to code BLKSIZE and RECFM in the DCB - always code RECFM if you code BLKSIZE (they are a pair) - 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 choose one: "TSTOUT" (Remember: a choice is not a guess) - 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 - 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 - we only use VOL=SER= in this course - 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 (not keyword) parameters! - cannot reorder the positional 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) - Important: ANSI tapes are limited to a maximum of a 2K block size! - when you write to an ANSI tape, the BLKSIZE must be <= 2048 bytes - 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=A //OUT DD SYSOUT=D //IN DD DSN=TSTOUT,DISP=(OLD,CATLG) //SYSIN DD * REPRO INFILE(IN) OUTFILE(OUT) /* // - style: choose a good step name (remember: a choice is not a guess) - style: output DD before input DD (but MVS doesn't care) - style: instream DD come last (professor preference but MVS doesn't care) - job spec doesn't say where to send the IDCAMS status messages - use the best SYSOUT queue (for less than 100 lines of messages) - Real World Suggestion: could send them to the same TSO hold queue - no need to code a DCB for a PASSed or input dataset - DCB only needed for NEW datasets (output) if the DCB info is not already set in the program creating the dataset - PASSed dataset UNIT and VOL=SER are remembered between steps - no need to code location of a PASSed (or cataloged) dataset - only need DSN and DISP for PASSed or cataloged datasets - easy! - 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 (the parms will be in the catalog). (Note: Real-world 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.