IEFBR14

I E F B R 1 4   Mysteries of IEFBR14 Revealed —

People ask what IEFBR14 does.  If you laughed at that, move along to some other reading material.

There, now we’re alone to investigate the mysteries of IEFBR14.  You’re new to the mainframe perhaps. 

If you have read the previous introductory JCL post, you know that the only thing you can ask the mainframe to do for you is run a program (as specified by EXEC in JCL), and when that happens the system does various setup before running the program, plus various cleanup after the program.  Most of that setup and cleanup is orchestrated by what you specify on the DD statements (DD means Data Definition).   So when you run a program, any program, you have quite a bit of control over the actions the system will take on your behalf,  processing your DD statements.

When the program IEFBR14 runs, IEFBR14 itself does nothing, but when you tell the system to run a program (any program), that acts as a trigger to get the system to process any DD statements you include following the EXEC statement.  So you can use that fact to create and delete datasets just with JCL.  

For example, you might specify DISP=(NEW,CATLG) on a DD statement for a dataset if you want the system to create the dataset for your program just before the program runs (hence NEW), and you want the system to save the new dataset when the program ends, and you also want the system to create a catalog entry so you can access the dataset again just by its name, triggering the system to look the name up in the catalog (hence CATLG).

So all you need to do to create a dataset is to put in a DD statement after the EXEC for IEFBR14, and on the DD statement you specify DSN= whatever name you want the new dataset to have, you specify DISP=(NEW,CATLG) as just mentioned, and rather than specify a lot of other information you pick an existing dataset you like and just model the parameters for this new one based on that, saying LIKE=selected.model.dataset — the DDname on the DD statement can be anything syntactically valid, that is, not more than 8 characters long, starts with a letter or acceptable symbol, and contains only letters, numbers, and the aforementioned acceptable symbols, which are usually #, @, and a currency symbol such as $.

Example:
 
//MYJOB  JOB  1,SAMPLE,MSGCLASS=X,CLASS=A
//BR14  EXEC  PGM=IEFBR14
//NEWDATA  DD  DSN=MY.NEW.DATA,DISP=(NEW,CATLG),
//    LIKE=MY.MODEL.DATASET

So the system creates the dataset.  Your program does not create it.  Your program might put data into it (or not), and the system doesn't care about the data.  The system manages the dataset itself based on what you specify in the DD statement in the JCL – or if a program really needs to create a dataset then the program builds the equivalent of a DD statement internally and invokes “dynamic allocation” to get the system to process the specifications the same as if there had been a DD statement in JCL.

In such a case the system processes that “dynamic allocation” information exactly the same way it would have processed it if you had supplied the information on a DD statement present in the JCL.

To delete an existing dataset you no longer want, you can specify DISP=(OLD,DELETE) on the DD statement, and the system will delete the dataset.  This is similar to the way it would delete a dataset if you issued the DELETE command under TSO, or using  IDCAMS, but there are a couple of important nuances you need to know about  deleting datasets.  

One is that it is a big mistake if you try to delete a member of a dataset using JCL.  The DISP you specify applies to the entire dataset, even if you put a member name in parentheses.    Never say DELETE for a Member in JCL; you will lose the entire library.

The second thing you need to know about deleting a dataset is that, for ordinary cataloged data sets, saying DELETE causes the deletion of both the dataset and the catalog entry that points to it.  That's fine and works for most cases, but sometimes you might have just a dataset with no catalog entry, and other times you might have a catalog entry pointing to a dataset that isn't really there anymore.

If you have a dataset that is not cataloged, then you need to tell the system where it is.  You do that by specifying both the UNIT and VOL parameters.   UNIT identifies the type of device that holds the dataset, something like disk or tape, which you might be able to specify just by saying UNIT=3390 (for disk) or UNIT=TAPE.   VOL is short for VOLUME, and identifies which specific disk or tape contains your dataset.  So UNIT is a class of things, and VOL, or VOLUME, is a specific item within that class.  

