0% found this document useful (0 votes)
316 views

JCL2

The document provides an overview of JCL (Job Control Language) and the MVS operating system. It describes how JCL directs the computer to run programs as jobs and how MVS uses virtual storage to allow multiple programs to run simultaneously. Disk storage can contain multiple data sets accessed at the same time, while tape and printers require exclusive access. JCL statements specify the I/O devices each program requires.

Uploaded by

Naveen Rawat
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
316 views

JCL2

The document provides an overview of JCL (Job Control Language) and the MVS operating system. It describes how JCL directs the computer to run programs as jobs and how MVS uses virtual storage to allow multiple programs to run simultaneously. Disk storage can contain multiple data sets accessed at the same time, while tape and printers require exclusive access. JCL statements specify the I/O devices each program requires.

Uploaded by

Naveen Rawat
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 169

JCL FOR PROGRAMMERS CONTENTS ________ COURSE FORMAT SUMMARIES SESSION 1: 1.1 1.2 1.3 1.4 1.5 1.

6 1.7 1.8 SESSION 2: 2.1 2.2 2.3 2.4 SESSION 3: 3.1 3.2 3.3 3.4 3.5 SESSION 4: 4.1 4.2 4.3 SESSION 5: 5.1 5.2 5.3 5.4 SESSION 6: SESSION 7: 7.1 7.2 7.3 7.4 JCL BASICS JCL Overview MVS Concepts JCL Syntax Jobs and Job Steps The JOB and EXEC Statements The DD Statement To Read Existing Data Sets The DD Statement To Create Data Sets A JCL Problem THE DETAILS OF DATA SETS AND JCL Data Sets Data Records DCB Sub-parameters and Data Set Labels Concatenating Data Sets DISK DATA SETS Space Allocation The SPACE Parameter More on the SPACE Parameter Estimating Disk Space Track Overflow and Spanned Records JOBSTREAM INPUT AND PRINTED OUTPUT Standard Parameters Parameters for the 3800 Printer The OUTPUT Statement TAPE DATA SETS Storage in Tape Files DD Parameters for Tape The LABEL Parameter for Tapes Unlabeled Tapes USING CATALOGED PROCEDURES JOB STEPS The PARM Parameter Backward References Passing Data Sets The COND Parameter Page 1 of 169

JCL FOR PROGRAMMERS

SESSION 8: 8.1 8.2 SESSION 9: 9.1 9.2 9.3 SESSION 10: 10.1 10.2 SESSION 11: 11.1 11.2 SESSION 12: 12.1 12.2

PARTITIONED DATA SETS Creating Partitioned Data Sets Compressing Partitioned Data Sets WRITING CATALOGED PROCEDURES Instream and Cataloged Procedures Writing Procedures--Jobstream Input Writing Procedures--Symbolic Parameters JCL PROBLEMS Common JCL Errors How To Read an Output Listing GENERATION DATA GROUPS Application of Generation Data Groups Creating and Using Generation Data Groups DIRECT AND VSAM DATA SETS Direct Data Sets VSAM Data Sets

JCL FOR PROGRAMMERS

Page 2 of 169

COURSE FORMAT SUMMARIES _______________________ Follow these directions if you are taking this course in the EZED format. STEP 1: Sign on to your system with a valid userid. invoked with the command: EZED The courseware is

STEP 2: Follow the instructions in the course. All answers to questions can be in upper or lower case--make things simple by entering everything in lower case. EZED FORMAT COMMANDS Press PF Key or Enter Command _____ _______ PF1 PF7 PF8 hint sign off list go to n go to n.n go to xxxx def glossary def xxxx