It turns out that coding UNIT isn't usually as simple as saying UNIT=DISK.  The people responsible for setting up your system can name the various units anything they want.  UNIT=TEST and UNIT=PROD are common choices.  The system, as it comes from IBM, has UNIT=SYSDA and UNIT=SYSALLDA as default disk unit names, but some places change those defaults or restrict their use.  If you have access to any JCL that created or used the dataset, it would likely contain the correct UNIT name — because if there is no catalog entry for an existing dataset, then every reference to the dataset has to specify UNIT.

When you first create a dataset, you are required to supply a UNIT type, but you are not required to specify a VOLUME — the system will select an available VOLUME from within the UNIT class you specified.  

If you are dealing with a dataset that was created with just the UNIT specified, and DISP=(NEW,KEEP), then you need to find the output from the job that created the dataset.  The JCL part of the listing will show what volume the system selected for the dataset.

To code the VOL parameter in your JCL, typically you say VOL=SER=xxxxxx, where xxxxxx is the name of the volume.  There are various alternatives to this way of coding it,  SER is short for Serial Number.  The names of tapes used to be 6-digit numbers in most places, for whatever reason — possibly to make it easy to avoid duplication.  Besides Serial Number, the volume parameter has other possible subparameters too,  but you don't care right now.

If you don't know what UNIT name to use, but you do know the volume where the dataset is, then go into  something like TSO/ISPF 3.4 and do a listing of the volume.  Select any other dataset on the volume and request the equivalent of ISPF 3.2 dataset information. Whatever UNIT it says, that should work for every dataset on the volume.

Note that it is possible for the same volume to be a member of more than one UNIT class.  It might belong to 3390, SYSDA, and TEST for example.  In that case it doesn't matter which UNIT name you specify for the purpose of finding (and deleting) the dataset.  The only point of putting UNIT into your JCL for an existing dataset is to help the system find it.

Note that it is possible to have multiple datasets with exactly the same name on different volumes and in different UNIT classes.  An easy example to visualize is having a disk dataset that you copy to a tape,  giving it the same DSN, and then later you copy it again to a different tape.  

Another, more perverse, example occurs when someone creates a new dataset they intend to keep, but mistakenly specifies DISP=(NEW,KEEP) rather than DISP=(NEW,CATLG).  Later they can't find the dataset, because no catalog entry was created. Rather than figure out what happened, they run the same job again.  If the system puts the second copy of the dataset onto a different disk volume, they now have two uncataloged copies of it.  If they keep doing that, at some point the system will select a volume that already has a copy of the dataset, and then the job will fail with an error message saying a duplicate name exists on the volume.  To clean up something like that, you need to find every uncataloged copy of the dataset  and delete it, specifying VOL and UNIT along with DISP=(OLD,DELETE) — you can use IEFBR14 for that.

On many systems, they have it set up so that a disk housekeeping program runs every night (or on some other schedule), and deletes all uncataloged disk datasets.  So if you find yourself in possession of a set of identically named uncataloged disk datasets, and you don't want to look for all the volume names, you might get lucky if you wait for a possible overnight housekeeping utility to run automatically and delete them for you.

One other point on those uncataloged datasets.  You also have the option of creating a catalog entry for a dataset, rather than deleting it, if you want to keep it around.  To do that, you specify UNIT and VOL, as just discussed, and DISP=(OLD,CATLG) — but you can only have one cataloged copy of any dataset name.

So, back to the point we touched on earlier, about how a program can create the equivalent of a DD statement internally.

It is also possible for part of the information to be specified on a DD statement in JCL, and part of the information to be specified in the program.  In that case the program needs to specify its DD modifications before the OPEN for the file.  The system then merges what the program specified with what the JCL specified, and if there’s a difference then the program takes precedence.  So the program can change what the JCL said, and the program wins any disagreements – but the program has to have its say BEFORE the OPEN for the file.

Note that IEFBR14 does not OPEN any files.  The system does the setup and cleanup involved in allocation processing, and only that. Various JCL specifications can be used to indicate processes that occur only at OPEN or CLOSE of a file.  Releasing unused disk space is an example of that.  If you code the RLSE subparameter in your SPACE parameter on a DD statement for IEFBR14,  that subparameter is ignored; no space is released.