For This Result ___ ____ ______ For a summary of EZED format commands (help). To back-page one screen at a time. To page forward one screen at a time. To request a hint on any question. To sign off at any screen. (You'll return to the same place when you sign on again.) To get a list of the topics in the course. To go to a specific session (n) or topic (n.n). For example: go to 3.3 To go to the topic that explains a particular instruction (xxxx). (i.e., go to procedure). To request a list of defined terms for the course. To request the definition of a term (xxxx). (i.e., def EZED).

ABSTRACT ________ COURSE SUMMARY ______ _______ Welcome to the JCL* for Programmers course. The entire course should take about 9 hours at the terminal, depending on how much background you have in programming and how deeply you want to go into the material. JCL for Programmers is intended primarily for programmers. The course uses a computer-based training (CBT) system to lead you through JCL programming techniques. You simply sign on to a terminal and invoke the CBT system when you have time available for study. You progress at your own pace. This student workbook has been designed primarily as a reference. It also contains information that supplements the course material. The organisation follows the course organisation; each course session is represented, with a JCL FOR PROGRAMMERS Page 3 of 169

summary of JCL features covered. used in estimating disk space.

The Appendix contains tables that can be

_____ *JCL (Job Control Language) is a product of International Business Machines Corporation.

JCL FOR PROGRAMMERS

Page 4 of 169

SESSION 1: JCL BASICS ______________________ TOPIC _____ 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 TITLE _____ JCL Overview MVS Concepts JCL Syntax Jobs and Job Steps The JOB and EXEC Statements The DD Statement To Read Existing Data Sets The DD Statement To Create Data Sets A JCL Problem NEXT | TOP

JCL FOR PROGRAMMERS

Page 5 of 169

TOPIC 1.1: _____ ____

JCL OVERVIEW ___ ________

Many computer systems have command languages that are similar in function to Job Control Language (JCL). But JCL is much different from most command languages and is an indispensable component of large IBM computers with the MVS operating system. JCL consists of a series of language statements you write to direct the computer to run your computer programs. The group of programs you run together is termed a job. JCL is intended for batch jobs. That is, you may submit your job in the afternoon, the computer schedules when your job is to run, and you might pick up your output the next morning. JCL is a very extensive language, and there are many JCL features that you may never need. For example, you defer mounting of a direct access volume (disk pack) until after your job begins execution. But your installation probably won't let you mount your own disk packs, so there is no need to explain this feature. The course concentrates on the JCL features you are likely to need to use. For an exhaustive description of JCL, we recommend you obtain the following book by the author of this course: System/370 Job Control Language, by Gary DeWard Brown, published by John Wiley & Sons, New York, 1987. TOPIC 1.2: _____ ____ MVS CONCEPTS ___ ________

MVS OPERATING SYSTEM JCL is a language that lets you use the facilities of the MVS operating system. To use JCL you need to know some general things about the operating system. Let's look at a typical computer: +----------+ INPUT/OUTPUT | CPU | OPERATIONS | | INTERFACE | +---------+ | +--| | | | | | +--------+ | REAL |------>------>|------>------>| | | STORAGE | | | I/O | | | | | DEVICE | | |<------<------|<------<------| | | | | +--------+ | | | +---------+ | CPU REAL STORAGE - The Central Processing Unit executes all the computer instructions. - This is the computer's memory. here when they are executed. Programs are placed

JCL FOR PROGRAMMERS

Page 6 of 169

At any given time, several programs may be running in real storage. programs are placed in areas called regions. +----------------------+ | Resident Portion of | | the Operating System | +----------------------+ This area ==> | Program 1 | is termed +----------------------+ a region. | Program 2 | +----------------------+ | Program 3 | +----------------------+ | Program 4 | +----------------------+ | Program 5 | +----------------------+ | . | +----------------------+ | Program n | +----------------------+

The

The CPU will execute instructions for a program, then quickly switch to another program and execute instructions for it. This leads to another term, timesharing. CPU time is shared among many programs.

MVS stands for Multiple Virtual Storage. Multiple means that several programs are run on the computer at the same time, as we just illustrated. Virtual means that each computer program is made to believe it has much more real storage available to it than is actually there. VIRTUAL STORAGE A program may be this large: (on disk) +----------+ | | | | |----------| | | ---------------------> | | Only the portion of |----------| the program containing | | the instructions being | | executed needs to be | | in real storage at any | | given time. | | | | | | | | | | | | +----------+ With virtual storage, of real storage. This storage available on the to be run on the computer Real storage: (inside the computer) +-----------------------+ | | | | +-----------------------+ | Real storage actually | | used by program | +-----------------------+ | | | | | | | | | | | | +-----------------------+ The result is that a very large program can be run with a smaller amount of real storage.

a program need occupy only a relatively small amount lets you run programs whose size exceeds the real computer. It also allows a larger number of programs at the same time.

JCL FOR PROGRAMMERS

Page 7 of 169

Each program may use various input/output (I/O) devices. statements tell the system which I/O devices each program needs. then co-ordinates the use of the I/O devices with the programs. +-----------+ | DISPLAY | | TERMINAL | +-----------+ +-----------+ /ooooooooooo/ | | /ooooooooooo/ /---->|-----------| /___________/ / | DISK | /|\ / | DRIVE | +-------+ \|/ |/ +-----------+ | 0 0 | +-----------+|-------| | | | TAPE |<---------->| Computer | | DRIVE | | | +---------+ | | | |<---------->| | +-------+ +-----------+ |---------| | | | PRINTER | +---------+

The JCL DD The system

Disk storage can also be shared. Many data sets can be placed on a single disk pack and all be used at the same time. DISK PACK +----------+----------+----------+----------+-------+ |Data Set 1|Data Set 2|Data Set 3|Data Set 4| ... | +----------+----------+----------+----------+-------+ On a large IBM computer, a disk pack is a large version of the floppy diskettes you've probably seen on personal computers. A disk pack consists of 15 to 30 disks stacked one on top of the other and spinning together. A disk unit on a large IBM computer is called a DASD (pronounced dasdee), which stands for Direct Access Storage Device. A magnetic tape unit consists of a reel of tape that the computer can read or write. Tapes on a computer are similar to cassette tapes or VCR tapes. At any given time, only one person can be reading or writing a single tape. When you ask for something to be printed on a high-speed printer on a large computer, it is put in a queue to be printed when its turn comes, similar to the way you queue up at a cash register at a supermarket to wait your turn to be processed. The process of storing output to be printed into a queue on disk storage, and then printing the output, an item at a time, is called spooling: Simultaneous Peripheral Operation On-Line.

JCL FOR PROGRAMMERS

Page 8 of 169

+-------------------+ +-------------+ | | | | | Program1 "prints" | +-------------+ | lines |==>| Data set to | | | | print | +-------------------+ +-------------+ | Program2 "prints" | | Data set to | | lines |==>| print | | | +-------------+ +-------------------+ | | | | +-------------+ | | \|/ Print queue is sent to printer | | +---------------------+ +-------------------+ \|/ +---------+ | Printer | |---------| | | +---------+ TOPIC 1.3: JCL SYNTAX _____ ____ ___ ______ JCL statements all have this general format: //name operation parameters Statements are identified by operation, and the usual operations are JOB, EXEC, and DD. One or more blanks must be left between fields (and after the statement, as appropriate) but nowhere else. The name field is optional. However, the rule that one or more blanks must separate each field still holds. NAMING In JCL, names (whether jobnames, stepname, or ddnames, etc.) must conform to three rules: 1) Must be 1 to 8 characters in length. 2) First character must be A-Z, @, $, or #. 3) Remaining characters can be A-Z, 0-9, @, $, or #. JCL treats the @, $, and # as alphabetic characters, so the rules are really: 1) 1- to 8-character names. 2) First character alphabetic. 3) Remaining characters alphanumeric.

JCL FOR PROGRAMMERS

Page 9 of 169

POSITIONAL AND KEYWORD PARAMETERS The parameter field is composed of two types of parameters: positional and keyword. o Keyword parameters have the form: keyword=value For example: SYSOUT=A This assigns the value A to the SYSOUT keyword parameter. o Positional parameters require that values be coded in a specific position. The system determines what each value means by its relative position. For example: TIME=(10,30) The system knows the specified time--10 minutes, 30 secondsby each value's relative position. Notice that a keyword parameter is often composed of positional sub-parameters such as this.

SUB-PARAMETERS Positional and keyword parameters can be composed of positional or keyword sub-parameters enclosed in parentheses. You can omit a positional subparameter by writing just a comma, and you can omit trailing commas. You can also omit the parentheses if there is only one positional sub-parameter. When we write: o o o //A DD DISP=(OLD,PASS,KEEP)

First sub-parameter is given a value of OLD. Second sub-parameter is given a value of PASS. Third sub-parameter is given a value of KEEP. //A DD DISP=(OLD,,KEEP)

When we write: o o o

First sub-parameter is given a value of OLD. Second sub-parameter is given no value. Third sub-parameter is given a value of KEEP. If we omit the

The extra comma is needed to indicate the missing value. second comma: //A DD DISP=(OLD,KEEP) o o o First sub-parameter is given a value of OLD. Second sub-parameter is given a value of KEEP. Third sub-parameter is given no value.

JCL FOR PROGRAMMERS

Page 10 of 169

CONTINUATION OF JCL STATEMENTS You must write JCL statements in columns 1-71. To continue a statement, stop at a comma (following a parameter or sub-parameter), and begin the continuation with "//", with the statement restarting within columns 4-16. //OUTPUT DD DSN=&&TEST,DISP=(NEW,PASS), // SPACE=(TRK,100),UNIT=SYSDA COMMENTS A comment statement in JCL has the form: //* You can leave a blank after "//*" or not. your comment

If you leave a blank in the parameter field, anything on the line after the blank is treated as a comment. //INPUT DD DSN=&&TEMP,DISP=(OLD,PASS) your comment When you submit a job to be run, the system reads all your JCL and checks it for errors. Only if the entire set of JCL contains no syntax errors does the system attempt to execute the job. A job must be completely free of JCL syntax errors to execute.

TOPIC 1.4: _____ ____

JOBS AND JOB STEPS ____ ___ ___ _____

A job begins with a JOB statement. Each job is composed of one or more job steps that begin with an EXEC statement. Here is some JCL for a single job. It has three job steps. +---------------------------------------------------------------------------+ |//TEST#2 JOB (2237,4),'PHASE1',CLASS=B | |//STEP1 EXEC PGM=CALC | |//SYSPRINT DD SYSOUT=* | |//STEP2 EXEC PGM=SORT | |//SYSPRINT DD SYSOUT=* | |//LAST EXEC PGM=STATS | |//SYSPRINT DD SYSOUT=A | +---------------------------------------------------------------------------+ THE JOB AND EXEC STATEMENTS The JOB statement is usually specified by each installation. statement has this general form: //stepname EXEC PGM=program The stepname is optional. // EXEC PGM=COPY JCL FOR PROGRAMMERS Page 11 of 169 The EXEC

THE DD STATEMENT Virtually all programs print some output. //ddname DD SYSOUT=class The program must internally define a data set with the ddname. SYSOUT=class is the JCL parameter to send the output to a printer. The "class" is a single letter (A-Z) or number (0-9) set by your installation to specify the printer. For example: //SYSPRINT DD SYSOUT=A Here's the way a DD statement works: +---------------------------------+ | The program writes an output | | data set. The program refers | | to the data set by the name of | | SYSPRINT here. | +--------------+------------------+ | \|/ //SYSPRINT DD SYSOUT=A /|\ /|\ | | This part of the DD statement This part of the DD is the "ddname" and it ties statement sends the data this DD statement to the data set to this printer. set the program is writing. All installations have a default SYSOUT class for the printer. To send your output to this default SYSOUT class, you write an asterisk (*) instead of a specific class. //SYSPRINT DD SYSOUT=* DATA IN THE INPUT STREAM The DD statement that lets you enter lines of data along with your JCL (your JCL and lines of data are termed the "input stream") is: //ddname DD * The * means that the data immediately follows this JCL statement. To mark the end of the data, you simply write in columns 1-2: /* Here is a complete job: Page 12 of 169 The general form is:

JCL FOR PROGRAMMERS

+---------------------------------------------------------------------------+ |//RUN#1 JOB (2247,12),'COPY ALL',CLASS=B | |// EXEC PGM=COPY | |//SYSPRINT DD SYSOUT=A | |//SYSIN DD * | |A line. | |Another line. | |A third line. | |Lots of lines. | |Enough lines. | |/* | +---------------------------------------------------------------------------+ TOPIC 1.5: _____ ____ THE JOB AND EXEC STATEMENTS ___ ___ ___ ____ __________

THE JOB STATEMENT The start of a job is defined by the JOB statement. //TEST#6 JOB (2215,16),'TEST6',CLASS=A The system reads in the entire job and checks your JCL statements for syntax errors. Then it stores the job on disk in a job queue to await execution.

THE CLASS PARAMETER The system keeps several queues, termed job classes. the queues by the CLASS parameter. Jobs are directed into

CLASS=A CLASS=B CLASS=C | Job 4 | | | | | | Job 3 | | | | | | Job 2 | | Job 6 | | Job 8 | | Job 1 | | Job 5 | | Job 7 | +-------+ +-------+ +-------+ | | | \|/ \|/ \|/ Jobs are selected to be executed on a first-in-first-out basis. Note: the CLASS=jobclass parameter coded on the JOB statement has nothing to do with the SYSOUT=class parameter coded on a DD statement. The CLASS parameter directs the job into a particular queue. The SYSOUT parameter directs the output to a particular job output queue for printing. There are several reasons for setting up separate job classes: o o To balance the running of jobs that do many calculations with jobs that do lots of input/output. To set aside jobs that require a special setup, such as requiring a tape to be mounted. Page 13 of 169

JCL FOR PROGRAMMERS

To control when some jobs are run, such as overnight or on weekends.

The JOB statement is easy. Most of the items on it are specified by your installation, which will tell you what to write. The "jobclass" in the CLASS parameter is a single letter (A-Z) or number (0-9). //jobname JOB (accounting-information),'remarks',CLASS=jobclass /|\ ----------------------------------| /|\ Often specified /|\ Often specified | by installation. | by installation. | | +-----------------+---------------+ | Always specified by installation. If you remember that the remarks can't be more than 20 characters, you usually won't make many errors in writing the JOB statement. THE TIME PARAMETER The TIME parameter specifies the maximum CPU time permitted your job. you omit this parameter, your installation will supply a default time. TIME=(minutes,seconds) or TIME=minutes If

Say you write a JOB statement like this: //RUN1 JOB (2315,12),'TEST RUN',CLASS=A,TIME=5 If your job uses a fraction over 5 minutes of CPU time, it is abnormally terminated (termed an ABEND, for ABnormal END), and the system gives you an error message and a completion code of 322. When you estimate CPU time, be liberal. Allow more time than you think you need. CPU time is the time it takes the CPU to actually execute your job. It doesn't include the time the CPU takes to execute other jobs or is idle. You may wish to estimate the CPU time for two reasons: o o Your installation may require it. They may also use your estimate of CPU time to assign you to certain job classes. If you are debugging a program and you think a bug may prevent your program from reaching completion, you can cut the job off after a specified length of time.

THE TYPRUN PARAMETER The TYPRUN parameter tells the type of run you are submitting: SCAN HOLD JCLHOLD //jobname JOB (accounting),'remarks',TYPRUN=_______ JCL FOR PROGRAMMERS Page 14 of 169

SCAN HOLD JCLHOLD no

checks the JCL for syntax errors and suppresses job execution. holds the job in the job queue until the operator releases it for execution. is the same as HOLD, except that the JCL isn't checked for errors until the operator releases the job. This has almost use.

You might use TYPRUN=HOLD to submit a job during the prime shift and have it run off-shift. Or you might need to hold a job until you can get a tape to the operators. Whatever, you need to tell the operators when to release the job if you use HOLD. Most installations have procedures and rules for all operator intervention such as this. TYPRUN=SCAN is used more often. executing the job. The system checks your JCL syntax without

With TYPRUN=SCAN, no data sets are allocated. The system can't detect disk space problems, region size problems, duplicate data set names, or insufficient allocation of CPU time.

THE EXEC STATEMENT The usual form of the EXEC statement is: //stepname EXEC PGM=program The stepname is usually not required. // EXEC PGM=IEBGENER THE REGION PARAMETER Before the system executes a job step, it allocates a virtual region for the step. You need to specify the region size. Region size, which is usually specified on the EXEC statement, is the amount of storage necessary to permit a given program to execute. Size is given in units of K bytes, where 1K is 1024 bytes. Storage must be allocated in 2K block increments. To specify the region size, you add a keyword parameter to the EXEC statement: REGION=nK where n is the number of K bytes needed. // EXEC PGM=IEBGENER,REGION=256K If you don't write the REGION parameter, you get a default region size established by your installation. If you request a region too small for the program, the program abnormally terminates (ABENDs) with an 804 or 80A completion code. Page 15 of 169

JCL FOR PROGRAMMERS

The TIME parameter that we described for the JOB statement can also be written in an EXEC statement to specify the maximum CPU time to allow for a single job step: // EXEC PGM=SAS,TIME=(,20) (ABENDs the job step if it consumes more than 20 CPU seconds.) Likewise, the REGION parameter can be written in the JOB statement to specify the region size for all steps within the job. Here is a job with TIME and REGION written in both the JOB and EXEC statements. A REGION in a JOB statement overrides any REGION in the EXEC statements for that step. +---------------------------------------------------------------------------+ |//RUN1 JOB (2315,12),'TEST RUN',CLASS=A, | |// REGION=256K,TIME=(,10) | |//STEP1 EXEC PGM=ONE,REGION=600K | |//STEP2 EXEC PGM=TWO,TIME=(,20) | +---------------------------------------------------------------------------+ STEP2 will ABEND after 10 CPU seconds (actually fewer, depending on how many CPU seconds STEP1 uses), because the TIME on the JOB statement is the maximum allowed for the job.

TOPIC 1.6: _____ ____

THE DD STATEMENT TO READ EXISTING DATA SETS ___ __ _________ __ ____ ________ ____ ____

THE DD STATEMENT The general form of the DD statement; is: //ddname DD parameters The ddname must match that used in the computer program. ddnames are assigned in the most popular programming languages: Assembler: DCB DDNAME=ddname COBOL: FORTRAN: PL/I: C: SELECT file ASSIGN TO ddname. FORTRAN unit nn requires a ddname of FTnnF001. DECLARE (ddname) FILE; fopen(ddname,mode); Here is how

THE DSN PARAMETER There are two general types of data sets: o Non-temporary data sets. them. DSN=data-set-name JCL FOR PROGRAMMERS Page 16 of 169 These stay in existence until you delete

Temporary data sets. step. DSN=&&data-set-name

These are deleted at the end of a job or job

NON-TEMPORARY DATA SETS Non-temporary data sets may have a qualified data set name composed of several levels. For example: Y2222.JAN.DATA Y2222.FEB.DATA Y2222.MAR.DATA

Each data set here has three levels of qualification, which might be a userid, a description, and the type of information the data set contains. Your installation will most likely specify how you name your non-temporary data sets. An installation might include any of the following in the naming conventions: o o o at can The userid The user department The account number

Before you create a non-temporary data set, find out the naming conventions your installation. Within the limits imposed by your installation, you often organize your data sets by carefully chosen names: Y2222.DRAFT1.RESUME Y2222.DRAFT2.RESUME Y2222.DRAFT3.RESUME Each qualification level follows the usual rules: o o o 1 to 8 characters. First character A-Z, #, $, @. Remaining characters A-Z, 0-9, #, $, @.

The total name cannot be longer than 44 characters, counting periods, and up to 22 levels of qualification are allowed. Non-temporary data sets are usually cataloged. When you catalogue a data set, the system stores the data set name, the volume serial number on which it resides, and the type of unit in the system catalog. (The system catalog is a data set containing this information for all the cataloged data sets.) The reason you catalog data sets is so that you don't have to remember the unit and volume serial numbers and specify them when you retrieve a data set.

JCL FOR PROGRAMMERS

Page 17 of 169

THE DISP PARAMETER The usual DISP parameters that you code to read an existing data set are: KEEP OLD PASS SHR DELETE DISP=(___,______) The OLD or SHR status at the start of a step means: OLD -- The data set already exists. Don't let anyone else read the data set while this program is using it. You normally use this disposition to update an existing data set. (If someone were reading a data set while it was being changed, the results be unpredictable.) this SHR -- Same as OLD, but other programs can read the data set while program is reading it. (SHR means share.) disposition for reading a data set. This is the usual

would

There is one important distinction between the dispositions of SHR and OLD. SHR: OLD: Several users can read or write the data set concurrently. Only one user can read or write the data set at a time.

You normally use OLD when you write a data set because the results might be unpredictable if someone were reading a data set while you were writing it. If someone else is reading or writing a data set with a disposition of OLD when you try to read it with a disposition of SHR, your job is held up until the other job completes. You can also use a disposition of OLD to write over an existing data set.

JCL FOR PROGRAMMERS

Page 18 of 169

Existing data set +-----------------------+-+---------------------------+ | |E| | | Old data |O| Available space | | |F|(EOF means End-of-File) | +-----------------------+-+---------------------------+ /|\ | +- OLD positions here. You write over the data set. KEEP PASS OLD DELETE SHR CATLG DISP=(___,______)

The KEEP, PASS, DELETE, or CATLG status at the end of the step means: KEEP -- Keep the data set and any catalog entry. It must be a non-temporary data set. You can't KEEP a data set with a &&data-set-name. You usually use KEEP as the ending status when you read a non-temporary data set. -- Pass the data set on to a following step and let that step determine the disposition. -- Delete the data set. Uncatalog it if it was cataloged.

PASS DELETE CATLG

-- Keep the data set and catalog it.

You can also specify a third disposition to take effect if the job step ABENDs, but we'll discuss that later. For an existing cataloged data set, you usually need to specify only the DSN and DISP parameters. //ddname DD DSN=data-set-name,DISP=(beginning-status,ending-status) If you don't code the second DISP sub-parameter, the system keeps the data sets the same as they were at the start of the step: non-temporary data sets are kept and temporary data sets are passed to the next step. DISP=(SHR) DISP=(OLD) same as same as DISP=(SHR,KEEP) DISP=(OLD,PASS) for a non-temporary data set. for a temporary data set.

If this DD statement were written to create a new data set, and no subsequent step references this data set, a disposition of DELETE is assumed for it at the end of the job. Since the data set didn't exist at the start of the job, it is deleted to re-establish this status.

JCL FOR PROGRAMMERS

Page 19 of 169

+---------------------------------------------------------------------------+ | //OUTPUT DD DSN=D11529.DEPT.DATA,DISP=(NEW,PASS), | | // UNIT=DISK,SPACE=(6160,(100,10)), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6160) | +---------------------------------------------------------------------------+

READING EXISTING DATA SETS To read cataloged or passed data sets on disk, you usually write the DD statement as follows: For non-temporary data sets: //ddname DD DSN=level.level.level...level,DISP=SHR For temporary data sets: //ddname DD DSN=&&data-set-name,DISP=OLD (You could use DISP=SHR instead, but since there is no way to share a temporary data set, it would be treated as DISP=OLD.) //ddname DD DSN=&&data-set-name,DISP=(OLD,DELETE) (You might do this if the data set isn't used in later steps and you want to free up disk space.)

TOPIC 1.7: _____ ____

THE DD STATEMENT TO CREATE DATA SETS ___ __ _________ __ ______ ____ ____

CREATING DATA SETS The DD statement for creating data sets may require the following: o o o o o The DSN, or data set name. The DISP, or disposition. The I/O device and perhaps the volume--the disk pack or tape reel. For disk data sets, the amount of disk space. The record type, record length, and blocking of the records in the data set.

JCL FOR PROGRAMMERS

Page 20 of 169

THE UNIT PARAMETER When you create a data set, you must decide what type of device you want to write the data set onto and then specify this in your JCL with a UNIT parameter. The two major types of I/O devices for containing data sets are: o o Tape units. A volume--a tape reel or cartridge--is mounted on the device to contain the data set. DASD or disk. An installation will have some number of volumes or disk packs for storing data sets.

The individual tape reel, tape cartridge, or disk pack is termed a volume. You specify the I/O device with a UNIT parameter: UNIT=unit Your installation will tell you which unit names to use. A disk pack or tape reel (a volume) is identified by a 6-digit volume serial number. Actually, tapes need not have volume serial numbers, so we'll explain them later. For now, let's assume we are writing data sets on disk storage. Your installation will have several disk packs and will have assigned its own volume serial numbers. The following are typical: +--------+--------+--------+--------+--------+ | SYSSQE | TEMP01 | TEMP02 | TEMP03 | TEMP04 | | | | | | | +--------+--------+--------+--------+--------+ | SYSRES | PERM01 | PERM02 | PERM03 | PERM04 | | | | | | | +--------+--------+--------+--------+--------+ Someone, either you or the system, has to decide which volume (disk pack) to write your data set on. The UNIT names are used by your installation to specify one or more disks. For example, an installation may use these unit names: SYSTEM -- for system data sets--volumes SYSSQE and SYSRES. SYSDA -- for storage of non-temporary data sets--volumes PERM01PERM04. TEMP -- for storage of temporary data sets--volumes TEMP01-TEMP04.

|<-------------- TEMP ------------->| +--------+--------+--------+--------+--------+ /|\ | SYSSQE | TEMP01 | TEMP02 | TEMP03 | TEMP04 | | | | | | | | SYSTEM +--------+--------+--------+--------+--------+ | | SYSRES | PERM01 | PERM02 | PERM03 | PERM04 | | | | | | | | \|/ +--------+--------+--------+--------+--------+ |<------------- SYSDA ------------->| Page 21 of 169

JCL FOR PROGRAMMERS

Your installation will tell you what UNIT names you can use. If you don't request a specific volume, the system selects a volume on which to store your data set. It's usually best to let the system select a specific volume for you. UNIT=TEMP UNIT=SYSDA The system would select TEMP01, TEMP02, TEMP03, or TEMP04. The system would select PERM01, PERM02, PERM03, or PERM04.

THE VOL PARAMETER You can also request a specific volume for your data set by writing: VOL=SER=volume You often write this for tape reels. MORE ON THE DISP PARAMETER So far, we've seen that the DISP parameter specifies two things for the data set: DISP=(beginning-status-of-data-set,disposition-at-end-of-step) To read an existing data set, we could write these options: KEEP OLD PASS SHR DELETE DISP=(___,______) It is usually optional for disk units.

For example:

DISP=(SHR,PASS)

To create a data set, we write these options: CATLG KEEP MOD PASS NEW DELETE DISP=(___,______) /|\ Different The first option describes the status of the data set at the start of a step: MOD NEW DISP=(___,... NEW -- Means the data set is new. That is, it doesn't exist and should be created. You'll get a JCL error if you specify NEW and the data set already exists. -- Can mean two things: o If the data set doesn't exist, create it. That is, it acts Page 22 of 169 <== New

For example:

DISP=(NEW,CATLG)

MOD

JCL FOR PROGRAMMERS

the same as NEW. o If the data set exists, write the data at the end of the data set. This is how you add data to the end of an existing data set. Here's a DD statement with the parameters you would typically write for a disk data set: +---------------------------------------------------------------------------+ |//SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS), | |// UNIT=DISK,SPACE=(TRK,10) | +---------------------------------------------------------------------------+ The NEW in the DISP parameter means that the data set is being created. default disposition is NEW if you omit the first parameter. That is: DISP=(NEW,DELETE) is the same as DISP=(,DELETE) The

DISP=MOD is very handy. following process: o o at the

When you write it, the system goes through the

If the data set doesn't already exist, the system treats MOD as if NEW had been written. If the data set does already exist, the system positions to the end-of-file (EOF) of the data set so that the new data is written the end. data set: That is, it positions so that new data can be added to

Data set: +--------------------+-+------------------------------+ | |E| | | Old data |O| Available space | | |F| | +--------------------+-+------------------------------+ /|\ | +-- MOD would position to here in the data set. Now let's describe the dispositions at the end of the step: CATLG KEEP MOD PASS NEW DELETE DISP=(___,______) DELETE PASS KEEP only.) JCL FOR PROGRAMMERS Page 23 of 169 -- Delete the data set. -- Pass the data set to a following step. -- Keep the data set. (Use this for non-temporary data sets

CATALOGED DATA SETS Your data set is always written on some volume--a disk pack, tape reel, or tape cartridge. Someone, either you or the system, must remember which volume your data set is written on. To have the system remember the unit and volume serial number, use a disposition of CATLG. DISP=(NEW,CATLG) The system then records the data set name, unit, and volume serial number in a catalog. That way, you need remember only the data set name. The catalog is maintained by the system on disk storage. a data set and catalog it: //ddname DD DSN=data-set-name,DISP=(NEW,CATLG), // UNIT=unit,VOL=SER=volume Because the catalog contains the information, you can omit the UNIT and VOL when you write a DD statement to read the data set later: //ddname DD DSN=data-set-name,DISP=SHR But if you create a data set and don't catalog it: //ddname DD DSN=data-set-name,DISP=(NEW,KEEP), // UNIT=unit,VOL=SER=volume You must write both the UNIT and VOL parameters when you code a DD statement to read the data set later: //ddname DD DSN=data-set-name,DISP=SHR, // UNIT=unit,VOL=SER=volume There is one final disposition we haven't mentioned: DISP=(...,UNCATLG) UNCATLG keeps the data sets and uncatalogs it. might need to use this are very rare. The circumstances where you UNCATLG Suppose we create

Cataloging data sets simplifies your life. You need only remember the data set name. The system remembers the UNIT and VOL. Your installation will probably have standards for cataloging data sets. Many installations require all non-temporary data sets to be cataloged. Check with your installation on what the rules are.

TOPIC 1.8: _____ ____

A JCL PROBLEM _ ___ _______

JCL FOR PROGRAMMERS

Page 24 of 169

To illustrate how job steps are put together to form a complete job, we'll start with a simple example that illustrates the concepts and then move on to a more complicated example that illustrates a language compiler and linkage editor. For this first example, we'll write a step to execute a program named SORT to sort some data in the input stream. Then we'll write a second step that will execute a program named REPORT to read the sorted file and print a report. +---------------------------------------------------------------------------+ | //SORT#1 JOB (2217,6),'SORT',CLASS=A | | //STEP1 EXEC PGM=SORT,REGION=256K | | //SYSPRINT DD SYSOUT=* | | //SORTIN DD * | | Lines of data | | /* | | //SORTOUT DD DSN=&&OUT,DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(6400,(20,10)), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400) | +---------------------------------------------------------------------------+ Let's briefly explain the SORTOUT DD statement as a preview to later sessions where it is described in detail ... //SORTOUT DD DSN=&&OUT,DISP=(NEW,PASS), DSN=&&OUT specifies the data set name. The && marks it as a temporary data set. The data set name is OUT. DISP=(NEW,PASS) specifies the data set disposition. NEW means the data set is to be created and PASS means the data set is to be passed to a following step. // UNIT=SYSDA,SPACE=(6400,(20,10)), UNIT=SYSDA specifies the type of device to write the data set on; each installation assigns its own names. SPACE=(6400,(20,10)) specifies the amount of disk space to allocate to the data set. We'll cover this later.

DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400) This parameter specifies the record type (Fixed Blocked), the Record length (80), and the blocksize (6400). More on this later. Symbolically, our step looks like this: STEP1 SYSPRINT SORTIN +--------------+ =====> Printed output.

//

Lines of data

====> | SORT PROGRAM | SORTOUT +--------------+ =====>

Sorted lines of data--passed to a following step.

Now we'll write the next EXEC statement--one that will execute a program named REPORT. We'll give the step a stepname of STEP2 and assign it a region of 512K. A DD statement is added with a ddname of PRINT to print the output. JCL FOR PROGRAMMERS Page 25 of 169

We'll assume that the REPORT program expects the input DD statement to have a ddname of INPUT.

JCL FOR PROGRAMMERS

Page 26 of 169

+---------------------------------------------------------------------------+ | //SORT#1 JOB (2217,6),'SORT',CLASS=A | | //STEP1 EXEC PGM=SORT,REGION=256K | | //SYSPRINT DD SYSOUT=* | | //SORTIN DD * | | Lines of data | | /* | | //SORTOUT DD DSN=&&OUT,DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(6400,(20,10)), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400) | | //STEP2 EXEC PGM=REPORT,REGION=512K | | //PRINT DD SYSOUT=* | | //INPUT DD DSN=&&OUT,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ Here's an explanation of the INPUT DD statement ... DSN=&&OUT names the data set--the same data set created in STEP1. DISP=(OLD,DELETE) gives the disposition of the data set. OLD means it already exists. DELETE means to delete it at the end of the step.

Symbolically, here is the way our job looks: STEP1 SYSPRINT SORTIN +--------------+ =====> Printed output ====> | SORT PROGRAM | SORTOUT +--------------+ =====> Sorted lines of | data--passed to a | following step | || | || STEP2 \|/ || PRINT +----------------+ INPUT || <===== | REPORT PROGRAM | <============== +----------------+

Lines of data

Printed output

Now let's take a more complicated example that is equally typical--compiling some computer language, link editing subroutines and modules to create a program, and loading and executing the program. We'll compile and run a very simple C language program. We'll use C for our example, but the JCL applies to every computer language. An EXEC statement is written to execute a program named CCOMP. A DD statement is needed to print the compilation listing. The ddname from which the source statements are read is SYSIN. Another DD statement is needed to write the compiled output (i.e., the object module) to disk storage.

JCL FOR PROGRAMMERS

Page 27 of 169

+---------------------------------------------------------------------------+ | //TESTC JOB (2217,6),'C PROGRAM',CLASS=A | | //C EXEC PGM=CCOMP | | //SYSPRINT DD SYSOUT=* | | //SYSIN DD * | | main() { | | int i; | | for (i = 1; i <= 6; i++) | | printf("Value: %d Value squared: %d\n",i,i*i); | | } | | /* | | //SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(TRK,10) | +---------------------------------------------------------------------------+ Let's examine this last statement because it is similar to many you'll write.

Symbolically, the C compiler operates like this: C step SYSIN+-------------+SYSPRINT =====>| Compiler |========> Compilation listing | PGM=CCOMP |SYSLIN | |========> Compiled output +-------------+ (termed object module)

Source statements

//SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS), // UNIT=SYSDA,SPACE=(TRK,10) DSN=&&LOADSET: The && means that the output is a temporary data set. It will exist only for the duration of the job. The data set name (DSN) is &&LOADSET.

set

DISP=(NEW,PASS): The data set disposition (DISP) is NEW, meaning the data set is being created. The PASS means the data is passed on to the next job step. UNIT=SYSDA: SPACE=(TRK,10): Tells what I/O unit to write the data set on. Requests an amount of disk space (10 tracks, here).

JCL FOR PROGRAMMERS

Page 28 of 169

The next step uses the linkage editor: C step SYSIN+-------------+SYSPRINT Source statements =====>| Compiler |========> Compilation listing | PGM=CCOMP |SYSLIN | |========> Compiled output +-------------+ (termed object module) | | LKED step | | Object module SYSPRINT+----------------+SYSLIN \|/ is passed to Printed output <========| Linkage editor |<==========+ next step SYSLMOD| PGM=HEWL | Load module <========| | (executable program) +----------------+ The linkage editor brings in any system subroutines and generally combines things in a way that creates a program, referred to as a load module, that is ready to be executed. Here's what the JCL for the linkage editor step looks like ... +---------------------------------------------------------------------------+ | //LKED EXEC PGM=HEWL | | //SYSPRINT DD SYSOUT=* | | //SYSLIN DD DSN=&&LOADSET,DISP=(OLD,DELETE) | | //SYSLMOD DD DSN=&&GOSET(GO),DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(TRK,(10,1,1)) | +---------------------------------------------------------------------------+ The purpose of the SYSLIN DD statement in the linkage editor step is to read the object module passed from the compiler. The last step, the GO step, executes the program: C step SYSIN+-------------+SYSPRINT Source statements =====>| Compiler |========> Compilation listing | PGM=CCOMP |SYSLIN | |========> Compiled output +-------------+ (termed object module) | | LKED step | | Object module SYSPRINT+----------------+SYSLIN \|/ is passed to Printed output <========| Linkage editor |<==========+ next step SYSLMOD| PGM=HEWL | Load module <========| | (executable program) +----------------+ | | | GO step | \|/ +--------------------+SYSPRINT +====PGM====>| C Program |========> Printed output This PGM parameter | termed the GO step | from program points to this +--------------------+ load module

JCL FOR PROGRAMMERS

Page 29 of 169

Our complete job: +---------------------------------------------------------------------------+ | //TESTC JOB (2217,6),'C PROGRAM',CLASS=A | | //C EXEC PGM=CCOMP | | //SYSPRINT DD SYSOUT=* | | //SYSIN DD * | | main() { | | int i; | | for (i = 1; i <= 6; i++) | | printf("Value: %d Value squared: %d\n",i,i*i); | | } | | /* | | //SYSLIN DD DSN=&&LOADSET,DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(TRK,10) | | //LKED EXEC PGM=HEWL | | //SYSPRINT DD SYSOUT=* | | //SYSLIN DD DSN=&&LOADSET,DISP=(OLD,DELETE) | | //SYSLMOD DD DSN=&&GOSET(GO),DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(TRK,(10,1,1)) | | //GO EXEC PGM=*.LKED.SYSLMOD | | //SYSPRINT DD SYSOUT=* | +---------------------------------------------------------------------------+ The PGM=*.LKED.SYSLMOD is termed a referback. A referback, which can be used in EXEC and DD statements instead of a program name, points to a previous DD statement that describes a program. The general form of the referback is: *.stepname.ddname +---------------------------------------------------------------------------+ | //LKED EXEC PGM=HEWL | | //SYSLMOD DD DSN=&&GOSET(GO),DISP=(NEW,PASS), <-----+ | | // UNIT=SYSDA,SPACE=(TRK,(10,1,1)) | | | . | | | //GO EXEC PGM=*.LKED.SYSLMOD -------------------+ | +---------------------------------------------------------------------------+ The PGM parameter on the GO step tells the system to go back to the LKED step and read the data set created by the SYSLMOD DD statement. A stepname, although optional for most purposes, must be specified for a referback to function properly.

JCL FOR PROGRAMMERS

Page 30 of 169

SESSION 2: _______ __

THE DETAILS OF DATA SETS AND JCL ___ _______ __ ____ ____ ___ ___

TOPIC _____ 2.1 2.2 2.3 2.4

TITLE _____ Data Sets Data Records DCB Sub-parameters and Data Set Labels Concatenating Data Sets NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 31 of 169

TOPIC 2.1: _____ ____

DATA SETS ____ ____

SEQUENTIAL DATA SETS Sequential data sets are made up of records that are ordered sequentially-that is, one record follows another in the order they are entered. For example: DSN=Y2222.DEPT.DATA Records: ASHE, BROWN, BRUCK, COLLINS, ROBERT PETE MIKE JOE 492 501 396 423 5-4683 6-3197 4-2185 3-6284 5 3 6 2 AC04 MF01 AC03 IN04

Each record follows the prior record sequentially. Each individual part of a data set name, such as DEPT or DATA DSN=Y2222.DEPT.DATA, is called a level. in

The last level of the name, DATA here, is termed the data set qualifier by the ISPF/PDF text editor. (TSO terms the lowest level the data set name and all the higher levels the qualifier. We'll use the ISPF/PDF terminology here because you'll use it the most.) Note: The data set naming conventions vary from company to company. with your installation for its rules on naming data sets. Check

The data set qualifier gives you (and a text editor) some idea of the type of data the data set contains. Text editors often align the lines in the proper columns implied by the qualifier. Some qualifiers are: COBOL TEXT CNTL LOAD for for for for COBOL language statements. document/text. JCL statements. load modules.

PARTITIONED DATA SETS Partitioned data sets are the next most popular type of data set. o o o o A partitioned data set (PDS) is made up of several similar sequential data sets grouped together. Each sequential data set is called a member of the partitioned data set. Each member has a unique name. The entire partitioned data set also has a name. Page 32 of 169

JCL FOR PROGRAMMERS

If we wanted to maintain a separate list of names for each department in a company, we could use a partitioned data set instead of several separate sequential data sets. Each department's name list would be a member. An example of a partitioned data set name is: Y2222.STUDENTS.DATA Each sequential data set that belongs to the STUDENTS data set is called a MEMBER. Access to a member file is by member name only. Member names are unique, are 1 to 8 characters long, follow the data set name, and must be enclosed in parentheses. Examples of partitioned data set member names are: Y2222.STUDENTS.DATA(SENIORS) Y2222.STUDENTS.DATA(JUNIORS) Y2222.STUDENTS.DATA(SOPHS) Y2222.STUDENTS.DATA(FRESHMEN) Here is an analogy that further illustrates sequential and partitioned data sets. Suppose we had a four-drawer file cabinet, with a drawer for each class--freshmen, sophomores, juniors, and seniors. Each piece of paper in the file represents a record. A single file drawer represents a sequential data set. The four drawers together are then equivalent to a partitioned data set. Y2222.FRESHMEN.DATA +-------------------------------------+ | AARON | | ABLE | | ANDERSON | | ARTEMUS | | . | | . | | . | | . | | ZENY | +-------------------------------------+ is The file drawer (sequential data set) is named Y2222.FRESHMEN.DATA. a record for each student. There

A partitioned data set is a single data set stored on disk. composed of a directory and its individual members: Partitioned data set +-------------------+ | Directory | |-------------------| | Member | |-------------------| | Member | |-------------------| | ... | |-------------------| | Member | +-------------------+

Each is

<===

The directory contains all all the member names and the locations where they are stored in the data set.

JCL FOR PROGRAMMERS

Page 33 of 169

We'll describe the internals of partitioned data sets in more detail later. A partitioned data set as a file cabinet: Y2222.STUDENTS.DATA _______________ / /| / / | / / | /______________/ | || @ || | || FRESHMEN || | || ___ || | || |___| || | ||____________|| | || @ || | || JUNIORS || | || ___ || | || |___| || | ||____________|| | || @ || | || SOPHS || | || ___ || | || |___| || | ||____________|| | || @ || | || SENIORS || /| || ___ || / / || |___| || / / ||____________||/ / |______________|/ The file cabinet (partitioned data set) is named Y2222.STUDENTS.DATA. The file drawers (members) are named FRESHMEN, SOPHS, JUNIORS, and SENIORS. Each member contains a record for each student in that class. Partitioned data sets are perhaps most often used for program libraries-source, object, and load. The load module created by the linkage editor step of a compile, link edit, go procedure must be stored in a partitioned data set. When direct access storage space is allocated for any data set, the minimum space that can be allocated is one track, which is more than 47,000 bytes on most disk devices. Partitioned data sets can also be used to save storage space in storing several small data sets. One partitioned data set could contain several data sets on a single track. As sequential data sets, each would require at least one full track. However, all partitioned data sets must have the same record format and logical record length, which we'll describe soon. OTHER TYPES OF DATA SETS There are two other types of data sets (we will describe them in greater detail later): direct and VSAM (Virtual Sequential Access Method). Both direct and VSAM data sets permit records to be processed either sequentially or directly. With direct access, records can be read directly, JCL FOR PROGRAMMERS Page 34 of 169

without regard to their location in the data set. If you wanted the 100th record in a data set, you could read it directly (read just that record). TOPIC 2.2: _____ ____ DATA RECORDS ____ _______

RECFM, LRECL, and BLKSIZE Parameters There are several different types of data set records and several different ways to store them. When you use JCL, you often specify three attributes of the records in the data set: o o o RECFM, the record format. is. RECFM indicates what type of record it LRECL indicates the length of a

LRECL, the logical record length. record of data.

BLKSIZE, the blocksize. Several records are usually placed together in a block for efficiency.

You specify RECFM, LRECL, and BLKSIZE as keyword sub-parameters of the DCB parameter on a DD statement. The following statement is typical: //OUT DD DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200), ... DCB stands for Data Control Block. The data control block represents an area in a program where the system keeps information about a data set while a program is executing. Now let's see what RECFM, LRECL, and BLKSIZE really mean. types of records are shown here: The two main

Data: (From 1980 Census) Much of the data manipulated by computers is fixed in length. each record has the same length: CITY SAO PAULO SHANGHAI MEXICO CITY CALCUTTA RIO DE JANEIRO COUNTRY BRAZIL CHINA MEXICO INDIA BRAZIL

That is,

POPULATION 12,578,045 11,000,000 9,200,000 9,165,650 9,011,981

Text: Text usually varies in length. different line length:

That is, each record may have a

JCL FOR PROGRAMMERS

Page 35 of 169

Mr. John Q. Smith The Ajax Company 14 Oak Street Norogrudo, Byelorussian Soviet Socialist Republic

THE LRECL PARAMETER You specify the length of a record with the DCB LRECL sub-parameter. general form is: DCB=(LRECL=length,... LRECL is determined differently for fixed-length and variable-length records. For fixed-length records, LRECL is the length of the record. (Each record has the same length in storage.) For variable-length records, LRECL is the length of the longest record in the data set plus 4. (The extra 4 bytes are added to the front of each record to contain the record length.) That is, if the longest record were 96, you would specify LRECL=100. The extra four bytes placed in front of each record are called the Record Descriptor Word. Fixed-length records waste a lot of storage space if each record isn't filled. With fixed-length data in a fixed-length record, no space is wasted: +-----------------------------------------------------------+ | CITY COUNTRY POPULATION | | SAO PAULO BRAZIL 12,578,045 | | SHANGHAI CHINA 11,000,000 | | MEXICO CITY MEXICO 9,200,000 | | CALCUTTA INDIA 9,165,650 | | RIO DE JANEIRO BRAZIL 9,011,981 | +-----------------------------------------------------------+ The

Variable-length data in a fixed-length record wastes space. +-----------------------------------------------------------+ | Mr. John Q. Smith | +-----------------------------------------------------------+ | The Ajax Company | +-----------------------------------------------------------+ | 14 Oak Street | +-----------------------------------------------------------+ | Norogrudo, Byelorussian Soviet Socialist Republic | +-----------------------------------------------------------+ Variable-length records don't waste the unused space at the end of the record. JCL FOR PROGRAMMERS Page 36 of 169

+-------------------+ | Mr. John Q. Smith | +------------------++ | The Ajax Company | +---------------+--+ | 14 Oak Street | +---------------+-----------------------------------+ | Norogrudo, Byelorussian Soviet Socialist Republic | +---------------------------------------------------+ Variable-length records are more complicated to process because the length of each record must be determined to process it. With fixed-length records, the computer always knows how long each record is. THE RECFM PARAMETER Because of the difference between fixed-length and variable-length records, the operating system must know which it is processing. In JCL, you specify a fixed-length record with RECFM=F and a variable-length record with RECFM=V: DCB=(RECFM=F,... DCB=(RECFM=V,... BLOCKING RECORDS Blocking determines how the records are transmitted and stored on an I/O (Input/Output) device, such as a disk. When records are physically stored on disk or tape, the system leaves a gap between the records so that it can tell where one record ends and the next one begins: +----------+ | Record 1 | +----------+ +----------+ | Record 2 | +----------+ +----------+ | Record 3 | +----------+ +----------+ | Record 4 | +----------+

This inter-record gap can take up as much as or even more space than the record itself. On a typical 3380 disk, the inter-record gap occupies 480 character positions; on a typical tape it occupies 230 character positions. To regain some of the space used for inter-record gaps, you can "block" the records. That is, you can put several records together in a block. Instead of this: +----------+ | Record 1 | +----------+ +----------+ | Record 2 | +----------+ +----------+ | Record 3 | +----------+ +----------+ | Record 4 | +----------+ +----------+ | Record 5 | +----------+

You can block them like this: +----------+----------+----------+----------+ | Record 1 | Record 2 | Record 3 | Record 4 | +----------+----------+----------+----------+ +----------+----| Record 5 | ... +----------+-----

This way, there is only one inter-record gap for every four records. JCL FOR PROGRAMMERS Page 37 of 169

You specify blocked records by adding a B to the RECFM sub-parameter. Fixedlength blocked records are termed fixed blocked and are specified as follows: RECFM=FB You specify variable blocked records as: RECFM=VB THE BLKSIZE PARAMETER In addition to specifying the RECFM as blocked, you must specify the blocksize with: BLKSIZE=size For fixed-length records, the blocksize must be an even multiple of the logical record length. //OUT DD DCB=(RECFM=FB,LRECL=80,BLKSIZE=6160) Notice that DCB is a keyword parameter that consists of a group of other keyword sub-parameters. You could write: DCB=BLKSIZE=80 or DCB=(BLKSIZE=80) To specify several sub-parameters, you

to specify a single sub-parameter. write:

DCB=(RECFM=FB,LRECL=80,BLKSIZE=6160) As with all keyword sub-parameters, you can code them in any order. Variable-length records contain 4 bytes at the front of each record that tell how long the record is (n). In addition, there are another 4 bytes at the front of each block telling the length of the block (m). This is true for both V and VB. (For variable-length blocks, the only difference between V and VB is that only one record is contained in a V (unblocked) block.) RECFM=V: (Each block contains one record.)

| | | | | | | | | | | | |m|n|Record1| |m|n|Record2 | |m|n|Record3| +-----------+ +----------------+ +-----------+ | |<---n--->| |<----m---->| RECFM=VB: (A block may contain several records.)

| | | | | | | | | | | | | | |m|n|Record1|n|Record2|n|Record3| |m|n|Record4|n|Record5| +-------------------------------+ +---------------------+ | |<---n--->| | JCL FOR PROGRAMMERS Page 38 of 169

|<-------------m--------------->| Blocking can save a tremendous amount of data set storage space. Blocked records can also be read and written much faster than unblocked records. The savings in time can significantly reduce run costs. It is far more efficient for the computer to transmit (read or write) a group of records in a block than to transmit the records one at a time. Blocking saves storage space on disk or tape. It does increase the region size needed for a job. For example, if you block half track (a track is the basic unit of storage on a direct access storage device) on a 3380 disk, each buffer occupies 23,476 bytes. (A buffer is an area in the computer's memory into which the system reads a block.) If 5 buffers were allocated to a data set, the buffers alone would require slightly more than 117K bytes. Blocking decreases the CPU time because the system has to do less I/O. takes a considerable amount of CPU time for the system to set up to do I/O. It

For fixed blocked records, the blocksize must be an even multiple of the record length. It is more complicated for variable-length records. For variable-length records: o o Record length must be at least as long as the longest record plus 4. Blocksize must be at least as long as the longest record plus 8 (4 extra bytes for the record length and 4 for the block length). This is true even if the block contains only one record.

The actual record length and block length are stored within those extra 8 bytes. Since the record length is stored in each record, the operating system can tell how long each record is. Of course, the blocksize can also be inefficient if it is too big. The basic unit of storage on disk is a track. On the IBM 3380, a typical disk unit, a track can contain 47,476 bytes. If you have 80-byte records and you choose a blocksize of 24,000 bytes, only one block will fit on a track. 47,476-byte track +------------------------------------------------------------+ | 24,000-byte block | 23,476 wasted bytes | +------------------------------------------------------------+ Approximately 23,000 bytes on each track are wasted because the blocksize is too large. Choosing an appropriate blocksize is very important--and very complicated. SUGGESTED BLOCKSIZES For data records, the suggested blocksize is 6160: DCB=(RECFM=FB,LRECL=80,BLKSIZE=6160) Page 39 of 169

JCL FOR PROGRAMMERS

If the record length (LRECL) isn't 80, choose some multiple of it that results in a blocksize close to 6200, but under 6233. For text records, the suggested blocksize is 6233: DCB=(RECFM=VB,LRECL=255,BLKSIZE=6233) If you are worried more about efficiency than device independence, choose one of the following blocksizes: Device 3350 3380 UNDEFINED RECORDS A third type of record format is used occasionally--.i.undefined records; format. Here's an example: RECFM=U: +------------+ +--------+ +---------------+ +-----------+ +--|Record 1 | |Record 2| |Record 3 | |Record 4 | |... +------------+ +--------+ +---------------+ +-----------+ +--If format is undefined, the system must read each record to determine its length. To specify undefined format, you omit LRECL and specify a BLKSIZE equal to the length of the longest record. DCB=(RECFM=U,BLKSIZE=120) Undefined record format is often used to read input from a terminal device. BLKSIZE 19069 23476 (or as close as you can get under this)

TOPIC 2.3: _____ ____

DCB SUB-PARAMETERS AND DATA SET LABELS ___ _____________ ___ ____ ___ ______

SOURCES OF DCB INFORMATION You don't always have to write the DCB parameter for a data set. Writing a DCB parameter is one of three ways the information can be supplied. The information can be: 1. Coded in the program. In assembler language, you code a DCB macro; in other languages there are statements to set the values. 2. Written in a DCB parameter on the DD statement. You must do this for new data sets if the values are not coded in the program. 3. In the data set label of an existing data set. We haven't discussed data set labels, but you usually don't have to code a DCB parameter on a DD statement for an existing data set. Page 40 of 169

JCL FOR PROGRAMMERS

The system retrieves values in this order, too--for example, values coded in the program can't be changed by JCL, and JCL values override the data set label. After you create a data set, the system will record the DCB values in the label. Here's a DD statement: //OUT DD DSN=data-set-name,UNIT=unit,VOL=SER=volume, // DISP=(NEW,CATLG), // DCB=(RECFM=type,LRECL=length,BLKSIZE=size) In accordance with DISP=(NEW,CATLG), the following information would be stored in the system catalog: DSN=data-set-name UNIT=unit VOL=SER=volume The following would be stored in the data set label: DSN=data-set-name DCB=(sub-parameters) All the above information is also saved for a temporary data set until it is deleted. The data set label is stored on the same tape or disk as the data set itself. On tape, it is stored in front of the data set.

Tape +-----------+---------------------------+ | Data set | Data set | | label | | +-----------+---------------------------+

On disk, the data set label is stored in an area separate from the data set. This area is called the Volume Table of Contents or VTOC.

Disk +----------------+--------------------------------+ | VTOC storage | | | for all data | Storage space for data sets | | sets on volume | | +----------------+--------------------------------+

JCL FOR PROGRAMMERS

Page 41 of 169

When a data set is being created, the sub-parameter values can only come from the program or the DCB parameter. The label for the data set is created later; thereafter, the DCB sub-parameter values are also stored in the label. Pictorially, the DCB sub-parameter values are obtained as follows: Creating data set: Accessing data set: | | | First priority | +---------------------------+ +---------------------------+ | DCB parameters in program | | Data set label | +---------------------------+ +---------------------------+ | | \|/ Second priority \|/ +---------------------------+ +---------------------------+ | DCB parameters in JCL | | DCB parameters in JCL | +---------------------------+ +---------------------------+ | | | Third priority \|/ | +---------------------------+ | | DCB parameters in program | | +---------------------------+ | | \|/ \|/ Values merged and stored Values merged to access in data set label data set Suppose you created a data set with this DD statement: +---------------------------------------------------------------------------+ | //OUTPUT DD DSN=Y0001.TEST.DATA,DISP=(NEW,CATLG), | | // UNIT=DISK,VOL=SER=PACK12, | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=800), | | // SPACE=(800,(100,10)) | +---------------------------------------------------------------------------+ You could then read the data set as if it were unblocked and had 800-byte records by writing this DD statement. +---------------------------------------------------------------------------+ | //INPUT DD DSN=Y0001.TEST.DATA,DISP=OLD, | | // DCB=(RECFM=F,LRECL=800,BLKSIZE=800) | +---------------------------------------------------------------------------+

You could do this because the system actually unites 800-byte physical records in creating the data set. Except for the information in the data set label, the DCB=LRECL=80 is the only way the system has of knowing that there are 10 logical records per physical record. (The DCB parameters in the JCL override those in the data set label.) When you access a cataloged data set, you usually need supply only the DSN and DISP parameters. //ddname DD DSN=data-set-name,DISP=disposition JCL FOR PROGRAMMERS Page 42 of 169

The DSN is used to get the following information from the catalog: UNIT=unit VOL=SER=volume Then the DSN, UNIT, and VOL parameters are used to locate the data set. data set label is then read to obtain the DCB information: RECFM LRECL BLKSIZE and a few more sub-parameters sometimes used. THE DSORG SUB-PARAMETER DSORG specifies the data set organization: DSORG=PS DSORG=PO DSORG=IS DSORG=DA DSORG=DAU Physical Sequential Partitioned Organization Indexed Sequential (an old IBM data set organization replaced by VSAM) Direct Access Direct Access Unmovable (the data set contains absolute track addresses; seldom used because such data sets can never be moved or copied) The

The DSORG is rarely written in JCL because: o o partitioned It is usually supplied by the program creating the data set. And if it is not supplied by the program, it is implied by other JCL parameters, such as one requesting a directory for data set in the SPACE parameter, which we'll cover later. a

THE OPTCD SUB-PARAMETER Another DCB sub-parameter stored in the data set label is OPTCD, which specifies some rather esoteric option codes for the data set. For example: DCB=(OPTCD=CW,... The C requests chained scheduling, which we won't go into in this course, and the W requests a write validity check for write operations on disk--which can minimize errors, but which also slows the writing down. THE BUFNO SUB-PARAMETER The BUFNO DCB sub-parameter lets you specify the number of buffers for a data set. For example, Page 43 of 169

JCL FOR PROGRAMMERS

//INPUT DD DSN=T0004.SOMEDATA,DCB=(BUFNO=3,... allocates three buffers to the data set. Buffer 1 +----------+ | | +----------+ Buffer 2 +----------+ | | +----------+ Buffer 3 +----------+ | | +----------+

Buffers increase the throughput speed. On input, a program can be "reading" (actually moving data internally) from one buffer while the system is filling other empty buffers. On output, a program can be "writing" (actually moving data internally) into one buffer while the system is transmitting data from other filled buffers to the I/O device. You rarely need to code the BUFNO sub-parameter because your installation will assign a default number of buffers to each data set that is best for overall performance. OTHER DCB SUB-PARAMETERS A few more seldom used DCB sub-parameters are kept in the data set label: DEN KEYLEN RKP Density (for tape) Key length for ISAM and direct data Relative key position of the keys

Some non-DCB information is also kept in the data set label. o o o o o TOPIC 2.4: _____ ____ Creation date Generation number for generation data groups--described later Expiration date or retention period from LABEL parameter--described later Password requirements, from the same LABEL parameter Space allocation information, from the SPACE parameter CONCATENATING DATA SETS _____________ ____ ____

CONCATENATING DATA SETS Concatenating data sets consists of treating two or more data sets as if they were placed end to end to form one long data set. Concatenating data sets also helps to make clear the distinction between sequential and partitioned data sets. Suppose we had three separate sequential data sets, like this: JAN.DATA +--------+ | | | | | | +--------+ JCL FOR PROGRAMMERS FEB.DATA +--------+ | | | | | | +--------+ MAR.DATA +--------+ | | | | | | +--------+ Page 44 of 169

To generate a quarterly report, we would need all three data sets. the system to see them like this: +--------+ | | | | | | +--------+ | | | | | | +--------+ | | | | | | +--------+ JAN.DATA

We want

FEB.DATA

MAR.DATA

To concatenate data sets, you write a normal DD statement for the first data set, and then add a DD statement without a ddname for each data set to be concatenated. To concatenate three data sets: JAN.DATA FEB.DATA MAR.DATA we could write this: //IN DD DSN=JAN.DATA,DISP=SHR // DD DSN=FEB.DATA,DISP=SHR // DD DSN=MAR.DATA,DISP=SHR The concatenated data sets must have the same characteristics (DSORG, RECFM, and LRECL). If the BLKSIZE is not the same for all data sets, the data set with the largest BLKSIZE must come first. Here, JAN.DATA will be read first, then FEB.DATA, and last MAR.DATA. CONCATENATING PARTITIONED DATA SETS You can also concatenate entire partitioned data sets. This is often done with program libraries to have the system search in several libraries for a member: +---------------------------------------------------------------------------+ | // EXEC PGM=CREATE | | //STEPLIB DD DSN=LIB1.LOAD,DISP=SHR | | // DD DSN=LIB2.LOAD,DISP=SHR | +---------------------------------------------------------------------------+ The STEPLIB DD is a special statement that tells the system the name of a partitioned data set (library) containing the program you want to execute. Here, the system will first search the directory of the LIB1.LOAD partitioned Page 45 of 169

JCL FOR PROGRAMMERS

data set to find the CREATE program. search the LIB2.LOAD data set.

If it doesn't find it, it will then

You can also concatenate the individual members of a partitioned data set. It will appear to the system as if they formed one long sequential data set. When we write: +---------------------------------------------------------------------------+ | | | // EXEC PGM=REGISTER | | //IN DD DSN=STUDENTS.DATA(FRESHMEN),DISP=SHR | | // DD DSN=STUDENTS.DATA(SOPHS),DISP=SHR | | // DD DSN=STUDENTS.DATA(JUNIORS),DISP=SHR | | // DD DSN=STUDENTS.DATA(SENIORS),DISP=SHR | +---------------------------------------------------------------------------+ Our partitioned data set Is treated by the system that looks like this: as if it were continuous STUDENTS.DATA sequential records +-----------+ +-----------+ | Directory | FRESHMEN | | +-----------+ +-----------+ | FRESHMEN | SOPHS | | +-----------+ +-----------+ | SOPHS | JUNIORS | | +-----------+ +-----------+ | JUNIORS | SENIORS | | +-----------+ +-----------+ | SENIORS | +-----------+ The following rules apply to concatenating data sets: o You can concatenate as many as 255 sequential data sets. They must have the same RECFM and LRECL. If the BLKSIZE is not the same for all the data sets, the data set with the largest BLKSIZE must be placed first to ensure that a large enough buffer is used. You can concatenate as many as 16 partitioned data sets. You can concatenate as many as 255 members of partitioned data sets to form what appears to a program to be one continuous sequential data set. You can't concatenate a combination of sequential data sets and members of partitioned data sets.

o o

JCL FOR PROGRAMMERS

Page 46 of 169

SESSION 3: _______ __

DISK DATA SETS ____ ____ ____

TOPIC _____ 3.1 3.2 3.3 3.4 3.5

TITLE _____ Space Allocation The SPACE Parameter More on the SPACE Parameter Estimating Disk Space Track Overflow and Spanned Records NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 47 of 169

TOPIC 3.1: _____ ____

SPACE ALLOCATION _____ __________

You allocate space by specifying one to three quantities: o o A primary amount of space. This is allocated at the beginning of the job step, and it is usually the amount of space you think your data set will initially need. A secondary amount. This is optional. The system will allocate this amount as many as 15 times if the data set needs additional space. You usually specify a secondary amount to allow for growth. A directory amount. This is required for partitioned data sets only. It sets aside a portion of the primary space to contain the directory of the partitioned data set. This will be explained later.

Let's look at how space is allocated for a sequential data set: 1st extent +------------------------+ Primary amount: | | (1st extent) | Data set storage | | | +------------------------+ Secondary amounts: +--------+ +--------+ | 2nd | | 3rd | | extent | | extent | +--------+ +--------+ +--------+ | 4th | | extent | +--------+ +--------+ | 16th | | extent | +--------+

...

Each amount allocated is termed an "extent." You are allowed 1 primary extent and 15 secondary extents--for a total of 16 extents. Here is how space is allocated for a partitioned data set: 1st extent +-----------+------------------------+ Primary amount: | Directory | | (1st extent) | of | Data set storage | | PDS | | +-----------+------------------------+ Secondary amounts: +--------+ +--------+ | 2nd | | 3rd | | extent | | extent | +--------+ +--------+ As for a sequential secondary extents, for a contain the disk address different place on a disk +--------+ | 4th | | extent | +--------+ +--------+ | 16th | | extent | +--------+

...

data set, you are allowed 1 primary extent and 15 total of 16 extents. (The system has 16 slots to for each data set. Since each extent can be at a pack, there can be only 16 extents.)

JCL FOR PROGRAMMERS

Page 48 of 169

If you allocated a 10-track primary amount and a 10-track secondary amount, you are allowed 1 primary extent and 15 secondary extents, for a total of 160 tracks. Unfortunately, there are times when your allocated. Disk packs do fill up. That's encourage you to: o o Delete data sets you don't need. For data sets that grow, specify a secondary amount small enough so that at any given time the data set uses only as much disk space as it needs. primary amount may not be why your installation will

Also, many installations charge for disk space, so you reduce your computing cost by using only as much disk space as you need. Incidentally, you get a JCL error if the system can't find enough primary space. SECONDARY ALLOCATIONS Once the system allocates the space for your primary amount, it tries to allocate the space for your secondary amounts, as needed, by using additional extents. You may not get all the space you wanted for your 15 secondary amounts for two reasons: o The disk pack may be full. Your secondary amounts are allocated on the same volume as your primary amount, and you have no way of knowing if space will be available on the disk pack in the future. If there isn't enough space on the pack, your job ABENDs with a B37 or E37 completion code. The space on the volume may have become fragmented.

The system always allocates space in contiguous tracks on a disk pack. If space becomes fragmented on a pack, the system will put together as many as 5 smaller separate areas for the allocation: Primary amount--Total of 5 pieces to equal what you asked for. +------------+------------+------------+------------+------------+ | Piece 1 | Piece 2 | Piece 3 | Piece 4 | Piece 5 | | 1st extent | 2nd extent | 3rd extent | 4th extent | 5th extent | +------------+------------+------------+------------+------------+ To allocate your primary amount here, the system had to use 5 separate areas on the disk pack. (We're assuming that space was so fragmented that 5 small pieces were required to come up with your primary amount.) To do this, it also had to use 5 extents, however. (Thus, a single extent is just "an" amount, and is not necessarily equal to the amount you specified.) Now you only have 11 extents left for the secondary allocation.

JCL FOR PROGRAMMERS

Page 49 of 169

Each time the system allocates a specified amount of space, it is allowed to use as many as 5 extents to obtain the space required. If more than 5 are needed, the system terminates the job. This diagram illustrates how space is allocated. Your request:

+--------------+--------------+--------------+-----+---------------+ | Primary |1st secondary |2nd secondary | ... |15th secondary | +--------------+--------------+--------------+-----+---------------+ What might result from this: +--------------+--------------+--------------+---------------------+ |1 |2 |3 |4 |5 | 6 | 7 |8 |9 |10|11|12| | +--------------+--------------+--------------+---------------------+ 1) The system had to piece together 5 fragments to get enough space for the primary amount. 2) It pieced together 2 fragments to get enough space for the first secondary amount. 3) Five more pieces were needed for the next secondary amount. You can now get only 4 more pieces. Looked at another way, the system reserves 16 slots to contain the location on disk of a fragment of contiguous disk storage. You request space as a primary and secondary amount. The system attempts to obtain disk space as follows. Slots (Extents): 1 2 3 ... 16

<=== Points to a contiguous area of storage on disk. When the system attempts to get space, either a primary or secondary amount, it gets from 1 to 5 pieces, which can take up 1 to 5 slots. You never know how much actual space you will get. You get 16 slots total, and that's it.

Try thinking of space allocation this way: 1) You specify a primary amount for a data set. 2) You specify a secondary amount for a data set. many of these you will get. You get all of this. You don't know how

3) The system has 16 slots (extents) for pointing to fragments of storage. 4) Each time the system tries to obtain space, it gets from 1 to 5 fragments that use up from 1 to 5 of the slots. In the best case, if you allocated a 10-track primary amount and a 10-track secondary amount, you could get: 16(10) = 160 tracks In the worst case, with incredibly bad luck, you would get: JCL FOR PROGRAMMERS Page 50 of 169

4(10) = 40 tracks This table shows how the space could be allocated: Primary 1st secondary 2nd secondary 3rd secondary Extents Used 5 5 5 1 ---16 Extents Left 11 6 1 0 ---0 Tracks Allocated 10 10 10 10 ---40

If the system can't piece together enough space in 5 extents to fulfill a secondary amount, it ABENDs your job with a B37 (for a sequential data set) or E37 (for a partitioned data set) completion code. If you don't specify any secondary, and the data set grows larger than the primary amount, your job is ABENDed with a D37 completion code. Allocating disk space is a constant dilemma, because the amount of available space on a pack is beyond your control. Even if space is available in the morning, someone may allocate a large amount of space so that the pack is full in the afternoon. You often go through this cycle: o You allocate a small primary amount and depend on your secondary amount for growth. But then the disk pack fills up and you can't get the amount of secondary space you need or the space becomes fragmented and you can't get all 15 of your secondary amounts. You then allocate a large primary amount, intending to copy your data set and get more space, but there isn't enough contiguous space to fulfill the primary amount required. (If several extents are needed to allocate the primary amount, you won't have gained very much.) You get frustrated.

MULTIVOLUME DATA SETS Space allocation is one of the most difficult aspects of the MVS operating system. For sequential data sets only, you can request that space be allocated on more than one volume. However, this complicates the JCL, and although it reduces the likelihood of space allocation problems, it doesn't eliminate them. Some installations don't allow multi-volume data sets because of the backup and restore problems they present. Multi-volume disk data sets have two important advantages: o You can store the data set even if there isn't enough space on a single volume for it. Page 51 of 169

JCL FOR PROGRAMMERS

You get a primary and as many as 15 secondary extents on the first volume and as many as 16 secondary extents on each additional volume you request.

You can request multiple volumes by listing them with the VOL=SER subparameter. //OUT DD DSN=X0000.TEST.DATA,DISP=(NEW,CATLG), // UNIT=DISK,VOL=SER=(PACK01,PACK02), // SPACE=(TRK,(1,1)) The primary space amount must be allocated on a single volume. Since the primary amount of space must all fit on one volume, don't make it so large that no volume is likely to have the space. Incidentally, you can later expand an existing single-volume data set onto multiple volumes by listing the volumes and using DISP=MOD. //OUT DD DSN=X0000.TEST.DATA,DISP=(MOD,CATLG), // VOL=SER=(PACK01,PACK02) Here is how the system allocates space for data sets on multiple volumes. 1) It first attempts to allocate the primary amount on a single volume. It can look at any eligible volume to find the space, but all of it must be available on one volume. 2) It allocates secondary amounts on the same volume until there is no more space on the volume or until all 16 extents have been allocated. 3) It allocates secondary amounts on the next volume until there is no more space on the volume or until all 16 extents have been allocated. 4) Step 3 continues for as many volumes as you specified. If you later add to the end of a multivolume data set, you do so with DISP=MOD. If the data set was cataloged when you created it, specify the disposition DISP=(MOD,CATLG) You need to specify CATLG so that if the data set extends onto new volumes, these volumes are recorded in the catalog. You can request multiple volumes in two ways: o By naming the volumes: UNIT=unit,VOL=SER=(volume,volume,...,volume) o Or by requesting a number of non-specific volumes: Page 52 of 169

as:

JCL FOR PROGRAMMERS

UNIT=(unit,number) The number can be from 1 to 59. These parameters are for disk data sets. The parameters are usually written differently for tape data sets, as we'll see later. To create a cataloged multivolume disk data set, you usually write the parameters: //ddname DD DSN=data-set-name,DISP=(NEW,CATLG), // DCB=(sub-parameters),SPACE=(whatever), // UNIT=unit,VOL=SER=(volume,volume,...,volume) (To request specific volumes) or // UNIT=(unit,number) (To request non-specific volumes) To read a multivolume cataloged data set, you need write only: //ddname DD DSN=data-set-name,DISP=OLD To extend a multivolume data set, you usually write: //ddname DD DSN=data-set-name,DISP=(MOD,CATLG), // UNIT=unit,VOL=SER=(volume,volume,...,volume) or // UNIT=(unit,number)

TOPIC 3.2: _____ ____ o

THE SPACE PARAMETER ___ _____ _________ The typical SPACE parameter for a sequential data set is coded as: CYL TRK blocksize SPACE=(_________,(primary,secondary)) The CYL sub-parameter requests units in cylinders, TRK requests units in tracks, and blocksize requests units of blocks. The RLSE sub-parameter can be used to release excess space when a data set is closed. SPACE=(units,(primary,secondary),RLSE)

o o

SPACE FOR SEQUENTIAL DATA SETS Sequential data sets are the simplest to write SPACE parameters for. general form of the SPACE parameter for them is: CYL TRK JCL FOR PROGRAMMERS Page 53 of 169 The

blocksize SPACE=(_________,(primary,secondary)) where CYL, TRK, and blocksize are the units of space, primary is the amount primary space, and secondary is the amount of secondary space. of

And, of course, you must write all the appropriate commas and parentheses or you will get a JCL error. Here is a typical SPACE parameter that allocates 10 tracks of primary space and 2 tracks of secondary: SPACE=(TRK,(10,2)) If we write a SPACE parameter as SPACE=(TRK,(10,2)), space is allocated as: Primary +---------+ |10 Tracks| +---------+ 1st secondary +--------+ |2 Tracks| +--------+ 2nd secondary 15th secondary +--------+ +--------+ |2 Tracks| ... |2 Tracks| +--------+ +--------+

REQUESTING SPACE IN CYLINDERS In the SPACE parameter below SPACE=(CYL,(primary,secondary)) the keyword CYL requests space in number of cylinders. A cylinder consists of all the tracks directly above or below each other (in the stack of disks). A cylinder on a 3380 disk pack contains 712,140 bytes. CYL is not often used. You'll need to use it only when: o o You want a large amount of space. On a 3380 disk unit, one cylinder is 712,140 bytes, which is quite large. And when you are concerned about fast access. Since all the tracks in a cylinder lie in the same vertical plane, the read/write heads can access all the tracks in a cylinder without moving. On a 3350 disk, a cylinder is 577,670

Cylinder size is device dependent. bytes. REQUESTING SPACE IN TRACKS In a SPACE parameter like this one SPACE=(TRK,(primary,secondary))

The keyword TRK indicates that requests for space will be in number of tracks. A track on a 3380 disk is 47,476 bytes.

JCL FOR PROGRAMMERS

Page 54 of 169

TRK is used often. After you have allocated a few data sets, you'll become accustomed to estimating size in tracks. It is rather like estimating how long it will take you to drive someplace. With experience, you can usually do this by feel rather than by dividing distance by speed. Track size is device dependent. On a 3380 disk drive, a track is 47,476 bytes. This is enough space to store 539 records with an LRECL of 80 and a BLKSIZE of 6160. On a 3350 disk, a track contains only 19,254 bytes, and with an LRECL of 80 and a BLKSIZE of 6160, you can store only 241 records per track. The problem with allocating space in units of tracks is that the number of records that can fit on a track depends upon the BLKSIZE, the LRECL, and the type of disk unit. In other words, you need to know what your DCB subparameters are, what the track size of your disk pack is, and how many records you have to store. Then, unless you have a feel for how many tracks to allocate, you must do some arithmetic. In any case, you may not know how many records you are going to store. REQUESTING SPACE IN UNITS OF BLOCKSIZE The third way to request space is in units of blocks. For example, you might request space for 10 blocks. If the LRECL were 80 and BLKSIZE were 8000, a block would contain 100 records. The 10 blocks requested would provide space for 1000 records. To request space in blocks, you specify the blocksize instead of TRK or CYL. The advantage of allocating space in units of blocks is that the space allocation is based on the number of records in your data set, and doesn't depend on the track size of the disk. You can estimate the number of records in your data set, calculate the number of records per block, and then calculate the number of blocks needed. You don't have to take track size into consideration other than to choose a blocksize appropriate for the track length. Notice that to compute the number of records per block, you use the LRECL for FB records and an average record length for VB records. The formulas are: records per block = BLKSIZE/LRECL (for FB records) records per block = BLKSIZE/average record length (for VB records) number of blocks needed = estimated number of records/records per block For 1000 fixed blocked records with BLKSIZE=3200,LRECL=80: records per block = 3200/80 = 40 number of blocks needed = 1000/40 = 25 Calculating the number of blocks for variable-length blocked records is slightly different, because you must estimate the average record length. If we had a data set like that below: DCB=(RECFM=VB,LRECL=255,BLKSIZE=3120) and we assumed that the average record length was 50, to store 1000 records, the number of blocks would be calculated as follows: JCL FOR PROGRAMMERS Page 55 of 169

records per block = 3120/50 = 62.4, rounded up to 63 number of blocks needed = 1000/63 = 15.9, rounded up to 16 As you see, there are several problems with allocating space in units of blocks: o o o You may not be able to estimate the number of records you are going to store. For variable blocked records, you must estimate the average record length to estimate the number of records per block. You must still do some arithmetic. (And you thought the computer was supposed to be the one to do the math!)

This is why, as you gain experience, you may prefer to allocate space in units of tracks by estimating. Of course, you could estimate the number of blocks, too. However, tracks work better for estimating because installations almost always provide statistics in units of tracks. A final word on allocating space in units of tracks, cylinders, or blocks. Many installations require that space be allocated only in units of blocks. So that if new disk units with a different track size are installed, users do not have to adjust the SPACE parameter in their JCL. With blocksize, the system calculates the number of tracks needed, taking into consideration the track size of the device. Of course, if the track size changes, all the BLKSIZE parameters will probably need to be changed and all the data sets reblocked. See the Appendix for tables to use in estimating disk space.

USING IEFBR14 TO ALLOCATE SPACE There is a dummy program named IEFBR14 that does nothing except allow you to execute some DD statements to allocate disk space. If we wanted this: Space allocated in units of blocksize, which you get from the DCB parameter. Primary amount equal to 1000 blocks. Secondary amount equal to 200 blocks.

we could code: //TEST#1 JOB // EXEC //OUT DD // // (2215,15),'SPACE',CLASS=A PGM=IEFBR14 DSN=TEST.DATA,DISP=(NEW,CATLG), DCB=(RECFM=VB,LRECL=255,BLKSIZE=6233),UNIT=SYSDA, SPACE=(6233,(1000,200))

The IEFBR14 program is very handy to run by itself to allocate space. Then when you run the real job you know that the space will be available. IEFBR14 is also used to delete data sets. JCL FOR PROGRAMMERS Here's an example: Page 56 of 169

//DELETE JOB (2215,15),'DELETE',CLASS=A // EXEC PGM=IEFBR14 //X DD DSN=TEST.DATA,DISP=(OLD,DELETE) There is one potential problem with using IEFBR14 to preallocate data sets. Some installations delete empty data sets on a periodic basis, usually at night. Since IEFBR14 allocates an empty data set, it may be deleted at some installations if a later job step does not write into it. When you allocate disk space, it is better to allocate too much than too little. If you allocate too little, the data set will be written and you will incur most of the run cost before you overflow the data set. You will waste your entire run. If you allocate too much, you waste some disk space.

RELEASING EXCESS SPACE is, To release excess space when the program is done writing a data set (that when the data set is closed), you add the RLSE option: CYL TRK blocksize SPACE=(_________,(primary,secondary),RLSE) The RLSE option releases the unused tracks (or cylinders if you requested space in cylinders) in either the primary or secondary extent, whichever is the last to be written on. That is, if the secondary allocation were 10 tracks and you'd just allocated a third extent and used 2 tracks of it, the remaining 8 tracks of this third extent would be released. You generally wouldn't use RLSE for a data set that grows over time, because releasing the excess tracks means that a new secondary extent must be allocated each time you add to the data set. You cannot use the IEFBR14 program to release unused disk space for a data set. Excess space is not released because space is only released when a data set is closed, and the null program doesn't open and close the data set. You don't have to write the SPACE parameter when you access an existing disk data set. If you do code a SPACE parameter on a DD statement that accesses a disk data set, the SPACE parameter on the DD statement is used and the SPACE parameter values in the data set label are ignored and not changed.

TOPIC 3.3: _____ ____

MORE ON THE SPACE PARAMETER ____ __ ___ _____ _________

SPACE FOR PARTITIONED DATA SETS When you allocate disk storage for a partitioned data set, you must also specify the directory space. The directory contains the names of all the Page 57 of 169

JCL FOR PROGRAMMERS

members, along with a pointer to where the member is stored within the data set. +-----------+ | Directory | |-----------| | Member | |-----------| | Member | |-----------| | ... | +-----------+ The SPACE parameter for partitioned data sets is identical to that for sequential data sets except for one extra sub-parameter to specify the number of directory blocks. SPACE=(units,(primary,secondary,directory),RLSE) In the SPACE parameter above, "directory" specifies the number of units of space to be reserved for directory blocks, which are carved out of the primary space. Directory blocks contain the names and locations of the members of the partitioned data set. A directory block is 256 bytes. estimate of the directory amount is: One formula for making a conservative

directory = most members you expect data set to contain/5 If you wanted at most 100 members, you could allocate 20 directory blocks. The system would then take the first 5,120 bytes (20 x 256) of your primary space for the directory. SPACE=(6233,(100,10,20)) The general form for the SPACE parameter for partitioned data sets is: SPACE=(units,(primary,secondary,directory),RLSE) To summarize, the general form of the SPACE parameter is then: SPACE=(units,(primary,secondary,directory),RLSE) For sequential data sets, you must specify the units and the primary amount; all the other sub-parameters are optional. SPACE=(6233,100) For a partitioned data set, you must also specify a directory amount: SPACE=(6233,(100,,20)) You can specify a secondary amount if you want, and you can release unused tracks if you want: SPACE=(6233,(100,10,20),RLSE) Page 58 of 169

JCL FOR PROGRAMMERS

OTHER SPACE SUB-PARAMETERS The other positional sub-parameters you can specify for allocating space are rarely used. CYL ALX TRK MXIG blocksize CONTIG SPACE=(_________,(primary,secondary),RLSE,______,ROUND) CONTIG: Allocates space in contiguous tracks and cylinders. MXIG: Allocates the primary space as the maximum contiguous free space on a volume, if it is as large as or larger than the primary space requested. Allocates the five largest contiguous free areas on a volume that together are as large as or larger than the primary space amount. This is done only for the primary space. Any secondary space is allocated as usual.

ALX:

If contiguous space is wanted, you should generally use the CONTIG subparameter. Disk access arm movement is minimized when a data set resides on contiguous space. Hundreds of other users may be accessing data sets on the same volume, however, so there may be access arm movement anyway. There is one other time when you might want to code the CONTIG option. Track overflow fills an entire track with blocks, and if a block doesn't fit evenly into a track, it can be allowed to overflow onto an adjacent track. CONTIG is needed to get adjacent tracks. MXIG and ALX can both allocate an amount of contiguous space that is anywhere from the amount of primary space requested to the entire volume. RLSE can then be used to release the unused space. But, in practice, MXIG and ALX are of limited usefulness and rarely used. CYL ALX TRK MXIG blocksize CONTIG SPACE=(_________,(primary,secondary),RLSE,______,ROUND) ROUND rounds the space up to a full cylinder, starting and ending the data set on a cylinder boundary. ROUND is redundant when space is requested in units of CYL and it is ignored when you request space in units of TRK. You might use it so space can be requested in blocksize units but allocated in cylinders, without regard to the type of device. If you knew how many blocks a data set required and you wanted to allocate space for it in cylinders without worrying about calculating the number of cylinders needed or the type of device the data set was stored on, you could use CONTIG with ROUND: SPACE=(6250,(200,50),,CONTIG,ROUND)

JCL FOR PROGRAMMERS

Page 59 of 169

CONTIG allocates the space on contiguous cylinders, and ROUND gets the minimum number of cylinders needed, regardless of the type of device. Notice that RLSE is a positional parameter whose absence must be indicated by commas. You can code RLSE to release excess space for a data set. following SPACE parameter: SPACE=(6250,(200,50),RLSE,CONTIG,ROUND) Excess cylinders are released. Space is always released in units of tracks or cylinders, depending on how the space was requested. This SPACE parameter is really requesting cylinders. TOPIC 3.4: _____ ____ ESTIMATING DISK SPACE __________ ____ _____ If you code the

To allocate space in blocks, you must know how many records you need to store. Let's assume you are going to store 10,000 fixed-length records. Then you need to know how many records are in a block. (This is BLKSIZE/LRECL for RECFM=FB; it is BLKSIZE/average-record-length for RECFM=VB.) The formula for the number of blocks is: number-of-records/number-of-records-per-block To allocate space in units of blocks, you need to make two calculations: 1) number-of-records-per-block = blocksize/record-length = BLKSIZE/LRECL 2) blocks = estimated-number-of-records/number-of-records-per-block The problem with allocating space in blocks is that you may not know how many records you are going to need to store. Experienced programmers can often tell within a few tracks how much space a data set requires but have no idea how many records it contains. Load modules are a case in point. It's like guessing the length of a book. You could probably tell at a glance roughly how many pages it had, but you would probably have no idea how many lines there were in it. We aren't used to quantifying length in terms of number of lines. Now let's review how we can determine how many tracks our data set would take on a 3380 disk. Assume we had 10,000 records 100 bytes long blocked 64 records per block. A 3380 track is 47,476 bytes long, with an inter-block gap of 523 bytes. Six blocks would fix on a track: 47,476/(523 + (100 * 64)) = 6.86, truncated to 6 Actually, this formula is only approximate. The real formula is even more complicated. Here is how the records and blocks are stored on a track. First, a block contains 64 records: |100 bytes-per-record * 64 = 6400 bytes| +--------------------------------------+ | 1 | 2 | 3 | ... | 64 | JCL FOR PROGRAMMERS Page 60 of 169

+--------------------------------------+ 64 records/block Then, with an inter-block gap of 523 bytes, 6 blocks fit on a track: |6400 bytes|523 bytes|6400 bytes|523 bytes| |6400 bytes|523 bytes|5938 bytes| +----------+---------+----------+---------+-+----------+---------+----------+ | Block 1 | Gap | Block 2 | Gap |.| Block 6 | Gap | Unused | +----------+---------+----------+---------+-+----------+---------+----------+ We arrived at 6 blocks per track with this formula: 47,476/(523 + (100 * 64)) = 6.86, truncated to 6 The formula we used here to calculate the number of blocks per track for the 3380 was only an approximation. The actual formula is more complicated--too complicated to be of practical use. The best way to calculate the number of blocks per track for a 3380 is to use the tables in the Appendix. Calculating the number of blocks per track is only the first step. The next step is to calculate the number of tracks needed: 10,000/(64*6) = 26.04, rounded up to 27. You round up because the system allocates in units of full tracks. truncate, the remainder of your data set cannot be stored. If you

Clearly it's a lot easier to calculate the number of blocks required than to calculate the number of tracks required. And, of course, track size is device dependent. If we'd allocated our data set on a 3350 disk rather than a 3380 disk, the data set would have required 79 tracks rather than the 27 tracks we calculated for the 3380. But you usually don't allocate space in tracks by calculating it. After you gain some experience, you will get a feel for how many tracks it takes to store your data sets. You can use a system utility to examine your data sets and see how many tracks are allocated and how many are used. And the reason you may estimate in units of tracks is that the statistics your installation provides about your data sets are usually in units of tracks. Suppose we want to store 10,000 records that have an LRECL of 15,000. Given this portion of the table in the Appendix for the 3380 showing the number of records per track, the best BLKSIZE is 15,000. Blocksize From --------9077 11477 15477 23477 (bytes) To --------11476 15476 23476 47476 Records per track -----------4 3 2 1 The other option of 30,000 Page 61 of 169

This allows 3 records to be placed on a track. allows only 2 records to be placed on a track. JCL FOR PROGRAMMERS

Given the following information: 10,000 records LRECL is 20,000 BLKSIZE is 20,000 And this portion from the table showing the number of records per track for a 3380: Blocksize From --------9077 11477 15477 23477 (bytes) To --------11476 15476 23476 47476 Records per track -----------4 3 2 1

Two records will fit on a track, so 10,000/2 or 5,000 tracks are needed. The following two space requests would be the same for a 3380: SPACE=(TRK,5000) SPACE=(20000,10000) (Two 20,000 blocks fit on a track.)

They would not be the same for a different hardware device. As a general rule, it is better to allocate space in units of blocksize. But there are times when you may want to allocate space in units of tracks, such as for temporary data sets when you know some number of tracks will be enough or when you've internalized tracks as the unit by which you estimate data set size.

TOPIC 3.5: _____ ____

TRACK OVERFLOW AND SPANNED RECORDS _____ ________ ___ _______ _______

TRACK OVERFLOW As a general rule, BLKSIZE must be less than the capacity of a single track on a direct-access storage device. For instance, the system permits blocks as large as 32,760 bytes, but the largest block that can fit on one 3350 track is only 19,069 bytes. Track overflow lets you overflow a block from one track onto another. This would allow a block of 32,760 bytes in size to overflow into a second 3350 track for storage. You request track overflow by appending a T to the RECFM parameter: RECFM=FT, FBT, VT, or VBT Track overflow has another benefit besides permitting a BLKSIZE greater than the track capacity. Less space is wasted if a block does not fit completely on the remaining available space on a track. |- Block 1 -||- Block 2 -| +-------+ +-------+ +-------+ |XXXXXXX| |XXYYYYY| |YYYY | +-------+ +-------+ +-------+ Page 62 of 169

JCL FOR PROGRAMMERS

Note that: o The BLKSIZE can be greater than the track capacity. o Each track is filled completely until the end of the data set, with no wasted space. The disadvantages of track overflow are: o You must request contiguous tracks in the space allocation. SPACE=(TRK,(primary,secondary),,CONTIG) o The I/O is considerably slower because the system can't take advantage of some internal efficiencies.

SPANNED RECORDS The maximum BLKSIZE permitted by the system is 32,760 bytes. Spanned records permit records to be larger than the BLKSIZE--and consequently greater than the 32,760 byte limit for blocks. With spanned records, one record spans two or more blocks. Spanned records must be variable length, blocked or unblocked. |------ Record 1 -------| Block 1 Block 2 +--------------+ +----+ | XXXXXXXXXXXX | | XX | +--------------+ +----+ |---- Record 2 -----| Block 3 Block 4 +----------+ +----+ | YYYYYYYY | | YY | +----------+ +----+

You specify spanned records by appending an S to the RECFM: RECFM=VS For example: //OUTPUT DD DCB=(RECFM=VS,LRECL=64000,BLKSIZE=23476),... To make sure that the difference between track overflow and spanned records is clear, here is a comparison: Spanned records: RECFM=VS or VBS or RECFM=VBS

Spanned records permit LRECL for variable-length records to be greater than the BLKSIZE--and to be greater than the maximum BLKSIZE of 32760. Track overflow: RECFM=FT, FBT, VT, or VBT

Track overflow permits the BLKSIZE to be greater than the maximum track capacity, and also permits each track to be completely filled.

JCL FOR PROGRAMMERS

Page 63 of 169

SESSION 4: _______ __

JOBSTREAM INPUT AND PRINTED OUTPUT _________ _____ ___ _______ ______

TOPIC _____ 4.1 4.2 4.3

TITLE _____ Standard Parameters Parameters for the 3800 Printer The OUTPUT Statement NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 64 of 169

TOPIC 4.1: _____ ____

STANDARD PARAMETERS ________ __________

Here is an example of the IEBGENER utility program to illustrate printing. The IEBGENER utility program requires four DD statements: // EXEC PGM=IEBGENER,REGION=64K //SYSPRINT DD ... (Tells where to print error messages and other information about execution of the step.) //SYSUT1 DD ... (Describes the input data set being copied.) //SYSUT2 DD ... (Describes the output data set--the copy.) //SYSIN DD ... (Describes a data set containing any control statements.) This example illustrates a couple of things: o someone. o You must know the ddnames required by the program. You get these from a manual, from the program documentation, or by asking In most IBM-supplied programs, such as the utilities and compilers, the following ddnames are used: SYSPRINT -- Program message output. SYSIN -- Control statement or source input. For

the

Printer and input stream data sets are used more than any others. example, when you compile a computer program, you usually have both: // EXEC PGM=compiler //SYSPRINT DD SYSOUT=* (For a printed copy of your compiled statements.) //SYSIN DD * (You place your source language statements here.) THE SYSOUT PARAMETER The general form of the DD statement for printing is: //ddname DD SYSOUT=class

The class is a single letter (A-Z) or digit (0-9) set by your installation to specify the printer.

JCL FOR PROGRAMMERS

Page 65 of 169