This general discussion of DD parameters that can be specified within a program is pretty much irrelevant to IEFBR14, except to note that IEFBR14 does no file handling of any kind, so it will never override anything in your JCL (as some other program might).  So if you use IEFBR14 to set up a dataset, and the dataset does not come out the way you wanted, that is not due to anything IEFBR14 did. Because IEFBR14 does nothing.

If some item of information about a dataset is not specified in JCL, and the program does not specify it either, then if it is a dataset that already exists, the system looks to see if the missing item of information might be specified in some existing saved information relevant to the dataset, such as the Catalog entry or the Dataset Label.  Things like record length, record format, and allowable space allocation are generally kept in the Dataset Label for ordinary datasets.  For VSAM datasets most of the information is kept in the Catalog.  The system looks for the information, and if the information is found, it merges it together with the information obtained from the program and the JCL to form a composite picture of the dataset.

What if the system needs to know something about a dataset – record length, for example (LRECL), or record format (RECFM) or one of those other parameters – and after looking in all three places just named, the system has not found the information anyplace – what happens?  Default values apply.  Ha ha, because you don’t usually like the defaults, with the single glowing exception of BLKSIZE where the default is always the best value possible.  The system can calculate BLKSIZE really well.  Other defaults – you don’t want to know.  So specify everything except BLKSIZE.  You don’t need to specify everything explicitly though, you can use the LIKE parameter to specify a model.  Then the system will go look at the model dataset you’ve specified and copy all the attributes it can from there, rather than using the very lame system defaults.  So you specify whatever parameters you want to specify, and you also say LIKE=My.Favorite.Existing.Dataset to tell the system to copy everything it can from that dataset’s settings before applying the <<shudder>> system defaults.  Note: The system will not copy BLKSIZE from the model you specify in LIKE.  No, the system knows where its strengths and weaknesses lie.  It recalculates the BLKSIZE unless you explicitly specify some definite numeric you want for that.

Also note that any particular system, such as the one you're using, can be set up with Data Classes and other system-specific definitions of things that affect defaults for new datasets.  Something could be set up, for example, stating that by default a new dataset with a certain pattern of DSN would have certain attributes.  If so, that would generally take precedence over any general IBM-supplied system defaults, but usually stuff you specify explicitly will override any site-specific definitions of attributes — unless, of course, the ones on your system were purposely set up designating they couldn't be overridden.

Okay, so then, does IEFBR14 do some magical internal specifications?  Nope.  IEFBR14 does absolutely nothing.  You do the work yourself by specifying everything you want on the DD statements.  IEFBR14 never opens the files, modifies nothing, does nothing.  You can code your own program equivalent to IEFBR14 by writing no executable program statements except RETURN. Or, for that matter, no statements at all, since most compilers will supply a missing RETURN at the end for you.  Yes, that is IEFBR14.  Laziest program there is: Lets the system do all the work.

You can use any ddnames you want when you run IEFBR14.  The files are never opened.  The system does the setup prior to running the program, including creating any new files you’ve requested.  The program runs, ignoring everything, doing nothing.  When it ends, the system does the cleanup, including deleting any datasets where you specified DELETE as the second subparameter of DISP.

So that’s how it works.  Often people think IEFBR14 does some magic, but it doesn’t.  It relies on the system to go through the normal setup and cleanup. 

You can add extra DD statements into any other program you might happen to be running, and the system will do the same setup and cleanup.  Of course you’d need to be sure the program you pick doesn’t happen to use the ddnames you pick – you wouldn’t want to use ddnames like SYSUT1 or SYSUT2  with most IBM-supplied programs, for example. 

Ddnames SALLY, JOE, and TOMMY should work just fine though.  The IEFBR14 program doesn’t look at them.  The system doesn’t know and doesn’t care whether the program uses the datasets. 

People use IEFBR14 for convenience because they know for sure that the program will not tamper with any of the file specifications. 

How did IEFBR14 get its name?  Well, the IEF prefix is a common prefix IBM uses for system-level programs it supplies.  BR14 is based on the Assembler Language instruction : BR 14
which means Branch (BR for branch) to the address contained in register 14 — the pointer that holds the return address.  So, Branch to the Return Address, that is, Return to Caller.