In the TSO (Time Sharing Option) system, an installation can reserve an output class to hold the JCL output for viewing rather than immediately printing it. You specify, in the JOB statement, the MSGCLASS output class (below, the letter T). This holds your JCL output (termed the job schedule output) in a queue so you can examine it with a system editor, such as ISPF. //TEST#12 JOB (2215,15),'TEST',CLASS=A,NOTIFY=Y2222,MSGCLASS=T Now you can view your output on a terminal before deciding whether to print or discard it. This can save a lot of paper. The output from your program will only be held if the same output class is also specified in the SYSOUT parameter, however: //SYSOUT DD SYSOUT=T For most of your printed output, however, you needn't specify the particular SYSOUT class. Instead, you can code an asterisk as the class: //SYSOUT DD SYSOUT=* The * means to send the output to the MSGCLASS class specified in the JOB statement or (if you omit the MSGCLASS from the JOB statement) to a default class established by your installation, usually A. THE HOLD PARAMETER The HOLD parameter also holds your output in the output queue instead of printing it. //SYSPRINT DD SYSOUT=A,HOLD=YES The operator must be notified to release your output to print it. (You can also submit job entry system commands to release the output, but they are beyond the scope of this course.) The HOLD parameter is an alternative to the MSGCLASS for holding output for viewing. MSGCLASS works only with TSO, and HOLD works only with the JES2 or JES3 job entry systems. Ask your installation which you should use. THE COPIES PARAMETER If you want multiple copies of your output, you can add the COPIES parameter: //ddname DD SYSOUT=class,COPIES=n The n specifies the number of copies you want to print. reprints the data set to make the copies.) //SYSPRINT DD SYSOUT=A,COPIES=2 THE OUTLIM PARAMETER If you want your output to stop printing after a given number of lines, you can code the OUTLIM parameter: JCL FOR PROGRAMMERS Page 66 of 169 (The system just

OUTLIM=lines You can specify a number of lines from 1 to 16777215. You might use OUTLIM if you want to look at only the first few lines of output, or if you suspect a print loop. THE INPUT STREAM PARAMETER The general form of the DD statement used to describe input from the input stream is: //ddname DD * You would place your lines of data following the DD * statement. the end of the data by writing: /* Actually, you usually don't need the /* because: o A line beginning with // also marks the end of data: //SYSUT1 DD * Your data would go here. //SYSUT2 DD ... <== You mark

The next JCL statement automatically marks the end of data.

An end-of-file also marks the end of data. //SYSUT1 DD * Your data goes here. <== If no lines follow this, the system knows your data ends at the end of the file.

Since your lines of data will almost always be followed by another JCL statement or will be the last lines in your data set, you don't need the /*. In practice, if it is unnecessary, you can either use it or omit it. A null JCL statement can also be used to mark the end of a job. as: // Since the end of a file or another JOB statement also marks the end of job, however, the null statement is seldom required. THE DATA PARAMETER If you have used //ddname DD * to describe data from the input stream, and one of your lines of data contains // in columns 1 and 2, the system will think that the following statement is a JCL statement and assume that the // marks the end of the data. If your data can contain // in columns 1 and 2, use DATA instead of * to describe the data from the input stream: JCL FOR PROGRAMMERS Page 67 of 169 It is coded

+---------------------------------------------------------------------------+ |//SYSIN DD DATA | |//This is a line of data. | |/* | | | | | |The /* is always needed with DD DATA; otherwise, the system will treat your| |JCL statements as part of the data. | | | | | |THE DLM PARAMETER | | | |If your data contains /* in columns 1 and 2, you can tell the system that | |two other characters delimit the data by using the DLM parameter: | | | | | | | +---------------------------------------------------------------------------+ |//SYSIN DD DATA,DLM='!\' | |/* This is a line of data. | |// This is also data. | |!\ | +---------------------------------------------------------------------------+ Note that the data can contain both /* and // in columns 1 and 2. Incidentally, if the system encounters lines of data in the input stream that do not contain /* or // in columns 1 and 2 and don't follow a DD * or DD DATA statement, it assumes a //SYSIN DD * statement. These two job streams are functionally equivalent. //INPUT DD DSN=D0000.JAN.DATA,DISP=SHR 14236 976 //OUTPUT DD DSN=D0000.FEB.DATA,DISP=OLD //INPUT DD DSN=D0000.JAN.DATA,DISP=SHR //SYSIN DD * 14236 976 /* //OUTPUT DD DSN=D0000.FEB.DATA,DISP=OLD THE DUMMY PARAMETER DUMMY is a special parameter that tells the system to ignore the data set. When we write: //ddname DD DUMMY the following occurs: o o If a program reads the data set, it gets an immediate end-of-file. If a program writes the data set, nothing is written.

JCL FOR PROGRAMMERS

Page 68 of 169

DUMMY data sets are often handy for testing programs because the programs can be run without reading or writing the data sets. DUMMY is a positional parameter. If you write it with other parameters, DUMMY must be written first. There is an important restriction on the use of DUMMY- -you may need to add a DCB=BLKSIZE parameter: //SYSIN DD DUMMY,DCB=BLKSIZE=80 The system needs to know the blocksize of all data sets, even dummy ones, and if this isn't specified elsewhere in the program, it must be specified in the DD statement. If you use DUMMY to test programs, it is a good practice to add all the normal DD statement keyword parameters after DUMMY. The parameters will be syntax checked and will be ready to use when a real data set name replaces the DUMMY parameter. THE NULLFILE PARAMETER There is another way to denote dummy data sets in addition to specifying a DUMMY sub-parameter. You can code the DSN as NULLFILE: //ddname DD DSN=NULLFILE,... This is identical to writing: //ddname DD DUMMY,DSN=data-set-name,... You can base your choice entirely on convenience. SPECIAL PROCESSING PARAMETERS The SYSOUT parameter can name a program to process the output. give the name of any special output forms needed. SYSOUT=(class,program,form) program is the name of a program that is to write the output. program must be contained in a system data set named SYS1.LINKLIB. The It can also Use whichever is easier.

form is a 1- to 4-character name set up by your installation for a special form. The system sends a message to the operator telling him or her to mount the form before the job is printed. Suppose you coded this JCL to request a special form: //SYSPRINT DD SYSOUT=(A,,BLUE) The operator receives another message when your job completes printing to mount the original form.

JCL FOR PROGRAMMERS

Page 69 of 169

THE UCS PARAMETER The UCS (Universal Character Set) parameter specifies a character set for some printer models: //ddname DD SYSOUT=class,UCS=(code,FOLD,VERIFY) The UCS parameter is used to request a print chain or train for a character set to be mounted for a 1401, 3203, or 3211 printer. If no UCS parameter is coded, a default character set is used. The code is a 1- to 4-digit code that identifies character set. The following codes for character sets may be generated at your installation: ------PRINTER------3211 3203 1401 A11 H11 G11 --P11 ---T11 --AN HN -PCAN PCHN PN QN RN SN TN XN YN AN HN -PCAN PCHN PN QN RN SN TN XN YN CHARACTER SET 48-character EBCDIC EBCDIC ASCII Alphanumeric Alphanumeric Alphanumeric (PL/I character set) Alphanumeric (PL/I-scientific) FORTRAN/COBOL commercial Text printing Text printing High-speed alphanumeric High-speed alphanumeric

The FOLD sub-parameter prints lower case characters as upper case. It does this by folding the first, second, and third quadrants of the EBCDIC code into the fourth quadrant. For example, the hexadecimal characters 01, 21, 81 (a), and C1 (A) to all print as an upper case A. The VERIFY sub-parameter displays the character set for the operator and asks that it be verified. THE FCB PARAMETER The FCB (Forms Control Buffer) parameter specifies a forms control image for some printer models: ALIGN VERIFY FCB=(image-id,______) The FCB parameter is for 3211 and 3800 Buffer feature. FCB specifies the forms movement of forms on the printer. It may for printers that have this feature. specifies the data protection image. printers that have the Forms Control control image and also controls the also specify a carriage control tape For the IBM 3525 card punch, FCB

The image-id is the image to be loaded into the forms buffer, the carriage control tape wanted, or a data protection image for the 3525 card punch. Five standard images are supplied by IBM: STD1 and STD6 for 6 lines per inch on an JCL FOR PROGRAMMERS Page 70 of 169

11-inch form, STD2 and STD8 for 8 lines per inch on an 8.5-inch form, and STD3 to print 8 lines per inch on a 3800 printer. The ALIGN parameter tells the operator to check the printer forms alignment before printing the data set. ALIGN is ignored for the 3800 printer. The VERIFY parameter also tells the operator to check the printer forms alignment, and also verify that the image displayed on the printer is the one wanted. THE DEST PARAMETER The DEST parameter is used to route the output to a particular destination, such as a local printer. You code: DEST=destination Check with installation. TOPIC 4.2: _____ ____ your installation on the destinations available at your

PARAMETERS FOR THE 3800 PRINTER __________ ___ ___ ____ _______

The IBM 3800 printer is a very fast printer that uses a laser to "print" the characters in whatever type font is selected. It also employs electrophotography to "draw" forms, graphics, logos, or whatever on the output. The characteristics of the printer are: up to 120 lines/page (66 is the usual) up to 204 characters/line (132 is the usual) up to 20,040 lines/minute (very, very fast) Although some of the features of the 3800 printer, such as proportional print, cannot be accessed through JCL, the following parameters can be coded on the SYSOUT DD statement: BURST printed Bursts the output into separate sheets. Specifies that a forms overlay is to be photographically

FLASH

on the output. CHARS MODIFY COPIES Specifies a character set or type font. Specifies a table that allows you to print legends and column headings. Prints a specified number of copies of every page of as many as 8 different output groups.

JCL FOR PROGRAMMERS

Page 71 of 169

For a full understanding of the 3800 printer, you should look at these two IBM manuals: 3800 Printing Subsystem Programmer's Guide Forms Design Reference for the IBM 3800 Printing Subsystem THE BURST PARAMETER BURST=N (for No) is the usual default if the parameter is omitted (although this can be changed by an installation for a particular output class). BURST=N doesn't burst the output--you get the traditional continuous computer fanfold output. If you want the output burst so that you get separate pages of output, you code BURST=Y. THE FLASH PARAMETER The FLASH parameter lets you use electrophotography to create "printed" forms, logos, or just about any graphics image. The operator must mount a photographic form on the printer. If the FLASH parameter is specified, the printer electrophotographically draws this photographic form onto each output page. Photographic Image +------------+ | | | /\ | | /____\ | | | | | | |____| | | | +------------+ Output Page +------------+ | | | /\ | | /____\ | | | | | | |____| | | | +------------+

Flash | ___/ \___ \ / | _ _ _ _ _ _ _ _ _

_ _ _ _ _ _ _ _ _

You specify the form name as: FLASH=name where name is the 1- to 4-character name of the overlay form. installation will have its own overlay form names. Your

If you are printing multiple copies, you can request the forms overlay for the first n copies by coding: FLASH=(name,n) THE CHARS PARAMETER The CHARS parameter lets you select one of the 3800's character arrangement tables, which may be a print font, or a mapping into a different alphabet, such as Cyrillic. You code: CHARS=name Page 72 of 169

JCL FOR PROGRAMMERS

where name is the 1- to 4-character name of a print font provided at your installation. DUMP is a special name used to print SYSUDUMP or SYSABEND storage dumps. Storage dumps are used for debugging, and we'll explain these later. The storage dump is printed on a 204-character print line: //SYSUDUMP DD SYSOUT=A,CHARS=DUMP The CHARS parameter lets you specify from 1 to 4 character arrangement table names. When you specify more than one name, you must also do the following: o In MVS print files, the first character of a print line controls the printer for line spacing, page ejects, etc. In the byte following the printer control character--byte 2 of the output line to be printed-- you must store the number of the table (0, 1, 2, or 3) to use for this line. The number corresponds to the order in which the table names are listed in the CHARS parameter. Each line must contain a number in this byte. Then code DCB=OPTCD=J to tell the system to look in byte 2 for the table number:

//SYSPRINT DD SYSOUT=A,DCB=OPTCD=J,CHARS=(FNT1,FNT2) THE MODIFY PARAMETER With the 3800 printer, an installation can create legends, column headings, and other fixed displays and store them as a copy modification module under a name in a system library. The MODIFY parameter lets you call this module up and print it on your output. You code: MODIFY=name You can use MODIFY in combination with CHARS and specify a separate copy modification module for each character arrangement table. +---------------------------------------------------------------------------+ | //SYSPRINT DD SYSOUT=A, | | // CHARS=(FNT1,FNT2,FNT3), | | // MODIFY=(FMA,1),MODIFY=(FMC,2) | +---------------------------------------------------------------------------+ Here, FMA would be used with FNT2 and FMC with FNT3 (FNT1 is table 0, FNT2 is table 1, and FNT3 is table 2). THE COPIES PARAMETER The COPIES option for the 3800 printer lets you print groups of copies, such as the following: o o 1, One copy of the entire output. A second copy of the entire output that contains 3 copies of page 3 copies of page 2, 3 copies of page 3, and so on. page is printed three times. That is, each Page 73 of 169

JCL FOR PROGRAMMERS

A third copy of the entire output that contains 6 copies of page 1, 6 copies of page 2, and so on.

To do this you would code: COPIES=(,(1,3,6)) You can specify from 1 to 8 groups. The number of copies for each group can be 1 to 254, but the total can't exceed 254 either. COPIES=(,(n1,n2,...,n8)) The system does the following: o o o TOPIC 4.3: _____ ____ Prints n1 copies of page 1, n1 copies of page 2, and so on. Prints n2 copies of page 1, n2 copies of page 2, and so on. Prints n8 copies of page 1, n8 copies of page 2, and so on. THE OUTPUT STATEMENT ___ ______ _________

THE OUTPUT STATEMENT The OUTPUT statement serves two general purposes: o o It lets you specify the SYSOUT parameters for several DD statements with a single OUTPUT JCL statement. It lets you print the output from a single DD statement several times, each with different SYSOUT parameters (even different printers).

To show the usefulness of the OUTPUT statement, suppose you wrote the following DD statement. +---------------------------------------------------------------------------+ | //SYSPRINT DD SYSOUT=A,BURST=Y,COPIES=2, | | // DEST=RMT001,CHARS=XYZ,MODIFY=LOGO, | | // FLASH=FM1 | +---------------------------------------------------------------------------+ If you suddenly realized that all these parameters applied to all of your SYSOUT data sets for a job, you could put them on one OUTPUT statement rather than coding them on all the SYSOUT DD statements. You write the OUTPUT statement as follows: //name OUTPUT parameters The options you have for the parameters are the same as those you have for a SYSOUT DD statement, plus several more. For example: Page 74 of 169

JCL FOR PROGRAMMERS

+---------------------------------------------------------------------------+ | //FORMS1 OUTPUT COPIES=2,CLASS=B,BURST=Y, | | // FLASH=LOGO,CHARS=CURR | +---------------------------------------------------------------------------+ If you want the OUTPUT statement to be available to an entire job, you place it between the JOB and the first EXEC statement. +---------------------------------------------------------------------------+ | //jobname JOB ... | | //name OUTPUT parameters | | //stepname EXEC ... | +---------------------------------------------------------------------------+ If you wanted the OUTPUT statement to be available to just one step in the job, you would place it anywhere after the EXEC statement for the step, but before any SYSOUT DD statements that are controlled by the OUTPUT statement parameters. Placing the OUTPUT statement after the JOB or EXEC statement makes it available for use within the job or step. To activate it, you must add a DEFAULT=YES parameter. For example: //jobname JOB ... //name OUTPUT DEFAULT=YES,parameters The parameters coded on this OUTPUT statement are now automatically applied to all DD statements in the job that contains a SYSOUT parameter. Coding DEFAULT=NO or omitting it altogether results in the OUTPUT parameters not being applied automatically. Here's an example: +---------------------------------------------------------------------------+ | //TEST#10 JOB ... | | //FORM2 OUTPUT DEFAULT=YES,COPIES=2 | | //STEP1 EXEC PGM=ONE | | //SYSPRINT DD SYSOUT=A | | //STEP2 EXEC PGM=TWO | | //FORM3 OUTPUT DEFAULT=YES,COPIES=3 | | //SYSPRINT DD SYSOUT=A | +---------------------------------------------------------------------------+ The SYSPRINT DD statement in STEP1 produces 2 copies. Three copies of the SYSPRINT output for STEP2 would be printed because an OUTPUT statement for a step overrides one for a job. THE OUTPUT PARAMETER Placing an OUTPUT statement between the JOB and the first EXEC statements or between the EXEC and the DD statements is called implicit referencing. The system assumes that the OUTPUT statement applies--if the DEFAULT=YES parameter is coded. Alternatively, you can explicitly reference the OUTPUT statement to use by referencing its name with a referback. (Referbacks are described in detail in a later topic.) For example: JCL FOR PROGRAMMERS Page 75 of 169

//FORM2 OUTPUT COPIES=2 //SYSPRINT DD SYSOUT=A,OUTPUT=*.FORM2 A new OUTPUT parameter refers back to a previous OUTPUT statement. The *.FORM2 referback refers back to the FORM2 OUTPUT statement. Omitting the DEFAULT=YES on the OUTPUT statement means the OUTPUT parameters won't be applied automatically to other SYSOUT parameters. The normal rules for writing the referback apply (you write *.stepname.ddname), and the OUTPUT can be in a prior job step. The OUTPUT parameter on a DD statement can refer to more than one OUTPUT statement. OUTPUT=(referback,referback,...,referback) The output is then printed as directed for each OUTPUT statement. example: Here's an

+---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=ONE | | //FORM1 OUTPUT COPIES=2,DEST=CORP | | //FORM2 OUTPUT COPIES=3,DEST=MFG | | ... | | //STEP4 EXEC PGM=FOUR | | //SYSPRINT DD SYSOUT=A,OUTPUT=(*.STEP1.FORM1,*.STEP1.FORM2) | +---------------------------------------------------------------------------+ The DEST parameter can route the output to different locations. prints 2 copies and FORM2 prints 3. The order of precedence of SYSOUT processing is: o o o o Parameters coded on a SYSOUT DD statement first. Explicit next (OUTPUT=referback used). Step level implicit next. Job level implicit last. FORM1

The OUTPUT statement can be placed in a cataloged procedure, which we'll cover soon, and you can use an OUTPUT parameter to refer back to it. However, in a cataloged procedure, an OUTPUT statement cannot be placed before the first EXEC statement. Using an OUTPUT parameter, you can refer back to any preceding OUTPUT statement in the job stream, even if it is in a cataloged procedure. You just can't refer forward to an OUTPUT statement. THE JESDS (JOB ENTRY SYSTEM DATA SET) PARAMETER Coding the JESDS parameter on the OUTPUT statement lets you tell the system what part of the system-generated output to print: ALL JCL JCL FOR PROGRAMMERS all of the system output the JCL statements only Page 76 of 169

LOG MSG JESDS=___

the job log only the job's system messages only

You can code more than one OUTPUT statement with the JESDS parameter, and the system will print the requested system output for each: //SYS1 OUTPUT JESDS=JCL,COPIES=2 //SYS2 OUTPUT JESDS=MSG,COPIES=3 This prints 2 copies of the JCL and 3 copies of the system messages. Since the JESDS parameter applies to the entire job, any OUTPUT statement on which it is coded must be placed between the JOB and EXEC statements. OTHER OUTPUT STATEMENT OPTIONS You can also code these options on the OUTPUT statement: BURST=Y or N Same as the BURST parameter on the DD statement. CHARS=(table-name,table-name,...,table-name) Same as the CHARS parameter on the DD statement. CKPTLNS=lines Maximum number (0-32767) of lines contained in a logical page. CKPTPAGE=pages Number (0-32767) of logical pages to be printed before taking a checkpoint. CKPTSEC=seconds Number (1-32767) of seconds of CPU time before taking a checkpoint of the SYSOUT data set being printed. CLASS=class Same as the SYSOUT=class parameter. Code CLASS=* to use the MSGCLASS parameter on the JOB statement. The CLASS option requires that you write a null SYSOUT class on the DD statement: //OUT DD SYSOUT=(,),OUTPUT=*.TEST1. COMPACT=compaction-table-name Names a compaction table to use when transmitting from a work station. CONTROL=PROGRAM or SINGLE or DOUBLE or TRIPLE Specifies the line spacing for the printer. PROGRAM specifies that the first character of a record is control character. COPIES=(copies,(group,group,...,group)) Same as the COPIES parameter on the DD statement. DEFAULT=Y or N DEFAULT=Y means the OUTPUT statement can be implicitly referenced SYSOUT DD statements. JCL FOR PROGRAMMERS DEFAULT=N, the default, means that this Page 77 of 169

by

OUTPUT statement will not be implicitly referenced. DEST=destination Same as the DEST parameter on the DD statement. FCB=image-id Same as the FCB parameter on the DD statement. FLASH=(overlay-name,count) Same as the FLASH parameter on the DD statement. FORMDEF=membername Names a library member that contains Print Services Facility statements for the 3800 printer. FORMS=form Same as the third sub-parameter on the SYSOUT=(class,program,form) parameter on the DD statement. GROUPID=group The output group to which the SYSOUT data set belongs. only.) (JES2

control

INDEX=nn Right indexing print position offset (1 to 31) for the 3211 printer.(JES2 only.) LINDEX=nn Left indexing print position offset (1 to 31) for the 3211 printer. (JES2 only.) LINECT=lines Number of lines to print on each page. (JES2 only.)

MODIFY=(module-name,trc) Same as the MODIFY parameter on the DD statement. PAGEDEF=member Same as the FORMDEF parameter except that PAGEDEF member statements specify page format: size, fonts, etc. PIMSG=Y or N Y, the default, prints the Print Services Facility messages with the output listing. N suppresses the messages. PRMODE=LINE or PAGE or mode Process mode for the SYSOUT data set. LINE schedules the data set on a line-mode printer, PAGE schedules the data set on a page-mode printer, and mode (JES2 only) is the 1 to 8 alphanumeric character mode initialized in JES2. PRTY=priority The priority of the printing in the output queue. THRESHLD=limit Number of data sets that are to be grouped together for printing. Page 78 of 169

JCL FOR PROGRAMMERS

TRC=Y or N Specifies whether the data set contains TRC (Table Reference Code) codes. N, the default, means that it does not contain TRC codes. (JES3 only.) UCS=character-set Same as the UCS parameter on the DD statement. WRITER=name Name of external writer to process the SYSOUT data set.

JCL FOR PROGRAMMERS

Page 79 of 169

SESSION 5: _______ __

TAPE DATA SETS ____ ____ ____

TOPIC _____ 5.1 5.2 5.3 5.4

TITLE _____ Storage in Tape Files DD Parameters for Tape The LABEL Parameter for Tapes Unlabeled Tapes NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 80 of 169

TOPIC 5.1: _____ ____

STORAGE IN TAPE FILES _______ __ ____ _____

Disk packs on mainframe computers are large, expensive, and fragile. Tape reels cost as little as $15, can hold vast amounts of data, can survive the postal service, and can be carried around in a briefcase. A typical tape reel might contain 138 million bytes. A comparably blocked 3380 disk pack contains 572 million bytes. Tape, which is an inherently sequential I/O device, can contain only sequential data sets. Tapes are usually stored in a fireproof vault, and a computer operator must retrieve the tape reel and mount it on a tape drive when you want to use it. Tape storage is ideal: o o to For storing large amounts of sequential data. For long-term storage of inactive data sets. If you aren't going

use data sets for some time, you can copy them to tape and free up scarce disk storage space. o o To send data sets from one installation to another. the data sets to tape and mail or carry the tape. You can copy

For critical data sets. You should make backup copies of these data sets on tape. (Your installation may also back up the disk packs onto tape on a regular basis.)

Quite often, tape backups are important to the entire operation of a company. Keeping several generations of backup may be necessary in the event that something disastrous happens to the computer. But remember--no vault is really fireproof--only fire resistant. Floods, earthquakes, and tornadoes can wipe out just about everything. Critical backup needs to be kept in a separate location. There are several advantages of tape storage over disk storage for sequential data sets. However, it may take several minutes to locate and mount a tape. And you may have to wait for an operator to become free to do this. To use a tape, you must tell the computer operator which tape reel you want. The system will then select an available tape drive and tell the operator to mount the tape on it. (Your installation will have its own procedures for assigning tapes and making requests to the operator.) Many installations also have tape management systems with their own set of control statements and parameters. When you are finished, the operator is notified to dismount the tape reel so that other users can have their tapes mounted on the tape drive. No one else can use a tape device while it is assigned to you. Installations assign tapes to users two general ways: o Tapes may be preassigned. In this case, you supply the volume serial number of the tape that was assigned to you on your DD statement when you run your job. Tapes may be assigned when the job is run. In this case, you Page 81 of 169

JCL FOR PROGRAMMERS

refer

usually omit the volume serial number on your DD statement and catalog the data set; the volume serial number of the tape assigned by the operator is stored in the catalog. This lets you later to the data sets on the tape by name without having to specify or even know the volume serial number.

Whether tapes are preassigned or cataloged, an installation will usually have some means of separating jobs that require tape mounts from other jobs. The jobs are usually separated by assigning them to different job classes or by separate job entry statements (these are unique to an installation) for scheduling--so the job isn't run until the tape drive is free. Once a tape has been assigned to you, you can request it through your JCL. If the data sets stored on the tape are cataloged, you needn't specify the tape volume serial number. But if the data set is not cataloged, you must specify the volume serial number. We'll illustrate how tapes are used. Assume that our job has asked the operator to mount a tape for us. The operator is asked to mount the tape on an available tape drive, and execution of our job is suspended until the tape is ready. +-------+ | O O | +-------+ | | | | +-------+ +-------+ | O O | +-------+ | | | | +-------+ +-------+ | O O | +-------+ | | | | +-------+ +-------+ | O O | +-------+ | | | | +-------+

You can mount several tapes at the same time if you wish, if the tape drives are available. The tape is automatically advanced to its starting position, termed the "load point." The load point is marked by a small piece of aluminium tape about 15 feet from the start of the tape reel. +-------------+---+--------------------------------| |///| +-------------+---+--------------------------------/|\ /|\ | +-- Load point of tape | +-- First few feet of tape are fed through the tape drive, onto the takeup spool Data sets are stored on tape in files. The data is written sequentially onto the tape and is followed by a file mark, which marks the end of the file or data set. +-------------+-+----------------------------------| |#| | Data set |#| +-------------+-+----------------------------------/|\ /|\ | | Tape file +-- File mark Page 82 of 169

JCL FOR PROGRAMMERS

Several data sets can be placed on the same tape reel:

JCL FOR PROGRAMMERS

Page 83 of 169

+------------+-+------------+-+------------+-+----| |#| |#| |#| | Data set 1 |#| Data set 2 |#| Data set 3 |#| ... +------------+-+------------+-+------------+-+----/|\ /|\ /|\ | | | File 1 File 2 File 3 When you write a data set on tape, the system always assumes you want the data set stored as file 1 on the tape, unless you specify otherwise with your JCL. It is up to you to keep track of what data sets are stored on tape. Otherwise, you can inadvertently overwrite an existing data set on tape. Besides storing several data sets on one reel of tape, you can also store one data set across several reels of tape: Reel 1: +---------------------------------------------------------------+ | Volume/data set label | Data set | Trailer record | +---------------------------------------------------------------+ Reel 2: +---------------------------------------------------------------+ | Volume/data set label | More of the data set | Trailer record | +---------------------------------------------------------------+ And so on. There's no practical limit on how large a tape data set can be (you can't have more than 9999 volumes). There are two general types of operating system (OS) tapes: labeled and unlabeled. Unlabeled -- Seldom used. Mainly for sending tapes to another installation. +--------+-+----------------+-+-----------------+-+-+ | |/| |#| |#|#| | |/| First file |#| Second file |#|#| +--------+-+----------------+-+-----------------+-+-+ /|\ /|\ +-- Load point End of volume --+ Labeled -- Usually used. +--+-+----------+------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ | |/|Volume |Header|#|First|#|Trailer|#|Header|#|Second|#|Trailer|#|#| | |/|serial no.|record|#|file |#|record |#|record|#|file |#|record |#|#| +--+-+----------+------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ /|\ /|\ +-- Load point End of volume --+ Most installations require you to use labeled tapes. the following advantages over unlabeled tapes: o Labeled tapes offer

The system can check the volume serial number in the tape label against the volume serial number in the JCL to ensure that the operator has mounted the correct tape. Page 84 of 169

JCL FOR PROGRAMMERS

o o

The RECFM, LRECL, and BLKSIZE are stored in the data set label, so you needn't specify them to read a data set. A data set on a labeled tape can be cataloged.

The system needs to know the following things to read or write a tape: RECFM -- Record Format. It is usually F or FB (Fixed-length or Fixed-length Blocked), V or VB (Variable-length or Variable-length Blocked), or U (Undefined). -- Logical Record Length in bytes. -- Blocksize in bytes.

LRECL BLKSIZE

Label type -- The three usual formats are: BLP - Bypass Label Processing. No labels. Don't check to see that there are labels. NL - No Labels. Read the tape to make sure it doesn't contain labels. SL - Standard Labels. File number -Number of the file that contains the data set.

All these are needed to create the tape. For an existing labeled tape, all these except the file number are stored in the data set label on the tape itself. The label type and file number for a tape look like this: Labeled tape: Label type SL (Standard Labels): +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ | |/|Tape| |#| |#| |#| |#| |#| |#|#| | |/|no. |Header|#|File|#|Trailer|#|Header|#|File|#|Trailer|#|#| +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ /|\ /|\ /|\ /|\ Load +-----File number 1 -----+-----File number 2 -----+ point Unlabeled tape: Label type NL (No Labels) +------+-+------------------------+-+-----------------------+-+-+ | |/| File |#| File |#|#| | |/| itself |#| itself |#|#| +------+-+------------------------+-+-----------------------+-+-+ /|\ /|\ /|\ /|\ Load +-- File number 1 File +-- File number 2 point mark Here is a DD statement for a tape data set:

JCL FOR PROGRAMMERS

Page 85 of 169

+---------------------------------------------------------------------------+ | //OUT DD DSN=TEST.DATA,DISP=(NEW,KEEP), | | // UNIT=TAPE,VOL=SER=970216, | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400) | +---------------------------------------------------------------------------+ When a tape is first mounted by the operator, it is advanced to the load point. Unlabeled: +--------+-+----------------+-+-----------------+-+-+ | |/| |#| |#|#| | |/| First file |#| Second file |#|#| +--------+-+----------------+-+-----------------+-+-+ /|\ /|\ +-- Load point End of volume --+ (EOV) Many programming languages also have a REWIND command to rewind the tape. This command returns the tape to the load point. Labeled: +--+-+----------+------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ | |/|Volume |Header|#|First|#|Trailer|#|Header|#|Second|#|Trailer|#|#| | |/|serial no.|record|#|file |#|record |#|record|#|file |#|record |#|#| +--+-+----------+------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ /|\ /|\ +-- REWIND would move If you were originally -+ you back here. positioned here. A disposition of NEW in a DD statement for a tape data set moves the tape to the start of a file. A disposition of MOD moves the tape to the beginning (if the data set doesn't already exist on tape) or the end of a tape file (if it already exists). +--+-+----------+-------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ | |/|Volume |File 1 |#|First|#|File 1 |#|File 2|#|Second|#|File 2 |#|#| | |/|serial no.|header |#|file |#|trailer|#|header|#|file |#|trailer|#|#| +--+-+----------+-------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ /|\ /|\ NEW positions here. -+ +- MOD positions here. DISP=(NEW,KEEP) DISP=(MOD,KEEP) A disposition of OLD also positions to the start of a file. Note that if you write a data set on tape, any following data sets or files on the tape are effectively destroyed. +--+-+----------+-------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ | |/|Volume |File 1 |#|First|#|File 1 |#|File 2|#|Second|#|File 2 |#|#| | |/|serial no.|header |#|file |#|trailer|#|header|#|file |#|trailer|#|#| +--+-+----------+-------+-+-----+-+-------+-+------+-+------+-+-------+-+-+ /|\ OLD also positions here. -+ DISP=(OLD,KEEP) Page 86 of 169

JCL FOR PROGRAMMERS

TOPIC 5.2: _____ ____

DD PARAMETERS FOR TAPE __ __________ ___ ____

You write the usual DD parameters for tape: +---------------------------------------------------------------------------+ | //ddname DD DSN=data-set-name,DISP=(beginning-status,ending-status), | | // UNIT=unit,VOL=SER=volume, | | // DCB=(RECFM=type,LRECL=length,BLKSIZE=size) | +---------------------------------------------------------------------------+ The DISP options have a slightly different meaning for tape than for disk data sets. In addition, there are new parameters and sub-parameters for tapes, which we'll cover in the next topic. And you don't write a SPACE parameter for tapes. For tape (as for disk), BLKSIZE may not exceed 32760 or be less than 18, but that is all. Small blocks waste tape space with the many inter-record gaps and are slower to read. Tape blocks are generally larger than disk blocks for this reason.

THE DISP PARAMETER FOR TAPE PASS OLD CATLG MOD KEEP NEW DELETE DISP=(___,______) OLD, MOD, and NEW are the same as for disk data sets. PASS is the same, but in addition it moves the tape back to the beginning of the data set and keeps the tape mounted between job steps. CATLG, KEEP, and DELETE all cause the tape to be rewound and dismounted. Keep in mind that an reel on the tape drive advance it to the load time) if you write your actual person, the computer operator, must place a tape and press a couple of buttons to thread the tape and point. You can waste the operator's time (and elapsed JCL and you don't keep this in mind.

The first job step that uses a tape causes a message to be displayed on the computer console telling the operator to mount the tape. The job step is held in limbo until the tape is mounted and advanced to the load point. A disposition of PASS keeps the tape on the drive, and no operator intervention is required to use the tape in a later step. Dispositions of DELETE, CATLG, and KEEP cause the tape to be rewound and dismounted. If you use the tape in a later step, the operator will be given another mount message and will have to walk over and ready the tape again. A single tape reel often contains several files that will be processed in a single job. For example, a tape might contain 10 data sets that you wish to copy to disk. Let's assume that you are copying the 10 files to disk in 10 JCL FOR PROGRAMMERS Page 87 of 169

separate job steps in the same job. The best way to do this is to run the 10 job steps as 1 job, and use DISP=(OLD,PASS) on each DD statement. Otherwise the operator may have to intervene with the tape 10 times. If you write DISP=(OLD,KEEP) on a DD statement, the following occurs: o o The tape is rewound and dismounted. any other job that needs it. The drive is made available to

If the next job step requests the same tape, the operator will have to ready the tape drive again. If the tape is allocated on another tape drive, the operator must move the tape to that drive.

If a tape reel contains several files, you should also be concerned about the order in which you process files. If you process the files in the order in which they are stored on tape, no time is wasted while the tape reel spins back and forth to the start of the data sets. There are two ways to keep a tape mounted between job steps. o o Code Code DISP=(whatever,PASS) on the DD statement. VOL=(,RETAIN,SER=volume) on the DD statement. VOL=(,RETAIN) for cataloged data sets.

Either PASS or RETAIN keeps the tape mounted between job steps. Code DISP=(whatever,KEEP) on the last step in which the tape is needed. TEMPORARY AND NON-TEMPORARY DATA SETS Temporary and non-temporary data sets exist for tape just as they do for disk. But with tape, it is the tape reel that is temporary or non-temporary, not the data sets on it. Thus, the distinction between temporary and nontemporary tape data sets depends on manual procedures. o A tape is non-temporary if the operator assigns it to you and reserves it for your use. Non-temporary tapes are often termed "permanent" tapes. A tape is temporary if the operator reassigns the tape (lets other users write on it). Temporary tapes are often termed "scratch" tapes.

When you use a disposition of DELETE for a tape, the data set is not actually deleted. (If the data set was cataloged, its name will be removed from the catalog.) DISP=(OLD,DELETE) Instead, the tape is rewound and unloaded, and the operator receives a message saying that the data set is deleted. Regardless of what you specify in the JCL, tapes are made temporary or non-temporary by the computer operators. Check with your installation on its procedures.

JCL FOR PROGRAMMERS

Page 88 of 169

Non-temporary and temporary (scratch) tape reels are like cassette tapes. You may have some cassettes that you rerecord regularly. You may also have other cassettes that contain albums. You could rerecord these too, but you usually don't. In effect, you decide whether your cassettes are non-temporary or scratch. Computer operators make the same decisions for tape reels, following the procedures at your installation. In order to write on a computer tape, a small plastic ring must be inserted on the tape. Your installation will also establish procedures for requesting the computer operators to insert this ring on the tape reel so that it can be written on. (The operator will "write enable" the tape.)

TAPE LABELS Tape reels are visually identified by an external label, pasted on the tape, If you don't specify a volume serial number, the operator will be requested to assign an available tape. Suppose you wrote a data set on tape with this DD statement: +---------------------------------------------------------------------------+ | //OUT DD DSN=Y2222.CENSUS.DATA,DISP=(NEW,CATLG), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=8000),UNIT=TAPE | +---------------------------------------------------------------------------+ You could later access the data set with this DD statement. //IN DD DSN=Y2222.CENSUS.DATA,DISP=OLD You can catalog tape data sets the same way you catalog disks. The operator here will be asked to assign a tape volume, and the volume serial number will be recorded in the catalog, along with the unit. TAPE STORAGE SPACE It is difficult to visualize how much data a tape can contain. The formula given here calculates the length of tape needed to store data on 6250-bit-perinch density tape. (Most tapes have a density of 6250 bpi.) length in feet = no. records x ((BLKSIZE/density) + ibg) --------------------------------------12 x (BLKSIZE/LRECL)

The ibg (inter-block gap) is 0.6 for 800 and 1600 bpi density, 0.3 for 6250 bpi, and 0.08 for 3480 tape cartidges. (The 3480 tape cartridge is 38,000 bpi.) For example, if LRECL=80, BLKSIZE=8000, and you want to store 100,000 records, on a 6250 bpi tape you need: 100,000((8000/6250) + 0.3) -------------------------12(8000/80) = 131.7 feet of tape

JCL FOR PROGRAMMERS

Page 89 of 169

Since a tape reel is 2400 feet long (a 3480 tape cartridge is approximately 500 feet long), this data set can easily be contained. One final note. Many installations have job entry systems that permit batch jobs to be submitted to a network of computers and computer I/O devices. Among other things, these job entry systems (of which JES2 and JES3 are the most popular) let you submit a job and route the output back to a local printer.

TOPIC 5.3: _____ ____

THE LABEL PARAMETER FOR TAPES ___ _____ _________ ___ _____

The main differences in JCL between data sets on tape and those on disk are: o o You don't need a SPACE parameter to request space for a tape data set as you do disk. You add a LABEL parameter for tape to specify the type of label, the file sequence number on the tape, and perhaps a retention period.

THE LABEL PARAMETER The LABEL parameter is written as follows: LABEL=(file-sequence-number,type) A typical LABEL parameter is written as: LABEL=(1,SL) If you omit the file number, the system assumes you want file 1. following are equivalent: LABEL=(1,SL) LABEL=(,SL) If you omit the LABEL parameter, SL is also assumed, along with file 1. Although there are others, there are only three label types you are likely to use: SL -- Standard labels. The volume serial number appears on the tape before the first file on the tape. Each data set you write causes three actual files to be written--a header file, your data set, and a trailer file. -- No labels. For reading or writing unlabeled tapes. ABENDs the job if the tape is labeled. The system Thus, the

NL BLP

-- Bypass label processing. Also reads or writes unlabeled tapes, but allows a labeled tape to be overwritten or read as unlabeled. Page 90 of 169

JCL FOR PROGRAMMERS

STANDARD LABELS (SL) //OUT DD LABEL=(2,SL),... Label type SL (Standard Labels): +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ | |/|Tape|Header|#|File|#|Trailer|#|Header|#|File|#|Trailer|#|#| /|\ /|\ | | Load File mark point Suppose you had this tape: +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ | |/|Tape|Header|#|File|#|Trailer|#|Header|#|File|#|Trailer|#|#| | |/|no. | 1 |#| 1 |#| 1 |#| 2 |#| 2 |#| 2 |#|#| +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ /|\ /|\ | | Load File mark point Before you can write file 3, file 2 must already exist on the tape. Since tape is sequential, a file must exist on a tape before the file following it can be written. The system does the following for a labeled tape: 1) Checks the tape number following the load point against what you specified in the VOL=SER=volume parameter. 2) If you are writing a tape, the system writes the DSN and DCB information in the header file. If you are reading a tape, the system checks the DSN in the header file against your DSN parameter, and obtains DCB information as necessary from the header. There is another advantage to using tapes with standard labels. The data set has a standard data set label, like that for disk data sets. The DCB information is stored in the data set label. The tape label is actually the first file on the tape. It contains the volume serial number. It acts as a sort of safety device. The volume serial number on the tape label is the same as the one pasted on the tape reel, but in case an operator inadvertently mounts the wrong tape reel, the system will double-check by reading the first tape file and comparing the volume serial number it contains with the VOL=SER=volume you supply on your JCL. This means that with labeled tapes you can't accidentally write on someone else's tape, and, more important, someone else can't accidentally write on your tape. The volume serial number of a labeled tape will be written on the tape for you, as a rule, and your installation will have procedures for assigning tapes. Page 91 of 169

JCL FOR PROGRAMMERS

Suppose you wrote a data set on file 1 of a labeled tape with this DD statement: +---------------------------------------------------------------------------+ | //OUT DD DSN=TEST.DATA,DISP=(NEW,CATLG), | | // UNIT=TAPE,VOL=SER=972216,LABEL=(1,SL), | | // DCB=(RECFM=FB,LREXL=120,BLKSIZE=12000) | +---------------------------------------------------------------------------+ You could later read this data set with the following DD statement. //IN DD DSN=TEST.DATA,DISP=OLD,LABEL=(1,SL) You can read the data set because the UNIT and VOL are obtained from the catalog and the DCB information is contained in the data set label on tape. CATALOGING TAPE DATA SETS When you catalog a data set, the file number of the data set on tape is also stored in the catalog (but the label type is not). Likewise, the file number is carried along when you PASS a data set on tape. You could omit this LABEL parameter entirely: LABEL=(file-sequence-number,SL) the when you read a cataloged data set on a labeled tape. data set with: //ddname DD DSN=data-set-name,DISP=OLD Although the label type isn't saved in the catalog, SL is assumed if you omit the LABEL parameter. And the file number is saved in the catalog, so you can omit the LABEL parameter. Check with your installation on any rules it has for cataloging and naming data sets on tape. THE EXPDT AND RETPD SUB-PARAMETERS To write on a tape, regardless of the type of label, the operator must "write enable" the tape by inserting a write enable ring. Your installation will establish procedures outside of the JCL for doing this. Another way to protect data set on tape is to use an expiration date. If you specify an expiration date for the data set, the data set can't be modified or deleted until that date. You write: LABEL=(file-sequence-number,type,EXPDT=yyddd) The yy is the year (89, 90, etc.) and ddd is the Julian date--day of the year. Actually, you can specify the EXPDT sub-parameter for both tape and disk data sets. The result is: o Before the expiration date, the data set cannot be modified, Page 92 of 169 You could retrieve

JCL FOR PROGRAMMERS

overwritten, or deleted. o After the expiration date, the data set becomes like any other data set--it can be modified, overwritten, or deleted.

As an alternative to specifying the expiration date, you can specify the number of days to retain a data set. To do this, use the RETPD=days subparameter: LABEL=RETPD=30 The retention period here is 30 days. The choice between EXPDT and RETPD can be based on convenience. They accomplish the same thing. Data sets on tape must be written in sequential order: 1, 2, 3, etc. You can't skip file numbers. You can overwrite a file, but any higher-numbered files are destroyed. That is, if you have files: 1, 2, 3, 4, 5 and you rewrite file 2, you also destroy files 3, 4, and 5. You can read tape data sets in any order, but it saves a lot of tape spinning if you read them in the order in which they appear on the tape. For completeness, two other sets of positional parameters are sometimes used: SL NL NOPWREAD IN RETPD=days BLP PASSWORD OUT EXPDT=yyddd LABEL =(file,___,________,___,___________) PASSWORD - Coded when the data set is created to permit a password to be assigned to the data set. Thereafter the operator must supply the password whenever this data set is opened or deleted. - Same as PASSWORD, except that the data set can be opened to be read without the password. The password is needed only to overwrite or extend it. - The data set can only be read. Used only for FORTRAN, because FORTRAN opens all data sets for input/output, so unless IN is coded, the write-enable ring must be inserted for a tape to be read. - Opposite of IN. The data set is only written.

NOPWREAD

IN

OUT

PASSWORD and NOPWREAD can also be coded for disk data sets.

JCL FOR PROGRAMMERS

Page 93 of 169

TOPIC 5.4: _____ ____

UNLABELED TAPES _________ _____

About the only use of unlabeled tapes today is for sending data from one installation to another. Most software vendors distribute their software on unlabeled tapes. Two reasons the tapes sent from one installation to another are unlabeled are: o the Installations may have strict rules for the volume serial numbers assigned to tapes, and they might not accept a labeled tape from outside. The NL (no labels) and BLP (bypass label processing) sub-parameters cause the system to do the following: NL it -- Whether you are reading or writing, the system first reads the first record off the tape to see if it is labeled. If it is, terminates the job. Otherwise, it positions to read or write the tape. No labels are written on the tape or read from the tape. BLP -- Operates identically to NL except that no check is made to see If the tape is labeled. This means you can overwrite a labeled tape or read a labeled tape as if it were unlabeled.

You write the NL and BLP sub-parameters as follows in order to write file 3: //OUT DD LABEL=(3,NL) or //OUT DD LABEL=(3,BLP)

In either case, the tape looks like this: +--------+-+----------+-+----------+-+-+ | |/| File 1 |#| File 2 |#|#| | |/| itself |#| itself |#|#| +--------+-+----------+-+----------+-+-+ /|\ /|\ | +- You start Load point writing here The file is positioned to the physical file on the tape. No labels are read or written. Files 1 and 2 must already be written for you to write file 3. Functionally, the difference between NL and BLP is that NL causes the job to be terminated if you attempt to read or write a labeled tape. Thus, NL protects against inadvertent attempts to read or overwrite a labeled tape. Procedurally, NL and BLP are usually treated much differently. Because of the risk that someone might overwrite a labeled tape, many installations disable the BLP feature so that it cannot be used under ordinary circumstances. Here's where BLP and NL differ. With BLP, you can read or write a labeled tape as if it were unlabeled: Page 94 of 169

JCL FOR PROGRAMMERS

+-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ | |/|Tape|Header|#|File|#|Trailer|#|Header|#|File|#|Trailer|#|#| | |/|no. | 1 |#| 1 |#| 1 |#| 2 |#| 2 |#| 2 |#|#| +-+-+----+------+-+----+-+-------+-+------+-+----+-+-------+-+-+ /|\ /|\ | | Load File mark point With BLP, you can read the tape label, header records, trailer records, or the file as data. If you tried to write file 1 of this tape, the following would occur: BLP: The tape number and everything following it would be overwritten. The main use of BLP is to overwrite a labeled tape or blank tape. NL: unlalabeled A JCL error would result because the system first reads the tape to make sure it isn't labeled. The main use of NL is to read beled tapes and to write them without fear of overwriting a tape. Suppose you wrote a data set on a tape with this DD statement: +---------------------------------------------------------------------------+ | //OUT DD DSN=TEST.DATA,DISP=(NEW,KEEP),UNIT=TAPE,VOL=SER=862543, | | // LABEL=(1,SL),DCB=(RECFM=FB,LRECL=120,BLKSIZE=12000) | +---------------------------------------------------------------------------+ Then you forgot the data set name, TEST.DATA. Since the system checks the DSN against the data set label for a labeled tape, you need the DSN. You could retrieve it by writing: +---------------------------------------------------------------------------+ | //IN DD DISP=OLD,UNIT=TAPE,VOL=SER=862543, | | // LABEL=(2,BLP),DCB=(RECFM=FB,LRECL=120,BLKSIZE=12000) | +---------------------------------------------------------------------------+ You can omit the DSN when reading an unlabeled tape, but you must supply any needed DCB information. File 2 of an unlabeled tape is file 1 of a labeled tape. You can read the DSN in the file 1 header. Even if your installation normally uses standard-labeled tapes, there are three instances in which you might want to use NL or BLP. o To read a tape label, a data set label (a file header), or a data set on a standard-labeled tape if you forget the data set name. (Only BLP will do this.)

To write an unlabeled tape to be sent to another installation. It is usually better to send an unlabeled tape, because a labeled tape might not conform to the numbering system of the other installation. (Even worse, the volume serial number might be the same as that on an existing tape.) NL should be used for this. JCL FOR PROGRAMMERS Page 95 of 169

To read an unlabeled tape sent from another installation. NL should be used for this.

Most installations use labeled tapes, and so you use BLP only if you forget a data set name. In the few instances where you might need to read or write unlabeled tapes, you will most likely use NL. One word of caution about NL: o Whether you are reading or writing a tape, the system first reads the first file on tape, up to the first end-of-file mark, to determine if it is a labeled tape.

If you try to read a brand new blank tape with NL, the system attempts to read instead or have the operators write an end-of-file marker at the beginning of the tape. You cannot use NL to write a tape that cannot be read. That is, you couldn't use NL to overwrite an old 800-bpi density tape if your tape drives cannot read 800 bpi. For both NL and BLP, you need to specify the full DCB information, including RECFM, LRECL, and BLKSIZE, even when reading an unlabeled tape.

JCL FOR PROGRAMMERS

Page 96 of 169

SESSION 6: _______ __

USING CATALOGED PROCEDURES _____ _________ __________ NEXT | TOP | PREVIOUS

Most of your use of JCL will be through cataloged procedures. A cataloged procedure is a set of JCL that is stored in a library. You use the EXEC statement to invoke the cataloged procedure instead of writing all the JCL yourself. Most of the cataloged procedures you'll use are supplied with the operating system or written by the support people at your installation. Cataloged procedures are usually provided for: o o o The language compilers, such as those for PL/I, COBOL, FORTRAN, and assembler language. The IBM utility programs. Application programs used by several people. They have

Cataloged procedures are usually stored on disk in a library. this general format: //procedure PROC // JCL statements <== Names the cataloged procedure.

You execute the JCL statements contained in the cataloged procedure by writing: // EXEC procedure If the COPY cataloged procedure consisted of: +---------------------------------------------------------------------------+ | //COPY PROC | | //STEPA EXEC PGM=ONE | | //STEPB EXEC PGM=TWO | +---------------------------------------------------------------------------+ And you submitted this job: +---------------------------------------------------------------------------+ | //TEST#1 JOB (2215,13),'A JOB',CLASS=A | | //STEP1 EXEC PGM=CREATE | | //STEP2 EXEC COPY | +---------------------------------------------------------------------------+ The cataloged procedure would be invoked, with the same result as if you had written: +---------------------------------------------------------------------------+ |//TEST#1 job (2215,13), 'A JOB' ,CLASS=A | |//STEP1 EXEC PGM=CREATE | |//STEPA EXEC PGM=ONE | |//STEPB EXEC PGM=TWO | +---------------------------------------------------------------------------+ JCL FOR PROGRAMMERS Page 97 of 169

OVERRIDING EXEC STATEMENTS To change an EXEC statement within a cataloged procedure, you override it by writing: //stepname EXEC procedure,parameter.stepname-in-proc=value Suppose this EXEC statement in a cataloged procedure named COBCLG already has a REGION parameter: +---------------------------------------------------------------------------+ | //COBCLG PROC | | //COB EXEC PGM=IKFCBL00,REGION=200K | +---------------------------------------------------------------------------+ You can override the existing REGION in the COB step with: // EXEC COBCLG,REGION.COB=400K The REGION parameter in the COB step in the cataloged procedure is replaced for this job execution. The EXEC will act as if it were: //COB EXEC PGM=IKFCBL00,REGION=400K The general form for overriding a parameter on an EXEC statement within a cataloged procedure is: //stepname EXEC proc,parameter.stepname-in-proc=value The parameter you write overrides (replaces) the same parameter within the procedure. If the parameter doesn't exist in the procedure, your override is added. Note that when you override a cataloged procedure, the override applies just to that execution of the job. The cataloged procedure itself isn't changed. You can add or override several parameters on the EXEC at once. You can override the EXEC statements in a cataloged procedure for several steps at once, but you must override them step by step in the order they appear in the procedure: // EXEC procedure,parameter.step1=value,parameter.step2=value, ... Any overrides in the wrong order are ignored without a JCL error. In the COBCLG cataloged procedure here, the region size of the COB step is set to 512K and the region size of the GO step to 128K. (The COB step comes before the GO step in the procedure.) // EXEC COBCLG,REGION.COB=512K,REGION.GO=128K A typical statement to execute a cataloged procedure might look like this: // EXEC COBCLG, // TIME.LKED=(,5), // REGION.GO=128K

JCL FOR PROGRAMMERS

Page 98 of 169

The three steps in the procedure, COB, LKED, and GO, are overridden. Just be sure to override steps in the order in which they appear in the cataloged procedure. Suppose you overrode the EXEC statement for a cataloged procedure, but did not specify which step to override: //EXEC COBCLG,REGION=512K The system overrides the first EXEC in the cataloged procedure. OVERRIDING DD STATEMENTS IN CATALOGED PROCEDURES We've seen overridden by: that the EXEC statement in a cataloged procedure can be

//stepname EXEC procedure,parameter.stepname-in-proc=value,... You can also override or add DD statements to a step within a cataloged procedure by coding: //stepname-in-proc.ddname DD ... Here is a typical cataloged procedure named FORTCLG (FORTran Compile, Link edit, and Go): +---------------------------------------------------------------------------+ | //FORTCLG PROC | | //FORT EXEC PGM=FORTVS,REGION=1280K | | //SYSPRINT DD SYSOUT=A | | //SYSLIN DD DSN=&&LOADSET,DISP=(MOD,PASS),UNIT=SYSSQ, | | // SPACE=(2960,(100,0)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=2960) | | //LKED EXEC PGM=HEWL,REGION=128K,COND=(4,LT) | | //SYSLIB DD DSN=SYS1.VFORTLIB,DISP=SHR | | //SYSLMOD DD DSN=&&GOSET(MAIN),DISP=(MOD,PASS),UNIT=SYSDA, | | // SPACE=(1024,(200,0,1),RLSE) | | //SYSPRINT DD SYSOUT=A | | //SYSUT1 DD UNIT=SYSDA,SPACE=(1024,(200,0),RLSE) | | //SYSLIN DD DSN=&&LOADSET,DISP=(OLD,DELETE) | | // DD DDNAME=SYSIN | | //GO EXEC PGM=*.LKED.SYSLMOD,COND=(4,LT),REGION=128K | | //FT04F001 DD DDNAME=SYSIN | | //FT06F001 DD SYSOUT=A | | //FT07F001 DD SYSOUT=B | | // PEND | +---------------------------------------------------------------------------+ To execute the FORTCLG procedure, you could code: But now you need to supply the FORTRAN source statements to the FORT step for compiling. For a cataloged procedure, you write a DD statement override as follows: //stepname-in-proc.ddname DD parameters

JCL FOR PROGRAMMERS

Page 99 of 169

You name the step in the procedure that you are writing the DD statement for. For example, you would write: +---------------------------------------------------------------------------+ | //FORT#1 JOB (2215,13),'FORTRAN',CLASS=A | | // EXEC FORTCLG | | //FORT.SYSIN DD * <== This SYSIN DD statement is | | FORTRAN statements placed here added to the FORT step in | | /* the FORTCLG cataloged | | procedure. | +---------------------------------------------------------------------------+ To add a DD statement to a step within a cataloged procedure, you write: // EXEC procedure //stepname-in-proc.ddname DD parameters The DD statement is added only for the job execution. The cataloged procedure itself isn't changed. Suppose you have this procedure: +---------------------------------------------------------------------------+ | //COPY PROC | | //STEPA EXEC PGM=ONE | | //STEPB EXEC PGM=TWO | +---------------------------------------------------------------------------+ You invoke the procedure with: // EXEC COPY //STEPB.SYSIN DD * The system treats this as if we had submitted: +---------------------------------------------------------------------------+ | //STEPA EXEC PGM=ONE | | //STEPB EXEC PGM=TWO | | //SYSIN DD * <== Added | +---------------------------------------------------------------------------+ Note that when you override a parameter on an EXEC statement, the parameter comes first, followed by the stepname. //STEP1 EXEC COBCLG,REGION.stepname-in-proc=300K But you write the stepname first when you override a DD statement: //stepname-in-proc.ddname DD ... +---------------------------------------------------------------------------+ | //COMP PROC | | //STEP1 EXEC PGM=COMPUTE | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS),UNIT=SYSDA, | | // SPACE=(6400,(100,10)) | | //STEP2 EXEC PGM=PRINT | | //IN DD DSN=&&TEMP,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ Page 100 of 169

JCL FOR PROGRAMMERS

When we write: +---------------------------------------------------------------------------+ | // EXEC COMP | | //STEP1.SYSPRINT DD SYSOUT=A | +---------------------------------------------------------------------------+ The system adds SYSPRINT to the end of STEP1 and treats this job as if we had entered: +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=COMPUTE | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS),UNIT=SYSDA, | | // SPACE=(6400,(100,10)) | | //SYSPRINT DD SYSOUT=A <== Added. | | //STEP2 EXEC PGM=PRINT | | //IN DD DSN=&&TEMP,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ You can also "override" DD statements in the cataloged procedure. That is, you can replace or change a DD statement within a procedure. Suppose, in this procedure, we want to change the unit to SYSSQ in the OUT DD statement. +---------------------------------------------------------------------------+ | //COMP PROC | | //STEP1 EXEC PGM=COMPUTE | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS),UNIT=SYSDA, | | // SPACE=(6400,(100,10)) | | //STEP2 EXEC PGM=PRINT | | //IN DD DSN=&&TEMP,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ To override the UNIT parameter in the OUT DD statement, you write: +---------------------------------------------------------------------------+ | // EXEC COMP | | //STEP1.OUT DD UNIT=SYSSQ | | | +---------------------------------------------------------------------------+ Only the UNIT parameter is changed. The first rule for adding and overriding DD statements in a cataloged procedure is this: o You must override DD statements in the order they appear in the cataloged procedure. That is, if the procedure is: //X //A PROC EXEC PGM=B

You can write: // EXEC X //A.ONE DD ... //A.TWO DD ... JCL FOR PROGRAMMERS Page 101 of 169

But you shouldn't write: // EXEC X //A.TWO DD ... //A.ONE DD ... You can only override cataloged procedure. DD statements in the order they appear in the

Next rule for adding and overriding DD statements in cataloged procedures: o Any added DD statements must follow the overridden DD statements within a step.

This means that you must write DD statements by step in this order: //stepname.ddname DD parameters <== First, any DD statements with a ddname that matches a ddname in the step. <== Then any DD statements with ddnames not in the step.

//stepname.ddname DD parameters

You must override and add all DD statements for the first step, then the second step, and so on. +---------------------------------------------------------------------------+ | //TESTIT EXEC COMP | | //STEP1.OUT DD UNIT=SYSSQ | | //STEP1.SYSPRINT DD SYSOUT=A | | //STEP2.IN DD DISP=(OLD,PASS) | +---------------------------------------------------------------------------+ These statements are valid because the STEP1 DD statement is overridden before the new statement is added, and then the STEP2 DD statement is overridden. Next rule for adding or overriding DD statements in cataloged procedures: o You can add or replace parameters on a DD statement. The order in which you write the individual parameters doesn't matter.

If this were our procedure: +---------------------------------------------------------------------------+ | //COMP PROC | | //STEP1 EXEC PGM=COMPUTER | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS),UNIT=SYSDA, | | // SPACE=(6400,(100,10)) | +---------------------------------------------------------------------------+ We could override the OUT DD statement with DSN and DISP: //STEP1.OUT DD DSN=Y2222.TEST.DATA,DISP=(NEW,CATLG) Page 102 of 169

JCL FOR PROGRAMMERS

or: //STEP1.OUT DD DISP=(NEW,CATLG),DSN=Y2222.TEST.DATA Last rule for adding or overriding DD statements in cataloged procedures: o To remove a parameter from a DD statement in a procedure, write just: //stepname-in-proc.ddname DD parameter= For example, suppose we had this procedure: +---------------------------------------------------------------------------+ | //COMP PROC | | //STEP1 EXEC PGM=COMPUTE | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS), | | // UNIT=SYSDA,VOL=SER=PACK10, | | // SPACE=(6400,(100,10)) | +---------------------------------------------------------------------------+ To remove the VOL parameter from the OUT DD statement, you would write: +---------------------------------------------------------------------------+ | // EXEC COMP | | //STEP1.OUT DD VOL= | +---------------------------------------------------------------------------+ Suppose you had this cataloged procedure: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=ONE | | //ONE DD ... | | //TWO DD ... | +---------------------------------------------------------------------------+ Then suppose you overrode the DD statements in the wrong order: +---------------------------------------------------------------------------+ | // EXEC TEXT | | //STEP1.TWO DD ... | | //STEP1.ONE DD ... | +---------------------------------------------------------------------------+ The STEP1.ONE DD statement is ignored. The system adds the STEP1.ONE DD statement to the end of the step. But when a step has two DD statements with the same name, the first is used. Thus, the STEP1.ONE DD statement is ignored.

JCL FOR PROGRAMMERS

Page 103 of 169

SESSION 7: _______ __

JOB STEPS ___ _____

TOPIC _____ 7.1 7.2 7.3 7.4

TITLE _____ The PARM Parameter Backward References Passing Data Sets The COND Parameter NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 104 of 169

TOPIC 7.1: _____ ____

THE PARM PARAMETER ___ ____ _________

This topic describes the PARM parameter, which you can use to pass information to a program. //stepname EXEC PGM=program,PARM='value,value,...,value' The PARM parameter passes values to the program being executed. It is written as below: PARM='value,value,...,value' Of course, you have to know what values the program expects. For systemsupplied programs the order in which you write the values doesn't matter. //FORT EXEC PGM=FORTVS,REGION=128K,PARM='XREF,LIST' or: //FORT EXEC PGM=FORTVS,REGION=128K,PARM='LIST,XREF' For user-written application programs, the order may or may not matter. If there is only one value and it contains only alphabetic or numeric characters, you can omit the single quotation marks. PARM='XREF' or PARM=XREF

Suppose that a cataloged procedure contained the following EXEC statement: and you invoked this procedure to override the PARM as follows: //STEPA EXEC COMP,PARM.STEP1='FOUR' The PARM value for the run would be PARM='FOUR'. doesn't supplement. An override replaces, it

You can retrieve the PARM values when you write your own application programs. Each programming language has a different way of obtaining the PARM values. In COBOL, you retrieve PARM values as shown: //STEP1 EXEC COBUCLG,PARM.GO='string' . . . . . . . LINKAGE SECTION. <== Your COBOL program. 01 PARM 05 PARM-LEN PIC S9(4) COMP. 05 PARM-VAL PIC X(100). PROCEDURE DIVISION USING PARM. PARM-LEN will contain the length of the string and PARM-VAL will contain the string. PL/I: //STEP1 EXEC PLIXCLG,PARM.GO='/string' JCL FOR PROGRAMMERS Page 105 of 169

. . . . . . . procedure: PROC(PARM) OPTIONS(MAIN); <== Your PL/I program. DCL PARM CHAR(100) VAR; PARM will contain the string as a variable-length character string. You can obtain the length by using the LENGTH function. Assembler Language: //STEP1 EXEC ASMFCLG,PARM.GO='string' General register 1 points to a full word containing the address of an area in storage. The first half word of this area contains the number of characters in the string, the remainder of the area contains the string itself. But most often, you supply PARM values for programs that someone else has written, such as the language compilers and the IBM utility programs. For example, a COBOL compile, link edit, go procedure might have parameters for the COB compile step to request a cross reference listing (XREF) and to optimize the code (OPTIMIZE). (These values are specific to a particular COBOL compiler.) //COB EXEC PGM=IKFCBL00,PARM='XREF,OPTIMIZE' TOPIC 7.2: _____ ____ BACKWARD REFERENCES ________ __________