Correction 23 November:  Sorry, it's parsed BR 14 rather than B R14.    The notation BR in Assembler Language means Branch to the address contained in the specified Register, as distinct from B. branching to an address specified some other way, for example as a label within the program.

That’s it, secrets of IEFBR14 revealed.

Or,  JCL Basic Concepts part II 

5 comments on “IEFBR14

  1. David, as usual you are SO right. If one wants to create a dataset using IEFBR14, one should be sure that the next program to use that dataset opens it for output.
    . . . Funny thing happened to me one time. I was the only one using the system, and was comparison testing different versions – release levels – of the same software. Some JCL created a card image (FB 80) dataset at the start, put control cards into it, and deleted it at the end. The next set of JCL, for another version of the software, also created the same dataset, and the system gave it the same piece of disk space where the previous dataset had been. Some set of events transpired such that on the second run the software did not write the control cards into the dataset. However, a later step opened the dataset for input. It was able to read the control cards left over from the previous run. Though I never saw such a thing happen in any other situation anyplace ever, it is probably still possible, and illustrates the problem you point out.
    Thanks.

  2. Shivan, It depends on other factors — on what you're trying to do in a larger context.
    If you use IEFBR14, you do everything with DD statements in the JCL; This means the dataset names are plainly visible to anyone looking at the JCL, and also makes it easy to use symbolic parameters, that is, JCL variables. So for example you could specify DSN=&SYSUID..NEW.DATASET to ask the system to create a new dataset starting with the TSO userid that submitted the job. Also you have the opportunity to specify additional JCL parameters if you wish to do so. Using IEFBR14 also means that any detected errors are plainly visible in the job log, mixed in with other JCL messages. Plus the return code from IEFBR14 is always zero.
    On the other hand, if you supply IDCAMS control statements on SYSIN cards, or if you supply TSO commands on SYSTSIN cards, opting to control your datasets using IDCAMS or IKJEFT01 — or any other program you might have — then you have a different set of advantages and disadvantages. You can get a non-zero return code if you want that as an option. Error detection is handled differently, with error messages being shown in the program output rather than as JCL errors. IDCAMS is generally the best choice if you allocate a lot of VSAM files. IDCAMS runs faster than IKJEFT01; of course nothing uses less CPU TCB time than the lazy and simple IEFBR14.
    What program to use depends on the details of what you want to do and how you want contingencies to be handled.

  3. [Just as with LinkedIn, I see WordPress here strips leading blanks, so I'll repost the above source code with the same leading "__" chars I use over there. These should be changed to spaces before attempting to assemble the source.]

    __ CSECT
    __ USING *,15
    __ BAS 2,GO
    __ OPEN MF=L,(DCB,OUTPUT)
    GO OPEN MF=(E,(2))
    __ CLOSE MF=(E,(2))
    __ SVC 3
    DCB DCB DDNAME=FILE,DSORG=PS,MACRF=E
    __ END

  4. Nice writeup on IEFBR14! When I first used it I was surprised to discover it didn't open files, so any file allocated with it lacked an EOF mark. This of course caused big problems for any program which then tried to read it. So, my shop wrote a COBOL program to OPEN and CLOSE a specific DDNAME, which then both initialized and allocated the file at the same time.
    Lately, out of curiousity (and maybe a little OCD*!) I've been trying to create the smallest possible program which does the same thing. Here's my latest, 48 bytes total. I challenge anyone to create one smaller than that! ;-)
    CSECT
    USING *,15
    BAS 2,GO
    OPEN MF=L,(DCB,OUTPUT)
    GO OPEN MF=(E,(2))
    CLOSE MF=(E,(2))
    SVC 3
    DCB DCB DDNAME=FILE,DSORG=PS,MACRF=E
    END

    [*OCD – Obsessive/Compulsive Disorder]

  5. Excelent!
    I have a question though, it's better use IDCAMS to delete datasets or IEFBR14? it's basically the same?

    Thanks!

Comments are closed.