The backward reference or referback permits you to obtain information from a previous JCL statement in the job stream. The simplest form of the referback is: *.ddname Here's an example: +---------------------------------------------------------------------------+ | //A DD DCB=(RECFM=FB,LRECL=120,BLKSIZE=6000),... | | //B DD DCB=*.A | +---------------------------------------------------------------------------+ The DCB=*.A tells the system to copy the DCB sub-parameters written on the previous statement in the same step with a ddname of A. If the DD statement you are referring back to is not in the same job step, you must also give the stepname in the referback: *.stepname.ddname +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=ONE | | //A DD DCB=(RECFM=FB,LRECL=120,BLKSIZE=6000),... | | //STEP2 EXEC PGM=TWO | | //B DD DCB=*.STEP1.A | +---------------------------------------------------------------------------+

JCL FOR PROGRAMMERS

Page 106 of 169

You can also refer back to a ddname contained in a procedure. you write the referback as: *.stepname-executing-proc.stepname-in-proc.ddname For example, if you had this procedure:

To do this,

+---------------------------------------------------------------------------+ | //COMP PROC | | //STEP1 EXEC PGM=COMPUTE | | //OUT DD DCB=(RECFM=VB,LRECL=255,BLKSIZE=6250),... | +---------------------------------------------------------------------------+ you could refer back to the DCB parameters on the OUT DD statement by coding: +---------------------------------------------------------------------------+ | //jobname JOB ... | | //FIRST EXEC COMP | | //SECOND EXEC PGM=REPORT | | //FN DD DCB=*.FIRST.STEP1.OUT,... | +---------------------------------------------------------------------------+ In brief, you can write the referback as: *.ddname (To refer to a previous ddname in the same step.) *.stepname.ddname (To refer to a ddname in a previous step.) *.stepname-executing-proc.stepname-in-proc.ddname (To refer to a ddname in a procedure that a previous step invokes.) Only the last of these is hard to remember. stepname first: To help remember it, think

*.stepname-executing-proc... Then, if the step invokes a procedure, add the stepname within the procedure. Then add the ddname. So far, we've seen these ways of modifying and using statements in a procedure: o Overriding step parameters in a procedure: //stepname EXEC proc,PARM.stepname-in-proc='value' o Overriding DD statements in a procedure: //stepname-in-proc.stepname.ddname DD ... o Referring back to a DD statement in a procedure: DCB=*.stepname-executing-proc.stepname-in-proc.ddname

JCL FOR PROGRAMMERS

Page 107 of 169

Although stepnames are optional as a general rule, they are required in order to refer back to a DD statement within a step. THE DCB REFERBACK When you refer back to a previous DD statement to obtain its DCB parameters, remember this: Only the DCB parameters coded on the DD statement are copied. None of the DCB parameters that might be contained in the label of the data set described by the DD statement is copied. You can also code other DCB parameters, along with the referback. referback must be written first. Here is an example: The

+---------------------------------------------------------------------------+ | //A DD DCB=(RECFM=FB,LRECL=120,BLKSIZE=1200),... | | //B DD DCB=(*.A,BLKSIZE=6000) | +---------------------------------------------------------------------------+ The RECFM and LRECL for DD statement B are copied from A. The DCB parameters written on the DD statement override those from the referback. The BLKSIZE will be 6000. Remember, when you refer back to a previous DD statement, you get the DCB sub-parameters on that DD statement-- not the DCB sub-parameters from the label of the data set described by the DD statement. +---------------------------------------------------------------------------+ | //A DD DCB=(RECFM=FB,LRECL=120,BLKSIZE=1200),... | | //B DD DCB=*.A | +---------------------------------------------------------------------------+ You can copy the DCB parameters from the label of a data set by naming the data set with the DCB parameter. For example: //B DD DCB=Y2222.TEST.DATA The data set must be cataloged. It doesn't have to be referred to by any prior step. The system uses the catalog to locate the data set and copies the DCB sub-parameters from the label. REFERBACK FOR THE DSN As we've seen for the DCB, it's sometimes convenient to refer back to a DD statement that describes a data set instead of referring to the data set by name. You can also refer back to a DD statement with the DSN parameter, rather than naming the data set. +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=ONE | | //A DD DISP=(NEW,PASS),UNIT=DISK, | | // SPACE=(TRK,(2,1)) | | //STEP2 EXEC PGM=TWO | | //B DD DSN=*.STEP1.A,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ Page 108 of 169

JCL FOR PROGRAMMERS

Note that the data set created in STEPA isn't given a name. Temporary data sets don't need names. You can use a referback to refer to them. REFERBACKS ON THE PGM PARAMETER The PGM parameter of the EXEC statement often uses a referback to point to a temporary data set (a library) containing a program to execute. For example: +---------------------------------------------------------------------------+ | //LKED EXEC PGM=IEWL | | //SYSLMOD DD DSN=&&TEMP(G0),DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(1024,(200,20,1)) | | //GO EXEC PGM=*.LKED.SYSLMOD | +---------------------------------------------------------------------------+ Referbacks are often used this way in the language procedures in link edit and go cataloged procedures. REFERBACKS IN THE VOL PARAMETER the Referbacks can also be used to refer to a previous DD statement to obtain volume serial number. You code: VOL=REF=*.referback For The referback copies the VOL=SER from the DD statement being referred to. example:

+---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=ONE | | //A DD VOL=SER=PACK12,... | | //STEP2 EXEC PGM=TWO | | //B DD VOL=REF=*.STEP1.A,... | +---------------------------------------------------------------------------+ Remember, the VOL=REF=*.referback only copies the VOL=SER coded on the DD statement being referred to. If the previous DD statement refers to a cataloged or passed data set, then it probably wouldn't have a VOL=SER parameter. For this, you name the data set with the referback: VOL=REF=*.data-set-name +---------------------------------------------------------------------------+ | //STEPA EXEC PGM=ONE | | //A DD DSN=X.TEST.DATA,DISP=(OLD,PASS) | | //STEPB EXEC PGM=TWO | | //B DD VOL=REF=*.X.TEST.DATA | +---------------------------------------------------------------------------+ The referback can also be coded on two other parameters: o On the OUTPUT parameter to refer to a previous OUTPUT statement. Page 109 of 169

JCL FOR PROGRAMMERS

On the CNTRL parameter to refer to a previous CNTRL statement. The CNTRL statement is used to place subsystem control statements in the job stream. PASSING DATA SETS _______ ____ ____

TOPIC 7.3: _____ ____

A data set read or written in a step can be given a disposition of PASS to pass it on to a following step in the same job. PASS does the following: o It keeps information normally kept in the catalog (DSN, UNIT, VOL, and tape file number for tape data sets) in virtual storage. You get the convenience of CATLG without the overhead of having to write an entry in the catalog. It also keeps information normally kept in the data set label (DCB sub-parameters) in virtual storage. You get the convenience of data set labels without the overhead of having to retrieve the information from disk or tape.

Passing a data set does several things: o o It lets you access a temporary data set in a later step in the same job in which it was created. It means you only have to specify the data set name and give a disposition to access a passed data set. The DCB information, unit, and volume are all supplied automatically when you retrieve a passed dataset.

It is very common to pass cataloged data sets because it saves the system work. When you access a cataloged data set, the system must do the following: o o Look in the system catalog to find the unit and volume where the data set resides. Go to the unit and volume containing the data set to get its volume table of contents (VTOC) where the data set label is stored.

When you pass a data set, all this information is retained by the computer. It doesn't have to do the catalog and VTOC search. Rule of thumb: Pass all data sets used in more than one step. PASS causes data sets to continue to be passed until a step gives them a new disposition, or until the end of the job. +---------------------------------------------------------------------------+ | | | //STEP1 EXEC PGM=CREATE <== Creates and passes data set. | | //OUT DD DSN=&&TEMP,DISP=(NEW,PASS),UNIT=DISK, | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400), | | // SPACE=(TRK,(20,5),RLSE) | | //STEP2 EXEC PGM=STUFF <== Data set not referenced. Continues to be | | //* passed. | | //STEP3 EXEC PGM=READ <== Reads and passes data set. | | //IN DD DSN=&&TEMP,DISP=(OLD,PASS) | JCL FOR PROGRAMMERS Page 110 of 169

| //STEP4 EXEC PGM=SORT <== Reads and deletes data set. | | //IN DD DSN=&&TEMP,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ You can pass a temporary data set--a data set with DSN=&&data-set-name. Besides PASS, DELETE is the only other disposition you can use for a temporary data set. If you don't specify a disposition for a passed data set at the end of the job, the data set reverts to its status at the start of the job: o o KEEP is assumed for pre-existing data sets. DELETE is assumed for data sets created in the job.

You can create a data set in one step, pass it, and catalog it in a later step. +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=Y2222.TEST.DATA,DISP=(NEW,PASS),UNIT=DISK, | | //IN DD DSN=Y2222.TEST.DATA,DISP=(OLD,CATLG) | +---------------------------------------------------------------------------+ Only if you omit the disposition or use PASS does the system have to decide on DELETE or KEEP at the end of the job. As a rule of thumb, you should pass all data sets used in more than one job step. PASS is even more important for tape data sets, because it keeps the tape mounted and rewinds it to the start of the data set. You also need to understand what happens if a step abnormally terminates (ABENDs). First, if the step ABENDs, temporary data sets are always deleted. For non-temporary data sets, the normal disposition is assumed. That is, the second value for the DISP parameter is assumed. If you write DISP=OLD, KEEP is assumed as the second value, and if the step ABENDs, KEEP is also assumed. If STEP2 ABENDs here, KEEP is assumed for the data set. +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=Y2222.TEST.DATA,DISP=(NEW,CATLG), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400), | | // UNIT=DISK,SPACE=(TRK,(20,5),RLSE) | | //STEP2 EXEC PGM=READ | | //IN DD DSN=Y2222.TEST.DATA,DISP=(OLD,KEEP) | +---------------------------------------------------------------------------+ Here is the same JCL with a different disposition in the first step. If STEP2 ABENDs, KEEP is assumed for the data set. DISP=OLD is equivalent to DISP=(OLD,KEEP), and so KEEP is assumed. +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=Y2222.TEST.DATA,DISP=(NEW,KEEP), | | // DCB=(RECFM=FB,LRECL=80,BLKSIZE=6400), | | // UNIT=DISK,SPACE=(TRK,(20,5),RLSE) | | //STEP2 EXEC PGM=READ | JCL FOR PROGRAMMERS Page 111 of 169

| //IN DD DSN=Y2222.TEST.DATA,DISP=OLD | +---------------------------------------------------------------------------+ You can also specify a third disposition sub-parameter to take effect only if the step ABENDs. For example, if you write: DISP=(OLD,DELETE,KEEP) and the step terminates normally, the data set is deleted. But if the step ABENDs, the data set is kept. (You might need this data set for debugging.) Note that the normal disposition is used if you don't specify the abnormal disposition: DISP=(OLD,DELETE) is the same as DISP=(OLD,DELETE,DELETE)

TOPIC 7.4: _____ ____

THE COND PARAMETER ___ ____ _________

The COND parameter lets the execution of one step depend on the outcome of a previous step. For example, take a typical compile, link edit, go procedure. If the compile step discovers compilation errors, there is no need to waste time on the link edit and go steps. The outcome of a step is determined by what is called a condition code or return code. We'll call it a condition code here. Any program can generate a condition code to indicate the status of a job's completion. The condition codes issued by the compilers and linkage editor are: 0 4 8 12 16 No errors or warnings. Warnings, but execution should be successful. Errors; execution likely to fail. Severe error; execution impossible. Most severe error; execution cannot continue.

You can generate condition codes in the various programming languages, too: COBOL FORTRAN PL/I Assembler C TYPICAL CASES You usually use a COND parameter on the EXEC statement to test previous condition codes to see if the step should execute. For example: //STEP6 EXEC PGM=CREATE,COND=(4,LT) The COND=(4,LT) means that if 4 is Less Than the condition code of any previous step, then don't execute this step. This the same as telling the system to execute the step if all previous condition codes were less than or JCL FOR PROGRAMMERS Page 112 of 169 MOVE condition-code TO RETURN-CODE. STOP condition-code CALL PLIRETC(condition-code); Load condition-code in register 15. exit(condition-code);

equal to 4. The (4,LT) causes the step to not be executed for condition codes of 5 or more. The step executes with codes of 0-4. If you coded this: //STEP6 EXEC PGM=CREATE,COND=(8,GE) the step is not executed if 8 is greater than or equal to the condition code from any previous step. That is, the step is not executed for values 0-8. It is executed for values of 9+. This illustrates the major problem with the COND parameter. It is extremely difficult to read and write. The general form of the COND parameter is: COND=(value,comparison) The value is compared with the condition code. the step is not executed. The comparisons are: GT LT GE LE EQ NE Greater than Less than Greater than or equal to Less than or equal to Equal to Not equal to If the comparison is true,

If you are executing a cataloged procedure, you can specify the step within the cataloged procedure to which the test applies: COND.stepname-in-proc=(value,comparison) You can also apply the COND to any of the steps. The CONDs must be listed in the order the steps appear in the cataloged procedure: +---------------------------------------------------------------------------+ | //EXEC FORTCLG,COND.LKED=(4,LT), | | // COND.GO=(0,LT) | +---------------------------------------------------------------------------+ When you write: // EXEC PLICLG,COND.GO=(8,LT) the GO step is not executed if 8 is less than the condition code from the previous compile or link edit step. The COND parameter is extremely difficult to read. It is difficult to visualize "don't execute this step if 8 is less than a previous condition code." It's a lot easier to understand "don't execute this step if a previous step has a condition code greater than 8." But you must write the COND parameter in this awkward manner. The COND parameter is difficult to write and also difficult to read for two reasons. o It expresses a condition for not executing a step. Negatives always make things more complicated. It's easier to express the Page 113 of 169

JCL FOR PROGRAMMERS

condition for doing something than for not doing something. this isn't all that bad. The next item is. o You must write the COND parameter in the form: value comparison code

But

We don't think this way. We would never say "forty thousand is less than or equal to what she makes a year." We think "She makes more than forty thousand a year." Writing the COND parameter correctly is a challenge. about doing it. Here's one way to go For example:

1. Express the comparison for not executing the step. Don't execute if condition code is greater than 4: code > 4 2. Reverse the equation, reversing the comparison too: change code > 4 to 4 < code 3. Now write the COND parameter with its comparisons. code < 4 becomes COND=(4,LT)

As many as eight COND tests can be coded for the COND parameter: COND=((value,comparison),(value,comparison),...) If any expression is true, the step is not executed. COND=((4,GT),(6,LT)) executes the step only for condition codes of 4, 5, 6. executed for condition codes of 0 to 3 or 7 or more. The step isn't This COND parameter:

You can test the condition code in a specific prior step by writing: COND=(value,comparison,stepname) or, for a step in a cataloged procedure: COND=(value,comparison,stepname-executing-proc,stepname-in-proc) For example: COND=(6,LT,STEPA) The program, rather than making the comparison to each of the condition codes for previous steps, compares only the condition code from STEPA.

JCL FOR PROGRAMMERS

Page 114 of 169

Suppose you wanted step execution like this: | \|/ STEP1 (If STEP1 returns > 0) STEPA / \ STEP2 | \|/ \ / STEPB (if STEP1 returns = 0) Note--the condition code cannot be negative.

The following COND parameter would do this. +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=ONE | | //STEPA EXEC PGM=A,COND=(0,EQ,STEP1) | | //STEPB EXEC PGM=B,COND=(0,LT,STEP1) | | //STEP2 EXEC PGM=TWO | +---------------------------------------------------------------------------+ STEPA is not executed if 0 equals the condition code for step 1--that is, it is run if the condition code from STEP1 is not 0. The opposite is true for STEPB. There are two other ways to write the COND parameter. COND=EVEN COND=ONLY Execute this step EVEN if a previous step ABENDs. Execute this step ONLY if a previous step ABENDs.

These can be coded with other COND parameters, but they cannot be coded with each other. EXTREME CASES Occasionally you may want to write a COND parameter that causes the step to never be executed. You might be sorting some data in one step and generating a report in a following step. After running the program once, you might no longer need to execute the sort step. The following does this: COND=(0,LE) (Zero is always less than or equal to the condition code, so the step is never executed.) In the opposite case, when you want to execute a step regardless of the condition code, you can omit the COND parameter or code: COND=(4095,GT) (The maximum value of a condition code is 4095, so 4095 cannot be greater than the condition code.) You might do this in a final step that deletes data sets. a step, even if a previous step ABENDs, you could code: To always execute

JCL FOR PROGRAMMERS

Page 115 of 169

COND=((4095,GT),EVEN) Although the COND parameter can be made very complicated, the following form usually suffices: COND=(value,LT) For example: COND=(4,LT) <== Don't execute this step if any previous step had a condition code greater than 4. <== Don't execute this step if any previous step had a condition code greater than the value.

The COND parameter can also be coded on the JOB statement, although it rarely is. You code: COND=(number,comparison) COND=((number,comparison),...,(number,comparison)) As many as eight comparisons can be listed. (You cannot code an EVEN or ONLY.) The comparisons are made for each job step within the job, and if any comparison is true for a step, that step and all following ones are bypassed. If you code COND on the JOB statement, any COND parameters on the EXEC statements are ignored.

JCL FOR PROGRAMMERS

Page 116 of 169

SESSION 8: _______ __

PARTITIONED DATA SETS ___________ ____ ____

TOPIC _____ 8.1 8.2

TITLE _____ Creating Partitioned Data Sets Compressing Partitioned Data Sets NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 117 of 169

TOPIC 8.1: _____ ____

CREATING PARTITIONED DATA SETS ________ ___________ ____ ____

PARTITIONED DATA SETS A partitioned data set consists of several sequential data sets) stored in the same data set. Sequential data set: A3426.TENSLIST.DATA +----------------------+ | Lines or records | | in the data set. | | | | | | | | | | | +----------------------+ members (actually, several

Partitioned data set: A3426.STUDENTS.DATA +----------------------+ | FRESHMEN member | +----------------------+ | SOPHS member | +----------------------+ | JUNIORS member | +----------------------+ | SENIORS member | +----------------------+

DIRECTORY OF A PARTITIONED DATA SET Each partitioned data set has a directory--an area where the member names and pointers are kept: A3246.MEMOS.TEXT +------------------------------------+ | Directory area. Contains list of | | member names and pointers to where | | members are stored in the data set.| |------------------------------------+ | Member 1 | |------------------------------------+ | Member 2 | |------------------------------------+ | . | | . | | . | |------------------------------------+ | Member n | +------------------------------------+ Rule of thumb:

<== The number of directory blocks sub-parameter tells how much space to allocate for this area.

Number of directory blocks = number of estimated members/5

Then round up to the nearest integer. When you allocate space for a partitioned data set, you must tell the system the number of directory blocks to set aside within the primary area. Each directory block contains approximately enough space for 5 member names. A directory block is actually 256 bytes of storage, which, on the average, can contain 5 member name entries. Suppose you had this DD statement: Page 118 of 169

JCL FOR PROGRAMMERS

+---------------------------------------------------------------------------+ | //OUTPUT DD SPACE=(TRK,(10,2,1)), | | // UNIT=3350,DCB=BLKSIZE=19069 | +---------------------------------------------------------------------------+ One track is actually reserved for the directory. (A 3350 track is 19,069 bytes.) The system uses 1 track for the directory. It starts with 256 bytes and then tries to fit a data set block on the rest of the track. A block won't fit here, so the directory takes up the entire track. If you attempt to store more information in a partitioned data set than the directory can hold, the system ABENDs your job with a B14 system completion code. When this occurs, you must usually allocate space for a new partitioned data set with more directory blocks, and copy the old partitioned data set into it. Two other ABENDs you might get with partitioned data sets are: D37 - Out of space and no secondary specified. E37 - Out of space and all 16 extents are used up. If you request 3 directory blocks, the partitioned data set can contain roughly 15 members. (Always allow some safety margin.) The system then |---------3 directory blocks--------| +-----------+-----------+-----------+--------------------+ | 256 bytes | 256 bytes | 256 bytes | blocks of data ... | +-----------+-----------+-----------+--------------------+ Note that a directory block is 256 bytes and has no relationship to the blocksize of the members specified on the DCB=BLKSIZE sub-parameter. One other note. An entire partitioned data set must fit on a single volume. It cannot be expanded onto multiple volumes. NAMING MEMBERS OF A PARTITIONED DATA SET You name a member of a partitioned data set by writing: DSN=data-set-name(member-name) The member name you select must conform to the usual naming rules--1 to 8 characters long, etc. One of the most useful applications for a partitioned data set is a program library. We'll show how to create and use a partitioned data set by creating a program library. Let's assume we have a FORTRAN program that we are executing with this JCL. Here's what the JCL looks like when VOL is coded to write the data set on a volume with a serial number of PACK12, and SPACE is coded to allocate space to the data set.

JCL FOR PROGRAMMERS

Page 119 of 169

+---------------------------------------------------------------------------+ | // EXEC FORTCLG | | //FORT.SYSIN DD * | | Your FORTRAN program. | | //LKED.SYSLMOD DD DSN=Y2222.LIB.LOAD(CALC),DISP=(NEW,CATLG), | | // VOL=SER=PACK12,SPACE=(TRK,(15,5,20)) | +---------------------------------------------------------------------------+ Notice that the new JCL overrides the SYSLMOD SPACE parameter. Otherwise, the right amount of space might not be allocated. For a non-temporary library, you will probably want different primary and secondary amounts of space and a different directory size. The program library is created and the member is written into it. EXECUTING A PROGRAM IN A PARTITIONED DATA SET The JCL needed to execute our CALC program is stored as a load module in the Y2222.LIB.LOAD partitioned data set. You begin with this JCL to execute the CALC program: //FORT#1 JOB (2215,15),'EXECUTE',CLASS=A //FIRST EXEC PGM=CALC The EXEC statement names the member of the partitioned data set. But the system needs to know which data set (library) to search. You add this DD statement after the EXEC statement to name the library. //STEPLIB DD DSN=data-set-name,DISP=SHR We stored the CALC program in a data set named Y2222.LIB.LOAD. We would need to add a STEPLIB DD statement and whatever other DD statements were needed. +---------------------------------------------------------------------------+ | //FORT#1 JOB (2215,15),'EXECUTE',CLASS=A | | //FIRST EXEC PGM=CALC | | //STEPLIB DD DSN=Y2222.LIB.LOAD,DISP=SHR | | //FT06F001 DD SYSOUT=A | | //FT05F001 DD * | | Place data here. | +---------------------------------------------------------------------------+ THE JOBLIB DD STATEMENT If several steps execute programs from the same library, you might want to use the JOBLIB DD statement instead of the STEPLIB DD statement. The JOBLIB DD statement serves the same purpose as the STEPLIB DD statement, naming a program library, but it differs as follows: o statement. //jobname JCL FOR PROGRAMMERS JOB ... Page 120 of 169 JOBLIB is placed between the JOB statement and first EXEC

//JOBLIB DD DSN=data-set-name,DISP=SHR //stepname EXEC ... o JOBLIB is effective for all the steps in that job (although if a step has a STEPLIB DD statement, JOBLIB is ignored for that step).

OVERRIDING DD STATEMENTS IN A CATALOGED PROCEDURE If you need to recompile the FORTRAN program to change and replace the CALC member, you override the previous SYSLMOD DD statement by writing this: +---------------------------------------------------------------------------+ | // EXEC FORTCLG | | //FORT.SYSIN DD * | | Place data here. | | //LKED.SYSLMOD DD DSN=Y2222.LIB.LOAD(CALC),DISP=OLD, | | // UNIT=,SPACE= | | (The UNIT= and SPACE= remove these parameters from the statement | | we are overriding.) | +---------------------------------------------------------------------------+ The LKED step of the FORTCLG procedure contains: +---------------------------------------------------------------------------+ | //LKED EXEC PGM=IEWL | | //SYSLMOD DD DSN=&&GOSET(MAIN),DISP=(NEW,PASS), | | // UNIT=SYSDA,SPACE=(1024,(20,10,1),RLSE), | | // DCB=BLKSIZE=1024 | +---------------------------------------------------------------------------+ The overridden SYSLMOD DD statement will act as if it were written: //SYS MOD DD DSN=Y2222.LIB.LOAD(CALC),DISP=OLD,DCB=BLKSIZE=1024 When you write a member of a partitioned data set, as with this statement: //SYSLMOD DD DSN=Y2222.LIB.LOAD(CALC),DISP=OLD The member (CALC here) is added to the data set, replacing any existing member with the same name. When you replace members of a partitioned data set, the space occupied by the old member is not reused. Eventually, partitioned data sets become "full" because of this wasted space. When this occurs, you must "compress" the data set to reclaim the wasted space for active use. We'll describe this later. You can delete a cataloged data set by using the IEFBR14 null program: +---------------------------------------------------------------------------+ | //jobname JOB ... | | // EXEC PGM=IEFBR14 | | //DD1 DD DSN=Y2222.LIB.LOAD,DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+

JCL FOR PROGRAMMERS

Page 121 of 169

This can be used to delete either a sequential or partitioned data set. Now here's something to watch out for. Suppose you wrote this DD statement to try to delete a particular member. +---------------------------------------------------------------------------+ | // EXEC PGM=IEFBR14 | | //DD1 DD DSN=Y2222.LIB.LOAD(ONE),DISP=(OLD,DELETE) | +---------------------------------------------------------------------------+ The entire data set will be deleted. This is a "gotcha." Never try to delete a member of a partitioned data set this way. You can't delete a member of a partitioned data set with just JCL. You must use a utility program. USING PARTITIONED DATA SETS You can reference a partitioned data set with a DD statement in two ways: o As a library. You write a DD statement such as the following:

//ddname DD DSN=data-set-name,DISP=... The system then searches the partitioned data set for a particular member. For example: +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CALC | | //STEPLIB DD DSN=Y2222.LIB.LOAD,DISP=SHR | +---------------------------------------------------------------------------+ The system automatically looks for the member CALC in the Y2222.LIB.LOAD library. //ddname DD DSN=data-set-name(member),DISP=... If you were reading, the member would be read as if it were a sequential data set. If you were writing, just that member would be added or replaced. Partitioned data sets are often used this way to store several individual data sets. Of course, all the members of the same partitioned data set must have the same DCB attributes, including RECFM, LRECL, and BLKSIZE. The DCB attributes are for the entire partitioned data set, and apply to each member too. Partitioned data sets are often used to store several small data sets together to save disk space. For example, suppose you had 10 small data sets with 80-byte records. Each data set might contain 20 records. These could all easily fit on one track of a 3350 or 3380 disk if stored in a partitioned data set. As sequential data sets, 10 tracks minimum, regardless of the disk drive, would be required to store the data set. The minimum space that can be allocated to a disk data set is one track. Storing the data sets as members of a partitioned data set saves 9 tracks. TOPIC 8.2: _____ ____ COMPRESSING PARTITIONED DATA SETS ___________ ___________ ____ ____ Page 122 of 169

JCL FOR PROGRAMMERS

When members are replaced in a partitioned data set, the old members are not overwritten. Instead, the new member is added at the end of the partitioned data set, where the system needn't worry about overlapping into another member as it would if it attempted to overwrite the old member. But the consequence of this is that partitioned data sets often become full of unavailable space occupied by replaced members. Compressing the data set lets you reclaim this space. Members are stored end to end inside a partitioned data set. has two members, A and B: +-------------------------------------------------------+ | A | B | Available space | +-------------------------------------------------------+ When you replace a member, the replacement is placed after the last member in the data set. The space the member originally occupied becomes unavailable. If we replace member A, we get: +-------------------------------------------------------+ |///| B | A | Available space | +-------------------------------------------------------+ If we replace member A again, we get: +---+---+---+---+---------------------------------------+ |///| B |///| A | Available space | +---+---+---+---+---------------------------------------+ Before long, the entire data set is full of wasted space: +-------------------------------------------------------+ |///| B |///////////////////////////////////////////| A | +-------------------------------------------------------+ When you try to replace or add another member, you get the following message: SYSTEM ABEND 'D37' or SYSTEM ABEND 'E37' This data set

This message means: "The partitioned data set is so full that the member can't be saved." You get a D37 if you didn't specify a secondary allocation. You get an E37 if you've used all 16 extents and still need more space. We need to compress the data set. Compressing a data set moves everything back to retrieve the wasted space. If you have this to begin with: +-------------------------------------------------------+ |///| B |///////////////////////////////////////////| A | +-------------------------------------------------------+ and you compress the data set, you get this: +-------------------------------------------------------+ | B | A | Available space | JCL FOR PROGRAMMERS Page 123 of 169

+-------------------------------------------------------+ If your installation charges for the total amount of disk space used by a data set, for cost effectiveness you would want to allocate a large primary amount of space and little secondary space for a partitioned data set. That way the data set will not expand to fill a large portion of the disk before it becomes full. You normally don't request a large secondary for partitioned data set. Instead, you request a reasonable amount and compress it when it becomes full. Here's why: When you replace members, all your secondary space will eventually be allocated and used up. +-------------------------------------------------------+ |/primary|//secondary///////////////////////////////| A | +-------------------------------------------------------+ +-------------------------------------------------------+ | A | | +-------------------------------------------------------+ It's better to just allocate a reasonable amount and compress as needed. With a partitioned data set in which you are updating members, you should assume all your secondary space will be allocated right away. +------------------------+ | A | | +------------------------+ The easiest way to compress a data set is to use the utility feature of the ISPF/PDF system editor. If you don't have ISPF at your installation, you can compress data sets using JCL. To compress a data set, you execute an IBM utility program named IEBCOPY. IEBCOPY uses a DD statement with a ddname of SYSUT2 to point to the partitioned data set. IEBCOPY also needs two temporary work data sets and a DD statement with a ddname of SYSIN to read a control statement from the input stream. +---------------------------------------------------------------------------+ | //COMPRESS JOB (2215,15),'COMPRESS PDS',CLASS=A | | // EXEC PGM=IEBCOPY | | //SYSPRINT DD SYSOUT=A | | //SYSUT2 DD DSN=Y2222.LIB.LOAD,DISP=OLD | | //SYSUT3 DD DSN=&&TEMP1,DISP=(NEW,DELETE),UNIT=SYSDA, | | // SPACE=(TRK,(3,2)) | | //SYSUT4 DD DSN=&&TEMP2,DISP=(NEW,DELETE),UNIT=SYSDA, | | // SPACE=(TRK,(1,1)) | | //SYSIN DD * | | COPY INDD=SYSUT2,OUTDD=SYSUT2 | | /* | +---------------------------------------------------------------------------+ Page 124 of 169

JCL FOR PROGRAMMERS

Your installation probably has a cataloged procedure to compress data sets to save you writing all this each time. Check with your installation to see if you need to worry about compressing your data sets. Some installations automatically compress your partitioned data sets for you and release some percentage of the space. If your installation does this regularly, it means two things: o o You usually don't have to worry about compressing your partitioned data sets. You should have a secondary allocation. If a portion of your excess space is released when the data set is compressed, you need a secondary amount so that your data set can grow again after being compressed.

The challenge in compressing a partitioned data set lies in knowing when to do programs available at your installation that show how much available space you have in your partitioned data sets. The ISPF/PDF utility option also provides this information.

JCL FOR PROGRAMMERS

Page 125 of 169

SESSION 9: _______ __

WRITING CATALOGED PROCEDURES _______ _________ __________

TOPIC _____ 9.1 9.2 9.3

TITLE _____ Instream and Cataloged Procedures Writing Procedures--Jobstream Input Writing Procedures--Symbolic Parameters NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 126 of 169

TOPIC 9.1: _____ ____

INSTREAM AND CATALOGED PROCEDURES ________ ___ _________ __________

Most of the JCL you use will be in cataloged procedures that were written by someone else. But you may need to write cataloged procedures yourself. First, hough, you need to understand what cataloged and instream procedures are and what each is used for. Cataloged and instream procedures are written identically. The only difference is that a PEND statement is needed to conclude an instream procedure. And the procedures are stored in different places. o Cataloged procedures are placed in a system library, usually SYS1.PROCLIB. (Your installation may also have a test library for cataloged procedures.) Instream procedures are placed in the job stream after the JOB statement but before the first EXEC statement.

Cataloged procedures are difficult to change because you must modify a system library. The changes are usually made at night, when the system is idle. Cataloged procedures are provided so that people don't have to keep rewriting the same JCL. Cataloged procedures aren't just nice to have. Without them, using JCL probably wouldn't be practical. Instream procedures let you test and modify cataloged procedures before the procedures are placed in a system library. They can also be used to "parameterize" JCL, and they may provide a useful means of keeping several related JCL steps together as a functional unit. Before we go into how cataloged and instream procedures are used, let's see +---------------------------------------------------------------------------+ | //procedure-name PROC | | JCL statements | | // PEND | +---------------------------------------------------------------------------+ The procedure-name can be 1 to 8 characters long. Here's an example showing the placement of an instream procedure: +---------------------------------------------------------------------------+ | //TEST10 JOB ... | | //RUNIT PROC | | lots of JCL statements | | // PEND | | //STEP1 EXEC PGM=ONE | | ... | | //STEP6 EXEC RUNIT | +---------------------------------------------------------------------------+ To make this instream procedure into a cataloged procedure, you would just take the RUNIT statements, remove the PEND, and store them as a member of the SYS1.PROCLIB partitioned data set. (Your installation may concatenate several other partitioned data sets to SYS1.PROCLIB.) JCL FOR PROGRAMMERS Page 127 of 169

The single most important item in deciding whether to create a cataloged procedure is the number of potential users. You wouldn't place a procedure in a system library unless there were several potential users. We mentioned that there were three main uses for instream procedures: o To test new procedures. No procedure should ever be placed in a system library as a cataloged procedure without being tested first as an instream procedure. To collect and organize JCL into functional procedures that you can reuse from time to time. To "parameterize" JCL that you don't want to bother putting in the cataloged procedure library. Here's an example of this ...

o o

As we'll describe in a following topic, you can create "symbolic" parameters within the JCL statements in a procedure. You can then supply values for these symbolic parameters on the EXEC statement. Here's an example: +---------------------------------------------------------------------------+ | //RUNIT PROC | | ... | | //OUTPUT DD VOL=SER=&DISK, ... | | ... | | // PEND | +---------------------------------------------------------------------------+ The &DISK is a symbolic parameter. invoke the procedure with an EXEC: // EXEC RUNIT,DISK=PACK10 The OUTPUT statement then acts as if it had been written as: //OUTPUT DD VOL=SER=PACK10, ... This way, you can specify a different volume each time you execute the procedure. You've effectively "parameterized" the volume. // EXEC RUNIT,DISK=PACK12 Of course, there are other ways to modify JCL for a particular execution. You could also have coded the volume serial number as some unique combination of characters: //OUTPUT DD VOL=SER=XXXX, ... Then you could have changed the XXXX to a volume serial number by using a text editor to make a global change. ===> C XXXX PACK12 ALL This achieves roughly the same results as parameterizing. You supply a value for it when you

JCL FOR PROGRAMMERS

Page 128 of 169

TOPIC 9.2: _____ ____

WRITING PROCEDURES--JOBSTREAM INPUT _______ _____________________ _____

STATEMENTS NOT ALLOWED IN A PROCEDURE You can place most statements in a exceptions. Some of these exceptions are: o o o o The JOB statement. The JOBCAT statement. The JOBLIB statement. An instream procedure (an internal PROC/PEND pair). procedure, but there are a few

Since a procedure is invoked by an EXEC statement, it can't contain statements that you would normally place in front of the first EXEC. Comment statements can, of course, be placed in a procedure. You cannot include in one procedure an EXEC statement that invokes another. You also can't code the null statement (// on a line by itself) within a procedure. Nor can you place a DD * in a procedure. JOBSTREAM INPUT FOR A CATALOGED PROCEDURE You can't code a DD * or DD DATA statement in a procedure. are several ways around this problem: o However, there

You can use a new DD parameter, the DDNAME parameter, to include the data in the input jobstream rather than inside the procedure.

You can store the data in a data set and use a DD statement to point to the data set. You want to achieve this effect in a procedure: +---------------------------------------------------------------------------+ | //procedure-name PROC | | ... | | //ddname DD * <=== Not allowed. | | lines of data | +---------------------------------------------------------------------------+ One way to get there is to store the lines of data in a data set or as a member of a partitioned data set. The data set should be RECFM=FB, LRECL=80. (All instream data sets have an LRECL of 80.) Then point to the data set. //ddname DD DSN=data-set-name,DISP=SHR This works very well if the lines of data don't change very often. If the lines of data change often, it's better to include them in the input stream. To Page 129 of 169

JCL FOR PROGRAMMERS

include input stream data when a procedure is invoked, you can override a DD statement for the step in the procedure: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=ONE | | ... | | // PEND | +---------------------------------------------------------------------------+ You could then write: +---------------------------------------------------------------------------+ | //STEP1 EXEC TEST | | //STEP1.ddname DD * | | lines of data <== This instream data is legal because it | | /* is outside the procedure. | +---------------------------------------------------------------------------+ THE DDNAME PARAMETER All of the IBM-supplied cataloged procedures and many user-written procedures do this a different way--by using the DDNAME parameter. Here's an example: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=ONE | | //INPUT DD DDNAME=SYSIN <== When the program reads the INPUT file, | | ... the system uses the DDNAME referral to | | locate the data. | +---------------------------------------------------------------------------+ Then the ddname specified by the DDNAME parameter is coded as shown here: +---------------------------------------------------------------------------+ | // EXEC TEST | | //STEP1.SYSIN DD * | | lines of data <== The DDNAME referral is to this data in | | /* the input stream. | +---------------------------------------------------------------------------+ Here's that again: +---------------------------------------------------------------------------+ | //procedure-name PROC | | ... | | //ddname DD DDNAME=any-ddname | | ... | +---------------------------------------------------------------------------+ The DD * input is then supplied as: +---------------------------------------------------------------------------+ | // EXEC procedure-name | | //stepname-in-proc.any-ddname DD * | JCL FOR PROGRAMMERS Page 130 of 169

+---------------------------------------------------------------------------+ The any-ddname is by convention usually SYSIN, but it can be any valid name. Here is an example: +---------------------------------------------------------------------------+ | //RUNIT PROC | | //STEP1 EXEC PGM=ONE | | //INPUT DD DDNAME=SYSIN | | ... | | //STEP3 EXEC PGM=THREE | | //MOREIN DD DDNAME=SYSIN | | ... | +---------------------------------------------------------------------------+ The procedure is invoked with: +---------------------------------------------------------------------------+ | // EXEC RUNIT | | //STEP1.SYSIN DD * | | lines of data | | //STEP3.SYSIN DD * | | lines of data | | /* | +---------------------------------------------------------------------------+ Coding the DDNAME parameter on a DD statement postpones the data set definition until a subsequent DD statement is encountered in the job stream with a matching ddname. DDNAME doesn't have to be used just for procedures, and it doesn't have to be used just for jobstream input. It can point to any data set. But mainly it is used for input stream data. Rather statement, First, the this helps o o than just having the user override a procedure step to add a DD the DDNAME parameter is often used for procedures for two reasons. DDNAME statements let you write a DD statement in the procedure, and document it. When you list the procedure, you can tell: That a DD statement is needed. What its ddname is.

+---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=ONE | | //IN DD DDNAME=JUNK | +---------------------------------------------------------------------------+ The second reason for using the DDNAME parameter is that you can code DCB parameters on the original statement instead of having to write them on the DD statement in the job stream. Here's an example: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=ONE | | //INPUT DD DDNAME=SYSIN,DCB=(BUFNO=1,BLKSIZE=80) | JCL FOR PROGRAMMERS Page 131 of 169

| ... | +---------------------------------------------------------------------------+ You wouldn't have to write the DCB parameter when you used the procedure: +---------------------------------------------------------------------------+ | //STEP1 EXEC TEST | | //SYSIN DD * | +---------------------------------------------------------------------------+ TOPIC 9.3: _____ ____ WRITING PROCEDURES--SYMBOLIC PARAMETERS _______ ____________________ __________

SYMBOLIC PARAMETERS The only other thing you need to know in order to write procedures is how to write symbolic parameters. You write a symbolic parameter on a statement within a procedure as follows: &name The normal rules for names apply: the first character must be A-Z, @, #, $; the remaining characters can be A-Z, @, #, $, 0-9. The symbolic parameter, with its leading ampersand, can be a maximum of 8 characters long. That is, the name itself can be a maximum of only 7 characters long. You then supply a value for the parameter when you execute the procedure. Here's an example: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEP1 EXEC PGM=&WHAT | +---------------------------------------------------------------------------+ You could execute this procedure and supply the program name by coding: // EXEC TEST,WHAT=IEFBR14 The system would interpret this as: //STEP1 EXEC PGM=IEFBR14 A symbolic parameter can be coded on the parameter field of any statement within a procedure. (It can't be coded as part of the name or operand field.) Since a comment statement doesn't have a parameter field, a symbolic parameter coded on it is treated as just part of the comment. //* THE UNIT FIELD IS &UNIT. The system treats this entire line as a comment. tute a value for the &UNIT. It doesn't try to substi-

You can't use a stepname or ddname as a symbolic parameter. Nor can the operation statements (DD, EXEC, etc.) be used as symbolic parameters. You supply values to symbolic parameters by coding the symbolic parameter name (without the ampersand) on the EXEC statement in the form: JCL FOR PROGRAMMERS Page 132 of 169

// EXEC procedure,name=value,name=value,... The order in which you write the symbolic parameter names doesn't matter. If the value contains one of the special characters * . & + - or =, you must enclose the value in single quotation marks. // EXEC SORT,NAME='&&TEMP' If you enclose the value in single quotation marks and the value itself contains a single quotation mark, code two single quotation marks where you want the single quotation mark in the value. For example, if you wanted a value of 0 you would code '0 The same symbolic parameter can be used in several places in a procedure. +---------------------------------------------------------------------------+ | //REPORT PROC | | //STEPA EXEC PGM=ONE | | //OUT DD DSN=&NAME,... | | //STEPB EXEC PGM=TWO | | //IN DD DSN=&NAME,... | | ... | +---------------------------------------------------------------------------+ This is a real advantage of using symbolic parameters. If you supplied the DSN by overriding the DD statements, you would have to override several statements. With symbolic parameters, you only need to supply a value once, and the system will substitute the value each time the symbolic parameter appears in the procedure. One of the parameters in the previous procedure was followed by a period: //STEPA EXEC PGM=ONE,REGION=&REG.K Without the period (REGION=&REGK), the system would think the symbolic parameter was named &REGK. You would need to code the K needed for the REGION parameter as part of the symbolic parameter's value: // EXEC JOBAID,REGK=104K With the period, the system knows that the symbolic parameter is named &REG and that the K is part of the statement. You would code the symbolic parameter without the K: // EXEC JOBAID,REG=104 Actually, a period is only one of several ways the system tells where symbolic parameter names end. Usually, of course, a space serves the purpose. But if the names are buried in the middle of the JCL, the system recognizes other characters as delimiters. SPACE=(1024,(&PRIMARY,2)) The second comma delimits the symbolic parameter name. COND=(NEW,&AFTER) The right parenthesis delimits the symbolic parameter name. JCL FOR PROGRAMMERS Page 133 of 169

DSN=&PFX&SFX The ampersand of the second symbolic parameter delimits the name of the first. If, however, no special character delimits the name, you must code a period to delimit it. REGION=&REG.K Note that this period vanishes when the value is substituted for the symbolic parameter, however, and that a problem arises if you need a period to follow the symbolic parameter--as could occur in a data set name: DSN=&PFX.TEST.DATA If you want to preserve the period in front of TEST, you must code a second period. DSN=&PFX..TEST.DATA The first period delimits &PFX. ment. Suppose you had this procedure: +---------------------------------------------------------------------------+ | //TEST PROC | | //STEPA EXEC PGM=ONE | | //IN DD DSN=&NAME.XT,DISP=OLD | +---------------------------------------------------------------------------+ The IN DD statement would have a DSN of XXT. The system sees the period as delimiting the &NAME symbolic parameter, not as a period separating different qualifiers of the data set name. Suppose you wanted to be able to write: // EXEC TEST,NAME=X And you wanted the resulting data set name to be X.XT. You need to code: The second stays as part of the DD state-

+---------------------------------------------------------------------------+ | //TEST PROC | | //STEPA EXEC PGM=ONE | | //IN DD DISP=OLD,DSN=&NAME..XT | +---------------------------------------------------------------------------+ The first period delimits the symbolic parameter and the second remains on the statement. Of course, you could also supply the period as part of the symbolic parameter value: DSN=&NAME.XT and NAME='X.'

The results are the same. The single quotation marks are needed because the period is a special character. Page 134 of 169

JCL FOR PROGRAMMERS

Now suppose you wrote this in a procedure: +---------------------------------------------------------------------------+ | //TEST PROC | | ... | | //IN DD VOL=SER=(SYSCAT,&PACK),... | +---------------------------------------------------------------------------+ Then you invoked the procedure and supplied a null value to the &PACK symbolic parameter: // EXEC TEST,PACK= This is a gotcha. VOL=SER=(SYSCAT,) is the result, and JCL considers this to be a syntax error and your job won't run. To correct the previous problem, you can code &PACK as: //IN DD VOL=SER=(SYSCAT&PACK),... Then to supply a volume, you would need to code a leading comma as part of the value: // EXEC TEST,PACK=',PACK10' But you could also assign a null value to PACK and not get a syntax error: // EXEC TEST,PACK= // EXEC procedure,name=value,name=value,... You can also assign values on the PROC statement: //procedure-name PROC name=value,name=value,... Values assigned here become the default values for the procedure. o o If a value isn't assigned on the EXEC, the value assigned on the PROC is used. If a value is assigned on the EXEC, the value on the PROC is ignored. Here's an

Most procedures assign default values to the symbolic parameters. example:

+---------------------------------------------------------------------------+ | //TEST PROC CODE=4 | | //STEP1 EXEC PGM=ONE,COND=(&CODE,LE) | | ... | | //STEP2 EXEC PGM=TWO,COND=(&CODE,LE) | | ... | | //STEP3 EXEC PGM=THREE,COND=(&CODE,LE) | +---------------------------------------------------------------------------+ If you invoke the procedure as: JCL FOR PROGRAMMERS Page 135 of 169

// EXEC TEST the COND parameters become COND=(4,LE). can code: // EXEC TEST,CODE=8 Now the COND parameters become COND=(8,LE). Because of the inherent confusion, you can't give a symbolic parameter the same name as a parameter you can code on the EXEC, such as REGION, TIME, COND, or PARM. If you fail to assign a value to a symbolic parameter on either the PROC or the EXEC, you get a JCL error with one exception. If you code DSN=&name, JCL treats the &name as the name of a temporary data set, and you don't get a JCL error. With that exception, however, you must always assign a value to a symbolic parameter, even if it is only a null value. Both instream and cataloged procedures can contain symbolic parameters and can have default values assigned to them. You normally start out with an instream procedure, and then after you've tested it, you make it a cataloged procedure by doing the following: o o Discard the // PEND statement Store the procedure as a member of the system procedure library. If you want a different value, you

OVERRIDING WITH SYMBOLIC PARAMETERS Next, we need to cover what happens when you override statements with symbolic parameters. Actually, it's very straightforward. You can override an existing symbolic parameter on a DD statement by supplying a value. You can also override an existing value on a DD statement by supplying a symbolic parameter. For example, if you have the values coded below: +---------------------------------------------------------------------------+ | //TEST PROC SIZE=104K,DISK=SYSDA | | //STEP1 EXEC PGM=ONE | | //INPUT DD DSN=&&TEMP,DISP=(NEW,DELETE) | | // PEND | +---------------------------------------------------------------------------+ You can override SIZE=104K and DISK=SYSDA by supplying &SIZE and &DISK parameters when you invoke the procedure. +---------------------------------------------------------------------------+ | // EXEC TEST,REGION.STEP1=&SIZE | | //STEP1.INPUT DD UNIT=&DISK | +---------------------------------------------------------------------------+

JCL FOR PROGRAMMERS

Page 136 of 169

If you had this procedure: +---------------------------------------------------------------------------+ | //TEST PROC AFTER=',DELETE' | | //STEP1 EXEC PGM=ONE | | //INPUT DD DSN=&&TEMP,DISP=(NEW&AFTER) | | // PEND | +---------------------------------------------------------------------------+ And you invoked it with this, to override the symbolic parameter: +---------------------------------------------------------------------------+ | // EXEC TEST | | //STEP1.INPUT DD DISP=(NEW,PASS) | +---------------------------------------------------------------------------+ You would get a JCL syntax error. The &AFTER on the DISP parameter is completely overridden in the procedure. The PROC statement still assigns &AFTER a value, however (AFTER='DELETE'), and when the system fails to find &AFTER in the JCL, it gives an error message. Whenever a symbolic parameter is assigned a value, either on the EXEC statement invoking the procedure or on the PROC statement within the procedure, the parameter must appear somewhere within the procedure. It can appear many times, but it must appear at least once, or you will get a JCL error. It is perhaps even more important to put comments in procedures than it is in other JCL because procedures are usually used more often. Here's how a procedure might be written with comments: +---------------------------------------------------------------------------+ | //INSTALL PROC P1=1,P2=1,P3=1 | | //* * | | //* INSTALL PROCEDURE TO COPY 3 FILES. * | | //* INVOKE THE PROCEDURE WITH: * | | //* // EXEC INSTALL, * | | //* // P1=0, <== ONLY IF FILE 1 NOT WANTED. * | | //* // P2=0, <== ONLY IF FILE 2 NOT WANTED. * | | //* // P3=0 <== ONLY IF FILE 3 NOT WANTED. * | | //* NOTE--COND=(0,LT) CAUSES STEP TO NOT EXECUTE * | | //STEP1 EXEC PGM=COPY,COND=(&P1,LE) | | ... | | //STEP2 EXEC PGM=COPY,COND=(&P2,LE) | | ... | | //STEP3 EXEC PGM=COPY,COND=(&P3,LE) | | ... | | // PEND | | // EXEC INSTALL,P2=0 | +---------------------------------------------------------------------------+

JCL FOR PROGRAMMERS

Page 137 of 169

SESSION 10: _______ ___

JCL PROBLEMS ___ ________

TOPIC _____ 10.1 10.2

TITLE _____ Common JCL Errors How To Read an Output Listing NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 138 of 169

TOPIC 10.1: _____ _____

COMMON JCL ERRORS ______ ___ ______

If this step is executed: +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=&&TEMP,DISP=(,PASS), | | // SPACE=(TRK,(10,5),RLSE),UNIT=SYSDA, VOL=SER=PACK12, | | // DCB=(RECFM=FB,LRECL=100,BLKSIZE=6000) | +---------------------------------------------------------------------------+ The data set may not be written on the volume intended. JCL assumes that anything following a blank in the parameter field is a comment and ignores the item. SPACE=(TRK,(10,5),RLSE),UNIT=SYSDA, VOL=SER=PACK12, /|\ | Blank here tells JCL that what follows on the line is a comment. The system ignores the VOL=SER=PACK12. You wouldn't get a JCLerror, and you might not notice that the data set was not written on the volume you wanted. The system sees the statement as: // If you execute this job step: +---------------------------------------------------------------------------+ | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=&&TEMP,DISP=(,PASS), | | // DCB=(RECFM=FB,LRECL=100,BLKSIZE=6000), | | // SPACE=(TRK,(10,5),RLSE),UNIT=SYSDA, VOL=SER=PACK12 | +---------------------------------------------------------------------------+ You will get a JCL error. The system ignores the VOL=SER=PACK12 because it is preceded by a blank. The system sees the last statement as: // SPACE=(TRK,(10,5),RLSE),UNIT=SYSDA, A comma indicates a continuaSPACE=(TRK,(10,5),RLSE),UNIT=SYSDA, //

You can't end a JCL statement with a comma. tion, and so you get a JCL error.

If a JCL syntax error is encountered anywhere in the JCL, none of the steps in the job is executed. When you have a JCL error, the following message is printed on the first page of your output: JOB FAILED - JCL ERROR Some errors occur during the execution of a job. If you request more disk space than is available, the current step isn't executed and you get the JCL ERROR message, but previous steps could have executed. JCL FOR PROGRAMMERS Page 139 of 169

Here is some JCL: +---------------------------------------------------------------------------+ | //RUN#1 JOB (2215,15),'TEST',CLASS=A,TIME=1 | | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=Y2222.TEST.DATA,DISP=(NEW,CATLG), | | // UNIT=SYSDA,VOL=SER=PACK10,SPACE=(TRK,(10,5)) | | //STEP2 EXEC PGM=COMPUTE | | //OUT DD DSN=Y2222.TEST.DATA,DISP=OLD | +---------------------------------------------------------------------------+ If STEP2 ABENDs because you didn't allow enough TIME on the JOB statement, and you resubmit the job as is, you will get a JCL error. The following occurs: 1. STEP1 creates the data set and catalogs it. 2. STEP2 ABENDs, but the data set is not deleted. If you resubmit the job, STEP1 tries to allocate the data set again, but it already exists. You get this JCL error message: JOB FAILED - JCL ERROR ALLOC - DUPLICATE NAME ON DIRECT ACCESS VOLUME There are, of course, many solutions to the problem: o o o o Change the DISP in STEP1 to DISP=(NEW,PASS). the data set is deleted. Then if STEP2 ABENDs,

Change the DISP in STEP2 to DISP=(OLD,KEEP,DELETE) to delete the data set if the step ABENDs. Change the DISP in STEP1 to DISP=(OLD,PASS) when you rerun. Don't execute STEP1 when you rerun. The fol-

And so on. Duplicate data set names will always be a problem. lowing is typical: 1. You submit a job and a step ABENDs.

2. You correct what was wrong but forget that a data set was created, and the job fails because of duplicate names on the volume. 3. You change your JCL to solve the duplicate name problem but make a mistake in changing the JCL and get a JCL error. This will be a constant frustration and you will just have to be careful. The compilers, linkage editors, utilities, and most programs issue a condition code at the end of each step. You should examine this code in your output listing for each step to determine if errors occurred. A typical message for a step will read: stepname - STEP WAS EXECUTED - COND CODE n JCL FOR PROGRAMMERS Page 140 of 169

By convention, the values for the condition codes (COND CODE n) have the following meanings: 0 4 8 12 16 No errors or warnings. Warnings, but execution should be successful. Errors; execution likely to fail. Severe errors; execution of a compiled or link edited program impossible. Most severe error; execution cannot continue. The compiler or link editor stops processing.

But if a step ABENDs, you get this message at the start of the job: IEF450I jobname stepname - ABEND Snnn U0000 Then you don't get a condition code for the step that ABENDs. message instead: You get this

IEF472I jobname stepname - COMPLETION CODE - SYSTEM=nnn USER=0000 The nnn is a number that identifies the cause of the error. The U0000 is a user ABEND code that appears if the program, rather than the system, issued an ABEND instruction. Programs can be written to do this, but few are. Let's dissect an error message: IEF450I jobname stepname - ABEND Snnn U0000 IEF450I: The error message number. You can look this up in the VS2

System Messages manual to get an explanation of the error message. //stepname EXEC ... Snnn: The system error number. This is what you really want. You can look this number up in yet another manual, VS2 System Codes. The user ABEND code, which is rare.

U0000:

Let's look at the most common system codes, starting with: 222 - Means the computer operator cancelled your job. A reason for this code might be that you asked for a tape volume that can't be found. - Means you needed more CPU time than requested for your job. You must increase the TIME parameter, assuming your job did not go into an endless loop. You

322

804, - Not enough virtual storage was provided for a job step. 80A must increase the REGION parameter. 806

- System couldn't find the program you requested. You probably named a wrong program with the PGM parameter on the EXEC Page 141 of 169

JCL FOR PROGRAMMERS

statement. For each of the codes below, you must allocate more space. B14 B37 D37 E37 - Not enough - More space set. - More space - More space set. directory space in partitioned data set. needed and all 16 extents used for a sequential data needed and no secondary allocation is specified. needed and all 16 extents used for a partitioned data

Other common codes: 013 - Invalid open. Means that the system tried to open a data set, but couldn't because something is wrong. Typical causes are: o You named a partitioned data set member that doesn't exist. o The BLKSIZE is not a multiple of the LRECL (or some other inconsistency in the DCB sub-parameters). o You tried to open the printer as a partitioned data set. o The data set was already open. 0C1 - Invalid instructions. This could be caused by a wild branch into the data area of a program or clobbering the instruction part of your program by overwriting it with data. - Invalid data. Usually caused by using a data area that was not initialized, by invalid alignment of data, or by packed decimal data being clobbered.

0C7

There are two manuals you'll need to use to look up error messages: VS2 System Codes. This manual describes just the completion codes issued by the operating system. (It has only about 150 pages.) VS2 System Messages. This manual describes the error messages, such as IEA153I or IHJ007I. It has close to 1000 pages. The best approach is to learn to recognize a few of the most common and look up the rest. One final item. If you wish a hexadecimal storage dump in the event a job step ABENDs, you include one of the three following DD statements: //SYSUDUMP DD SYSOUT=A (Prints the program area, contents of registers, and gives a traceback of subroutines called.) //SYSABEND DD SYSOUT=A (Same as SYSUDUMP, but also prints the system nucleus. Don't use unless you need the nucleus--and you almost never will. Produces a lot of paper.) Page 142 of 169

JCL FOR PROGRAMMERS

//SYSMDUMP DD DISP=(NEW,CATLG),DSN=... (Same information as SYSABEND, but dump isn't formatted for printing. Used to store dumps in a data set to be processed by an application program.) TOPIC 10.2: _____ _____ HOW TO READ AN OUTPUT LISTING ___ __ ____ __ ______ _______

The output from your job can be divided into two categories: o Job scheduler messages, which include your JCL statements and error messages, device allocations, data set dispositions, and accounting information. The output generated by the programs you execute with your JCL.

The job scheduler message output you receive differs with the version of the You first receive a summary of the job execution, called a job log. It will look about like this: 15.49.39 JOB nnnn jobname STARTED - CLASS A (Tells you the time (hours.minutes.seconds) your job started, the job number assigned to the job internally, your jobname, and the job class.) 15.50.04 15.50.13 (For The K means it JOB nnnn IEF233A M 562,942731,,jobname,stepname JOB nnnn IEF234E K 562,942731,,jobname,stepname tapes: The M above tells you that tape 942731 was mounted. was kept--dismounted--at 15.50.13 on tape drive 562.)

Messages such as: 15.50.04 JOB nnnn IEF233A M 252,942731,,jobname,stepname also tell you the volume serial number used by each step (here, 942731). If your job ABENDs, you get a system code message. 15.49.39 15.50.04 15.50.13 15.50.20 15.50.23 JOB JOB JOB JOB JOB 1724 1724 1724 1724 1724 TEST#1 STARTED - CLASS A IEF233A M 562,942731,,TEST#1,STEP1 IEF234E K 562,942731,,TEST#1,STEP1 IEF450I TEST#1 STEP2 - ABEND 322 U0000 TEST#1 ENDED

You exceeded the CPU time limit and need to increase the TIME parameter on the JOB statement. If you saw this message: 15.50.20 JOB 1724 IEF450I TEST#1 STEP2 - ABEND 322 U0000 You would look up the 322 in VS2 System Codes. IEF450I in VS2 System Messages.) (You could look up the

JCL FOR PROGRAMMERS

Page 143 of 169

Following the job log there will be a listing of your JCL. The JCL statements you actually write--that is, the JCL statements in the input stream--are shown with // in the first two columns. //TEST#1 JOB (2215,15),'TEST',CLASS=A // EXEC FORTCLG If you invoke a cataloged procedure, it is listed after the EXEC invoking it. You can tell cataloged procedure statements because they are shown with XX in the first two columns. When you override a DD statement in a cataloged procedure, both the overriding statement and the original statement are shown. Your override is shown with // in the first two columns and the cataloged procedure statement displays with X/ in the first two columns: //LKED.SYSLMOD DSN=Y0000.PGM.LIB(COMPUTE),DISP=(OLD,PASS) X/SYSLMOD DD DISP=(MOD,PASS),DSN=&&GOSET(MAIN), X/ SPACE=(1024,(200,0,1)),UNIT=SYSDA Notice that you don't get a display of how the overridden step actually appears to the system. The SYSLMOD DD statement will be treated as if it were written as: //SYSLMOD DD DSN=Y0000.PGM.LIB(COMPUTE),DISP=(OLD,PASS), // SPACE=(1024,(200,0,1)),UNIT=SYSDA You must visualize how the statement will appear. display it this way. The system doesn't

The system also lists comment statements differently if they come from the input stream than if they come from a cataloged procedure. A comment statement such as this: //* THIS IS A COMMENT. Appears with asterisks in the first three columns if it comes from the input stream: *** THIS IS A COMMENT. It appears with XX* in the first three columns if it comes from a cataloged procedure: XX* THIS IS A COMMENT. Following the expanded JCL will be a list of all the symbolic parameter substitution done within the step of the cataloged procedure. The output might look like this: STMT NO. 4 5 . . . MESSAGE IEF653I SUBSTITUTION JCL - TIME=3 IEF653I SUBSTITUTION JCL - DISP=SHR . . . Page 144 of 169

JCL FOR PROGRAMMERS

The STMT NO. is the sequential number of the JCL statement to which the message refers. Then you get the allocation messages for each data set in the step: IEF236I IEF237I IEF237I IEF237I . ALLOC. FOR TEST#1 452 ALLOCATED TO STEPLIB 450 ALLOCATED TO SYSLIN JES2 ALLOCATED TO SYSPRINT . .

The 450 and 452 are hardware device addresses. From this, you know that the data set specified with a ddname of SYSLIN was placed on hardware address 450, which is a specific disk pack. The presence of JES2 in place of the hardware address for SYSPRINT means that the printed output was spooled rather than being written to a particular hardware device. (JES2 stands for Job Entry System 2, which is another system.) Then you get a line telling you the condition code for the step, such as this: IEF142I TEST#1 FORT - STEP WAS EXECUTED - COND CODE 0012 Following the COND CODE message, you get a disposition message for each data set used in the step. IEF285I IEF285I IEF285I IEF285I IEF285I . SYS1.PROCLIB VOL SER NOS= SYSPGM. JES2.JOB00258.S00102 SYS85178.T089249.RA000.TEST#1.LOADSET VOL SER NOS= PACK12. . KEPT SYSOUT PASSED .

From this you know that a data set named SYS1.PROCLIB on a volume named SYSPGM was kept. The JES2.JOB00258.S00102 for SYSOUT represents your spooled output. The SYS85178.T089249.RA000.TEST#1.LOADSET is the data set name made up for the temporary data set you named DSN=&&LOADSET. The system makes up names like this, incorporating the date, time, and jobname to ensure that the temporary data set name is unique. The LOADSET data set was stored on PACK12 and was passed. Disposition messages, such as this: IEF285I SYS1.PROCLIB KEPT

identify each data set used by the program, tell where it is stored, and indicate what was done with it at the end of the step. And, finally, you get a message telling you when the step started, when it ended, how much virtual storage you used, and how much storage the system needed to execute the step. IEF373I TEST#1 IEF374I TEST#1 CPU JCL FOR PROGRAMMERS /FORT /FORT / START 89178.1549 / STOP 89178.1553 OMIN 00.13SEC Page 145 of 169

OMIN 01.79SEC SRB

VIRT 256K SYS 240 this number until you execute the job step. for The final item printed for the step is usually the accounting information the job step. This will differ for each installation. All of the information is then repeated for each step. o o o o o o It consists of:

A list of your JCL statements, interspersed with any cataloged procedure statements you invoked. The allocation message for each data set. The condition code for the job step. The disposition messages for the data sets. The elapsed time, CPU time, and region used. And any accounting information.

There is a MSGLEVEL parameter you can add to your JOB statement to shut off a lot of the JCL output. The MSGLEVEL parameter is written in the JOB statement as: MSGLEVEL=(jcl,allocations) jcl = 0 1 2 Print JOB statement only. Print all JCL, including cataloged procedures. This is usually the default, although it may be different at your installation Print only the JCL in the input stream. Don't print allocation messages (unless JOB ABENDs). Print all allocation messages. This is usually the default

allocations = 0 1

MSGLEVEL=(0,0) prints only the JOB statements--not the full JCL and allocation messages. This is fine for saving paper during production, but you need all the information available during debugging. The final parameter relating to the job scheduler messages is the MSGCLASS parameter, which you also write on the JOB statement. MSGCLASS=class This parameter directs all your job scheduler messages to the output class you name. Usually you use this in TSO to hold your output so you can examine it on-line with a system editor. The MSGCLASS parameter applies only to the job scheduler messages. If your program generated output with DD statements such and the special job class to hold your output were class N, not all of your SYSOUT=A output would be held. You can solve this problem by using a SYSOUT class of *: //SYSPRINT DD SYSOUT=* Page 146 of 169

JCL FOR PROGRAMMERS

This sends the output to whatever MSGCLASS you specify on your job statement or, if you omit the MSGCLASS, to the installation default, usually A.

JCL FOR PROGRAMMERS

Page 147 of 169

SESSION 11: _______ ___

GENERATION DATA GROUPS __________ ____ ______

TOPIC _____ 11.1 11.2

TITLE _____ Application of Generation Data Groups Creating and Using Generation Data Groups NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 148 of 169

TOPIC 11.1: _____ _____

APPLICATION OF GENERATION DATA GROUPS ___________ __ __________ ____ ______

A Generation Data Group, often abbreviated GDG, is a facility of the operating system that keeps track of periodic or cyclical data sets. As the name suggests, each new data set that is created forms a new "generation" in a series. Generation data groups typically follow this pattern: 1. A new generation of the data set is added. 2. Some number of the previous generations of the data set are retained. 3. The oldest generation of the data set is deleted. Of course, you don't have to delete the oldest generation of the data set, but there are few data sets for which you need to keep all generations forever. Typical nomenclature for the generations of data sets is: Current version Previous version Next previous version Current generation Parent or minus 1 version Grandparent or minus 2 version

The data set naming convention uses a number to indicate the generation. DSN=data-set-name(0) DSN=data-set-name(-1) DSN=data-set-name(-2) Current generation Previous generation or parent Next previous generation or grandparent

The biggest advantage of using generation data groups is that the system keeps track of the generations for you so you don't have to change your JCL each time you run. Generation data groups consist of data sets that are normal except for their names. The data sets can be sequential, partitioned, or direct. The benefit of using generation data groups is that the system keeps track of the generations for you. You don't have to keep track of many individual data set names. For example: With normal data set names: ACCT.DEC.DATA ACCT.NOV.DATA ACCT.OCT.DATA With generation data group names: ACCT.DATA(0) ACCT.DATA(-1) ACCT.DATA(-2)

To add a new generation to a generation data group, you just create a data set with the same name as before and +1 for the generation: DSN=data-set-name(+1) The system then changes all the previous generation names so that the old (0) becomes (-1), the old (-1) becomes (-2), etc. Here's an example: Page 149 of 169

JCL FOR PROGRAMMERS

Before job completes: ACCT.DATA(+1) ACCT.DATA(0) ACCT.DATA(-1) ACCT.DATA(-2)

After job completes: ACCT.DATA(0) ACCT.DATA(-1) ACCT.DATA(-2) Deleted--if only 3 generations were to be kept

With a generation data group named ACCT.DATA, you could add a new generation by creating a data set named ACCT.DATA(+1): //ddname DD DSN=ACCT.DATA(+1),DISP=(NEW,CATLG),... If you used individual data set names instead, you would need to do the following: 1. Change the JCL to create the new data set name, such as ACCT.DEC.DATA. 2. Delete the previous third generation, such as ACCT.SEPT.DATA (if you wanted to keep only three generations). With generation data groups, there is no need to change the JCL. You just run it each time you want to create a new generation. The system keeps track of generation data groups in the catalog. Of course, this means that when you specify the disposition for a new generation data set, you must specify CATLG. To make things consistent within a given job, generation data group numbers are not updated at the end of the job step in which a new generation is created. Instead, they are updated at the end of the job. This is important to as (+1) throughout the job. +---------------------------------------------------------------------------+ | //UPDATE01 JOB ... | | //STEP1 EXEC PGM=CREATE | | //OUT DD DSN=ACCT.DATA(+1),DISP=(NEW,CATLG),... | | ... | | //STEP2 EXEC PGM=REPORT | | //IN DD DSN=ACCT.DATA(+1),DISP=OLD | +---------------------------------------------------------------------------+ You refer to generation data group generations as: name(+n) or name(0) or name(-n)

The system actually names the data sets as follows: name.GnnnnVvv nnnn vv is the absolute generation number, 0000-9999. is the version number. Usually this is 00. (You can create different versions of the same generation, but not with JCL, and we get into that here.)

For example: Name you use during the job: JCL FOR PROGRAMMERS Name you use after the job: Actual name (used during and after the job): Page 150 of 169

ACCT.DATA(+1) ACCT.DATA(0) ACCT.DATA(-1) ACCT.DATA(-2)

ACCT.DATA(0) ACCT.DATA(-1) ACCT.DATA(-2) Deleted

ACCT.DATA.G0008V00 ACCT.DATA.G0007V00 ACCT.DATA.G0006V00 ACCT.DATA.G0005V00

Since you refer to a generation data group as: name(+n) or name(0) or name(-n)

you don't need to keep track of the real data set name: name.GnnnnV00 The system does that for you. But if you're looking at your data sets with a tool such as ISPF, it's nice to know how your data sets are actually named, because the actual name is what you'll see with ISPF. If the generation data group contains partitioned data sets, you must use the real data set name to refer to a member: name.GnnnnV00(member) Generation data groups are rarely used for partitioned data sets, however. When you create the first generation of a generation data group: name(+1) it is actually named name.G0000V00. The next generation of the data set is named name.G0001V00, the next name.G0002V00, and so on. You must not exceed 10,000 (0000-9999) total generations. Furthermore, you can keep only 256 ((0) to (-255)) generations active at any one time. That is, generation data groups are numbered from 0 to 9999. Only 256 of these can be active at any one time. So generations 6000 to 6255 could be active, and generations 0 to 5999 would all be inactive. The individual generations in a generation data group don't all have to have the same DCB attributes. The RECFM, LRECL, BLKSIZE, and even DSORG can all be different. However, the DCB attributes are usually the same. If they are the same, you can refer to the generation data group without a generation number. DSN=data-set-name The system then concatenates all the generations (current to oldest generation) for the processing. This might be used to produce such things as year-to-date reports. Generation data groups can reside on disk or tape. TOPIC 11.2: _____ _____ CREATING AND USING GENERATION DATA GROUPS ________ ___ _____ __________ ____ ______

To create a generation data group, you must first do these two things: 1. Create a generation data group base entry in a VSAM catalog. entry names the generation data group and specifies how many JCL FOR PROGRAMMERS This

Page 151 of 169

generations to keep. 2. Create a data set label on the same volume as that used for the VSAM catalog entry. The data set label is used as a model for the generation data group. The DCB sub-parameters on the label may or may not be used for the data sets for the generation data group. CREATING A GENERATION DATA GROUP BASE ENTRY o o o o o Sets up the catalog entry used to keep track of the generation data group generations. Names the generation data group. Specifies how many generations are to be kept. Tells what to do with old generations (those that get bumped). As an option, tells how long to keep the entire generation data group.

You create a generation data group base entry by executing a VSAM utility program called IDCAMS. Here is an example: +---------------------------------------------------------------------------+ | //jobname JOB ... | | / EXEC PGM=IDCAMS | | //SYSPRINT DD SYSOUT=* | | //SYSIN DD * | | DEFINE GDG ( | | NAME (X2222.ANNUAL.DATA) | | LIMIT(12) | | NOEMPTY | | SCRATCH ) | | /* | +---------------------------------------------------------------------------+ The NAME parameter names this generation data group as X2222.ANNUAL.DATA. The VSAM utility programs have a different syntax from the regular utility programs, which in turn are different from JCL. The dash at the end of a line continues a statement only for the VSAM utilities. Here's an explanation for the DEFINE statement used to create a generation data group base entry: DEFINE GDG ( (The items following GDG are enclosed in parentheses. cates that the statement is continued.) NAME (generation-data-group-name) LIMIT(generations) (The number of generations to be kept. 255.) The value can be 1 through The - indi-

JCL FOR PROGRAMMERS

Page 152 of 169

NOEMPTY (This tells what to do with the old generations. Coding NOEMPTY requests that the LIMIT number of newest generations be kept and the remainder be deleted. If you code EMPTY instead, all the old generations are deleted, and only the (+1) generation is kept when the LIMIT is reached.) Here's the DEFINE statement with EMPTY coded rather than NOEMPTY: +---------------------------------------------------------------------------+ | DEFINE GDG ( | | NAME (X2222.ANNUAL.DATA) | | LIMIT(12) | | EMPTY SCRATCH ) | +---------------------------------------------------------------------------+ NOEMPTY EMPTY When the LIMIT number is exceeded, NOEMPTY keeps the LIMIT number of newest generations. When the LIMIT number is exceeded, EMPTY keeps only the most recent generation.

EMPTY is mainly used to wipe out all the old data sets for the beginning of new time period. Here's some more of the DEFINE statement: DEFINE GDG ( NAME (generation-data-group-name) LIMIT(generations) NOEMPTY (EMPTY or NOEMPTY) SCRATCH (SCRATCH tells the system to uncatalog and delete the old generations--those not kept. You could code NOSCRATCH instead, and the system would uncatalog the data sets and keep them. Generally you would back up the data set to tape and then just code SCRATCH to keep things simple.) FOR(days) ) (FOR is optional. It specifies the number of days to keep a generation data group. As an alternative, you can specify the retention period as TO(yymmdd).) CREATING A MODEL DATA SET LABEL

The second step in creating a generation data group, after the IDCAMS program is used to create a base entry, is to create a data set to be used as a model for the generation data group. Actually, the system doesn't need an entire data set. It just requires the DCB information contained in the data set label. The following JCL can be used to create a data set label. The IEFBR14 program doesn't do anything--it just allows a step to be executed so that the DD statement is processed.

JCL FOR PROGRAMMERS

Page 153 of 169

+---------------------------------------------------------------------------+ | //jobname JOB ... | | // EXEC PGM=IEFBR14 | | //DD1 DD DSN=data-set-name,DISP=(NEW,KEEP), | | // SPACE=(TRK,0), | | // UNIT=unit,VOL=SER=volume, | | // DCB=(whatever sub-parameters you want) | +---------------------------------------------------------------------------+ data-set-name volume This is usually the generation data group name, but This must be the number of the volume containing the VSAM catalog base entry for the generation data group. The system will only look in this volume for the model data set label.

SPACE=(TRK,0) is coded because creating a data set on disk without allocating space to the data set results in just the data set label being created, which is all that is required. CREATING A DATA SET FOR A GENERATION DATA GROUP To create a new data set for a generation data group, you provide the generation number for the new generation. +---------------------------------------------------------------------------+ | //jobname JOB ... | | //STEP1 EXEC PGM=CREATE | | //IN DD ... | | //OUT DD DSN=X2222.ANNUAL.DATA(+1), | | // UNIT=SYSDA,VOL=SER=PACK12, | | // DISP=(NEW,CATLG),SPACE=(6160,(20,10)) | +---------------------------------------------------------------------------+ If the model data set being used for the generation data group does not have the same name as the generation data group, you must name this model data set with the DCB parameter: +---------------------------------------------------------------------------+ | //jobname JOB ... | | //STEP1 EXEC PGM=CREATE | | //IN DD ... | | //OUT DD DSN=X2222.ANNUAL.DATA(+1), | | // UNIT=SYSDA,VOL=SER=PACK12, | | // DISP=(NEW,CATLG),SPACE=(6160,(20,10)), | | // DCB=Y3333.MODEL.DATA | +---------------------------------------------------------------------------+ The requirements for creating a new data set for a generation data group are: o The DISP parameter must be CATLG. All the generation data group information is kept in the catalog. The DCB sub-parameters are copied from the model. The DCB Page 154 of 169

JCL FOR PROGRAMMERS

Parameter must refer to a data set name being used as the model. o You must name the new generation as follows: generation-data-group-name(+n) Although there must always be a model data set label when you create a new generation, you don't have to actually use any of its DCB sub-parameters. You +---------------------------------------------------------------------------+ | //jobname JOB ... | | //STEP1 EXEC PGM=CREATE | | //IN DD * | | //OUT DD DSN=X2222.ANNUAL.DATA(+1),DISP=(NEW,CATLG), | | // SPACE=(6200,(120,10)), | | // UNIT=SYSDA,VOL=SER=PACK12, | | // DCB=(Y3333.MODEL.DATA,BLKSIZE=6120) | +---------------------------------------------------------------------------+ The model data set label doesn't have to have the same name as the generation data group. If it has a different name, you can catalog it, too. Here's an example: +---------------------------------------------------------------------------+ | //jobname JOB ... | | // EXEC PGM=IEFBR14 | | //DD1 DD DSN=Y3333.MODEL,DISP=(NEW,CATLG), | | // SPACE=(TRK,0),UNIT=SYSDA,VOL=SER=PACK12, | | // DCB=(RECFM=VB,LRECL=255,BLKSIZE=6250) | | ... | | //jobname JOB ... | | // EXEC PGM=CREATE | | //IN DD ... | | //OUT DD DSN=X2222.ANNUAL.DATA(+1),DISP=(NEW,CATLG), | | // SPACE=(6160,(30,2),RLSE), | | // UNIT=SYSDA,VOL=SER=PACK12, | | // DCB=(Y3333.MODEL,RECFM=FB,LRECL=80,BLKSIZE=6160) | +---------------------------------------------------------------------------+ Y3333.MODEL is the model data set for the X2222.ANNUAL.DATA generation data group. None of Y3333.MODEL's DCB sub-parameters is used in this example. You can copy the following DCB sub-parameters from the model data set: DSORG RECFM LRECL BLKSIZE OPTCD KEYLEN RKP

Of course, you don't need to use any of them, if you don't want to.

JCL FOR PROGRAMMERS

Page 155 of 169

SESSION 12: _______ ___

DIRECT AND VSAM DATA SETS ______ ___ ____ ____ ____

TOPIC _____ 12.1 12.2

TITLE _____ Direct Data Sets VSAM Data Sets NEXT | TOP | PREVIOUS

JCL FOR PROGRAMMERS

Page 156 of 169

TOPIC 12.1: _____ _____

DIRECT DATA SETS ______ ____ ____

Direct data sets provide fast random access record retrieval. That is, you can retrieve any record in the data set equally fast, whether it is the first or last record in the data set. With sequential access, in contrast, you can retrieve the first record in the data set very fast, but it can take a relatively long time to retrieve the last record. In terms of function, you can do just about anything with sequential access that you can do with random access. But random access has the advantage of fast access. Direct data sets can be read or written sequentially or randomly. However, they cannot be blocked. Because they cannot be blocked, they have all these disadvantages: o o o Direct data sets take more disk space. Direct data sets are slow to process sequentially. Direct data sets can only be stored on a direct access storage device.

DIRECT DATA SET TYPES There are two types of direct data sets: o Relative: Data sets written in COBOL RELATIVE, FORTRAN direct, and PL/1 REGIONAL(1) are relative. You retrieve records by the relaTive record number: 1, 2, etc. Keyed: Data sets written in COBOL RANDOM and PL/I REGIONAL(2) and (3) are keyed. Each record has a field containing a value that identifies the record; the value is termed a key. To retrieve a record, you tell the system the record key and the relative track number on which the record is stored (several records may be on the same track).

RELATIVE DIRECT DATA SETS Relative direct data sets are similar to tables or arrays. The records are stored sequentially, and you can retrieve any record by giving its relative record number:

JCL FOR PROGRAMMERS

Page 157 of 169

Relative Record No. 0 1 2

n-1

+----------------+ | Record 1 | |----------------| | Record 2 | |----------------| | Record 3 | |----------------| | ... | |----------------| | Record n | +----------------+

A relative data set can have only RECFM=F. Relative records must have fixed- length unblocked records because the system calculates where each record is stored on the disk track. The records are stored on a track, end to end: Track: +-------------------------------------------------+ | Record 1 | Record 2 | Record 3 | ... | Record n | +-------------------------------------------------+ Since the records are fixed length, the system can easily calculate where the first, second, and nth records are stored. Creating a relative direct data set is easy. You just write the data set as you would a sequential data set, adding the DSORG sub-parameter. +---------------------------------------------------------------------------+ | //stepname EXEC PGM=program | | //IN DD ... | | //OUT DD DSN=data-set-name,DISP=(NEW,CATLG), | | // UNIT=SYSDA,VOL=SER=volume, | | // SPACE=(...), | | // DCB=(RECFM=F,LRECL=length,BLKSIZE=size,DSORG=DA) | +---------------------------------------------------------------------------+ To DSORG=DA tells the system that the data set organization is Direct Access. //ddname DD DSN=data-set-name,DISP=SHR (or OLD)

The relative direct data set can be read as if it were a sequential data set by using any of the usual utility programs or programming languages. To read or update the data set, you must use the appropriate COBOL RELATIVE, FORTRAN direct, or PL/I REGIONAL(1) statements. Here's a typical example in PL/I: READ FILE(file) INTO(area) KEY(key); KEYED DIRECT DATA SETS Keyed direct data sets are like relative direct data sets except for these differences: o The records in keyed direct data sets can be fixed, variable, or Page 158 of 169

JCL FOR PROGRAMMERS

undefined length. o the o

They still cannot be blocked.

Each record in a keyed direct data set must have a record key--a field in a fixed position in the record that uniquely identifies individual record. To read or write a record randomly, you must tell the system the relative track number on which the record resides and supply the value of the record key for the record you want on that track.

Each record in a keyed direct data set must have a key. The key is a field in each record that uniquely identifies the record. Here's an example: +----------------------------------------+ | data | 550-96-1966 | other data | +----------------------------------------+ The Social Security number here serves to uniquely identify the record. Every record must have a key in the same location within a record. You tell the system where the key is with two new DCB sub-parameters: RKP=relative-byte-position-of-record-key (relative means the bytes are numbered 0, 1, 2, ..., n) KEYLEN=key-length Here's a record with a Social Security number as the key: column: 1 2 12345678901234567890 550-96-1966

+---------------------------------------------------------------------------+ | //OUT DD DSN=A0000.TEST.DATA,DISP=(NEW,CATLG), | | // UNIT=SYSDA,VOL=SER=PACK12, | | // SPACE=(80,(2000,10),RLSE), | | // DCB=(DSORG=DA,RECFM=F,LRECL=80, | +---------------------------------------------------------------------------+ The RKP parameter numbers the bytes 0,1,2, ..., n. Columns: RKP: 12345678901234567890 01234567890123456789 550-96-1966 /|\ /|\ +-KEYLEN--+ Now here is how

We've described the position and length of the record key. the records are stored on a track: Track 1: +---------------------------------+ | A | B | C | D | +---------------------------------+ JCL FOR PROGRAMMERS

Page 159 of 169

Track 2: +---------------------------------+ | E | F | G | H | +---------------------------------+ The A, B, etc., represent the record keys. To retrieve a record, you: o o Tell the system the relative track number containing the record. Tell the system the value of the record key.

Track 1: +---------------------------------+ | A | B | C | D | +---------------------------------+ The system locates the record as follows: 1. It goes to the track you specified. 2. It reads each record on the track, continuing until it finds a record with a matching key. If the system reaches the end of the track without finding a record, it quits looking and tells you that it couldn't locate the record. To locate or update a record randomly in a keyed direct file, you use the COBOL RANDOM or PL/I REGIONAL(1) or (2) statements. You can actually allow the system to search forward some number of tracks for a record. This feature is often used in sophisticated applications where you store a new record by giving a track number and then searching forward until you find an available space to store the new record. Two new DCB subparameters are needed to allow the system to search forward onto additional DCB=(OPTCD=E,LIMIT=n,... where n is the number of tracks to search. Now we come to the difficult part of keyed direct files--finding out which track the records are stored on. There are two ways: o Keyed direct data sets can be created by writing the data set sequentially. Records cannot be added thereafter--unless you write dummy records that can be overwritten or skip over tracks to leave empty space. As you write each record, the system returns the relative track number. It's up to you to store this number in some way that enables you to associate a record key with the track number. Keyed direct data sets can be created randomly. You compute a track number from the record key and tell the system which track to store the record on. To retrieve the record later, you use the key to recompute the same track number. There are several techniques for computing the track number from the record key, but they are Page 160 of 169

JCL FOR PROGRAMMERS

beyond the scope of this course. When a direct data set, relative or keyed, is created with DISP=NEW and DSORG=DA, the system formats all the space in the data set. Since the space is preformatted, you can create the data set randomly by writing the records directly where you want them in the data set. The preformatting nulls out any areas that you don't write in. The things to consider when you choose between relative and keyed direct files are: o o Whether the language you use supports either or both. The most suitable arrangement for the data set. Relative direct is best when the data set can be treated like a table or array. In addition, the records must be fixed length. The purpose of the data set. Keyed direct is best when you want to have access to a record by supplying a key. Looking up vehicle information by giving a license plate number is an example. VSAM DATA SETS ____ ____ ____

TOPIC 12.2: _____ _____

VSAM (Virtual Storage Access Method) data sets are organized in one of three ways: o o Entry sequenced (ESDS), in which records are stored in the order they are entered. These records are essentially sequential files. Key sequenced (KSDS), in which records are stored in order of entry but retrieved on the basis of a record key. In essence, these records are sorted sequential files. However, the records can be accessed sequentially or randomly. Relative (RRDS). Relative records are the equivalent of relative direct data sets.

JCL FOR VSAM DATA SETS You must create VSAM data sets by using a VSAM utility program. Therefore, you write JCL only to access existing VSAM data sets. The JCL needed to access VSAM data sets is: //ddname DD DSN=data-set-name,DISP=SHR (or OLD)

You must use a VSAM utility program to both create and delete VSAM data sets. There is one DD parameter that you can code for VSAM data sets: //ddname DD AMP=('AMORG,option,option,...,option')

JCL FOR PROGRAMMERS

Page 161 of 169

AMORG is coded if the VSAM data set is to be made DUMMY or if the UNIT and VOL parameters are coded on the DD statement. AMORG tells the system that this DD statement describes a VSAM data set. The other options are as follows: BUFND=n is the number of buffers for the control data area data. An installation-defined default is assumed if BUFND is omitted. A minimum of two buffers must be provided. is the number of buffers for the index data. An installation default is assumed if BUFNI is omitted. A minimum of one buffer must be provided. specifies the same number for BUFND and BUFNI, overriding

BUFNI=n

both.

BUFSP=n

An installation-defined default is assumed if BUFSP, BUFND, and BUFNI are omitted. A minimum of two buffers must be specified. NRC NRE NCK RCK CROPS=___ gives the checkpoint/restart options as follows: RCK requests that both a data-erase test and a data set postcheckpoint modification test be performed. RCK is assumed if CROPS is omitted. NCK NRE NRC requests that the data set post-checkpoint modification test not be performed. requests that the data-erase test not be performed. requests that neither the data-erase test nor the data set post-checkpoint modification test be performed. names a module to be used by the EXLIST macro instruction.

SYNAD=modulename

TRACE requests that the generalized trace facility be used to gather statistics. STRNO=n gives the number of VSAM requests that requires concurrent data set positioning.

For the ISAM interface to VSAM, the following options can be coded: L I IL OPTCD=__ I

specifies how ISAM records flagged as deleted are to be processed by the program. means write records flagged as deleted only if DCB=OPTCD=L was not coded when the data set was created. Page 162 of 169

JCL FOR PROGRAMMERS

L IL

means write records flagged as deleted. means don't write records flagged as deleted. gives the format of the original ISAM data set, which can be F, FB, V, or VB.

RECFM=format

If you create a user catalog for your VSAM data sets, you also need to include a JOBCAT or STEPCAT DD statement to point to the catalog. (The catalog itself is created by using a VSAM utility that is beyond the scope of this course.) o JOBCAT is placed between the JOB and first EXEC statement and is effective for all job steps. //JOBCAT DD DSN=catalog-name,DISP=SHR o STEPCAT is placed following an EXEC statement and is effective just for that job step. JOBCAT is ignored for any step that contains a STEPCAT DD statement. //STEPCAT DD DSN=catalog-name,DISP=SHR The VSAM utility program used to create and delete VSAM data sets is named IDCAMS. IDCAMS itself is outside the scope of this course; what followsis a conceptual overview of VSAM. A separate master catalog is maintained for VSAM data sets, and this catalog can point to user catalogs. The user catalog and its data sets can all be copied together, which is important, since the catalog contains a lot of information about the data sets. +---------+ | Master | | Catalog | +---------+

\ \ +---------+ | User | | Catalog | +---------+ Contains passwords for data sets and the VSAM equivalent of DCB information for the data sets.

A VSAM data space, often an entire volume, is allocated by an installation for VSAM data sets by using a VSAM utility program. +---------+ | Master | | Catalog | +---------+ VSAM data space +---------------------+ | | \ | | \ | +---------+ | +---------+ | | Cluster | | | User |----->| | | | | Catalog | | +---------+ | +---------+ | | Page 163 of 169

JCL FOR PROGRAMMERS

| | +---------------------+ A portion of the VSAM data space, termed a cluster, is allocated to individual VSAM data sets by the IDCAMS utility program. The cluster allocated from the VSAM data space to a specific VSAM data set differs from a normal operating system data set in several ways: o o It can have 123 secondary allocations instead of 15. The system picks an optimum blocksize for the data set.

There's a lot more to VSAM data sets internally, but we won't go into that here. The point is that VSAM data sets are different from normal operating system data sets. VSAM DATA SET ORGANIZATION o Entry Sequenced Data Sets (ESDS): Records are stored in the order they are entered. They are less efficient than normal operating system sequential data sets, so they are seldom used. These are just sequential data sets stored under VSAM. Relative Record Data Sets (RRDS): These are the equivalent of relative direct data sets. They are described in the previous topic, so we won't go into them here. Key-Sequenced Data Sets (KSDS): Records are stored in order of entry but retrieved on the basis of a record key. These are sometimes called indexed data sets, and they replace the old, obsolete ISAM data sets. These data sets are the most common use for VSAM.

KEY-SEQUENCED DATA SETS Key-sequenced data sets have two parts: o o An index that contains the keys and a pointer to where the corresponding records are stored on the track. The record storage area.

Index Record storage area +----------------+ +-------------+ | Key | Location |----+ | Record 1 | +----------------+ | | Record 2 | | | ... | +---->| Record n | +-------------+ A library is an almost perfect analogy to a key-sequenced data set. correspond to records, and the card catalog corresponds to the index. Books

JCL FOR PROGRAMMERS

Page 164 of 169

The VSAM utility program blocks records by storing several records together. However, the VSAM equivalent of a block is termed a control interval.

JCL FOR PROGRAMMERS

Page 165 of 169

Index Key Location +-----------+ | A | 1 | | B | 1 | | C | 1 | | D | 2 | | ... | ... | +-----------+

Record storage area +--------------------------------+ | Control Interval 1 | |--------------------------------| | Record A | Record B | Record C | |--------------------------------| | Control Interval 2 | |--------------------------------| | Record D | ... | |--------------------------------| | ... | +--------------------------------+

Since the records are stored in sequential order based on their record keys, the index only needs to contain the key for the last record in a control interval. +-----------+ | C | 1 | | F | 2 | | I | 3 | | ... | ... | +-----------+ Control interval +--------------------------------+ 1 | Record A | Record B | Record C | 2 | Record D | Record E | Record F | 3 | Record G | Record H | Record I | +--------------------------------+

You can leave free space in a control interval to allow new records to be inserted. +---------------------------------------------+ | Record A | Record B | Record C | Free space | +---------------------------------------------+ If the records overflow the control interval, VSAM creates a new control interval and splits the records so there is free space in both control intervals. + | + +----------------------------------+ +---------------------------------| Record A | Record B | Free space | | Record C | Record D | Free space +----------------------------------+ +----------------------------------

To retrieve a record randomly, you supply a record key with the application language. The system does the following: 1. Finds the appropriate entry in the index--the one in which the key is less than or equal to this key. Page 166 of 169

JCL FOR PROGRAMMERS

2. Searches that control interval for a record with a matching key. Index Key Location +-----------+ | C | 1 | | F | 2 | | I | 3 | +-----------+ Control interval 1 2 3

+-----------------+ | A | B | C | | D | E | F | | G | H | I | +-----------------+

Since the records are stored in sequential order as well as on the basis of the record keys, the data set can be read sequentially. VSAM key-sequenced data sets provide these benefits: o o o Records are blocked in the data set. Access can be random for purposes of retrieving, adding, or updating records. Access can also be sequential, which allows the data set to be read sequentially.

Blocking, as always, conserves storage space and makes reading and writing considerably faster, especially for sequential access.

JCL FOR PROGRAMMERS

Page 167 of 169

APPENDIX: TRACK CAPACITY FOR 3380 AND 3350 DISK DEVICES _________ _____ ________ ___ ____ ___ ____ ____ _______ TOP | PREVIOUS

TABLE 1.

RECORDS PER TRACK ON 3380 DISK DEVICE Records From ------1045 1077 1141 1205 1269 1333 1397 1493 1589 1685 1781 1877 2005 2165 2325 2485 2677 2933 3189 3477 3861 4277 4821 5493 6357 7477 23477 Blocksize (bytes) Records To per track ---------------1076 30 1140 29 1204 28 1268 27 1332 26 1396 25 1492 24 1588 23 1684 22 1780 21 1876 20 2004 19 2164 18 2324 17 2484 16 2676 15 2932 14 3188 13 3476 12 3860 11 4276 10 4820 9 5492 8 6356 7 7476 6 9076 5 47476 1

Blocksize (bytes) From To per track ---------- ------------1 20 93 21 52 88 53 84 83 85 116 78 117 148 74 149 180 71 181 212 68 213 244 65 245 276 62 277 308 59 309 340 57 341 372 55 373 404 53 405 436 51 437 468 49 469 500 48 501 532 46 533 564 45 565 596 44 597 628 42 629 660 41 661 692 40 693 724 39 725 756 38 757 788 37 789 820 36 949 980 32 981 1044 31

JCL FOR PROGRAMMERS

Page 168 of 169

TABLE 2.

RECORDS PER TRACK ON 3350 DISK DEVICE Records From ------186 193 201 208 217 225 234 243 253 263 274 285 297 309 322 336 350 366 382 399 417 437 457 479 503 529 556 586 618 653 691 732 778 829 885 948 1019 1099 1191 1297 1955 2222 2566 3025 3666 4629 6234 9443 TOP Page 169 of 169 Blocksize (bytes) Records To per track ---------------192 51 200 50 207 49 216 48 224 47 233 46 242 45 252 44 262 43 273 42 284 41 296 40 308 39 321 38 335 37 349 36 365 35 381 34 398 33 416 32 436 31 456 30 478 29 502 28 528 27 555 26 585 25 617 24 652 23 690 22 731 21 777 20 828 19 884 18 947 17 1018 16 1098 15 1190 14 1296 13 1419 12 2221 8 2565 7 3024 6 3665 5 4628 4 6233 3 9442 2 19069 1

Blocksize (bytes) From To per track ---------- ------------1 1 103 2 3 102 4 5 101 6 7 100 8 9 99 10 11 98 12 13 97 14 15 96 16 17 95 18 19 94 20 22 93 23 24 92 25 26 91 27 28 90 29 31 89 32 33 88 34 36 87 37 38 86 39 41 85 42 44 84 45 46 83 47 49 82 50 52 81 53 55 80 56 58 79 59 61 78 62 65 77 66 68 76 69 71 75 72 75 74 76 78 73 79 82 72 83 86 71 87 90 70 91 94 69 95 98 68 99 102 67 103 106 66 107 111 65 112 115 64 131 135 60 136 141 59 142 146 58 147 152 57 153 158 56 159 165 55 166 171 54 172 178 53 179 185 52

JCL FOR PROGRAMMERS

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy