|
Data management is designed to provide a balance between ease of
use, migration to new releases, coexistence with various levels of
software and hardware, device independence, exploitation of hardware
features, and performance. Sometimes these considerations can conflict.
If your program exploits a particular model's features to maximize
performance, it might not take full advantage of newer technology.
It is the intent of IBM that your programs that use documented
programming interfaces and work on the current level of the system
will run at least equally well on future levels of the system. However,
IBM cannot guarantee that. Characteristics such as certain reason
codes that are documented only in z/OS DFSMSdfp Diagnosis are
not part of the intended programming interface. Examples of potential
problems are:
- Your program has a timing dependency such as a READ or WRITE macro
completes before another event. In some cases READ or WRITE is synchronous
with your program.
- Your program tests a field or control block that is not part of
the intended programming interface. An example is status indicators
not documented in Figure 1.
- Your program relies on the system to enforce a restriction such
as the maximum value of something. For example, the maximum block
size on DASD used to be less than 32 760 bytes, the maximum NCP
value for BSAM used to be 99 and the maximum block size on tape used
to be 32 760.
- New releases might introduce new return and reason codes for system
functions.
For these reasons, the operating system has many options. It is
not the intent of IBM to require extensive education to use assembly
language programming. The purpose of this topic is to show how to
read and write sequential data sets simply in High Level Assembler
while maximizing ease of use, migration potential, the likelihood
of coexistence, and device independence, while getting reasonable
performance.
You can use the examples in this topic
to read or write sequential data sets and partitioned members. These
include ordinary disk data sets, extended format data sets, compressed
format data sets, PDS members, PDSE members, UNIX files, UNIX FIFOs,
spooled data sets (SYSIN and SYSOUT), real or VM simulated unit record
devices, TSO/E terminals, magnetic tapes, dummy data sets, and most
combinations of them in a concatenation.
Recommendations:
- Use QSAM because it is
simpler. Use BSAM if you need to read or write nonsequentially or
you need more control of I/O completion. With BSAM you can issue the
NOTE, POINT, CNTRL, and BSP macros. These macros work differently
on various device classes. See Record Format—Device Type Considerations and Achieving Device Independence. Use BPAM if you need to access
more than one member of a PDS or PDSE.
- Specify LRECL and RECFM in the DCB macro if your program's logic
depends on the record length and record format. If you omit either
of them, your program is able to handle more types of data but you
have to write more code. See Selecting Record Formats for Non-VSAM Data Sets.
- Use format-F or format-V records, and specify blocking (RECFM=FB
or VB). This allows longer blocks. Format-U generally is less efficient.
Format-D works only on certain types of tape.
- Omit the block size in the DCB macro. Code BLKSIZE=0 in the DCBE
macro to use the large block interface. When your program is reading,
this allows it to adapt to the appropriate block size for the data
set. If the data set has no label (such as for an unlabeled tape),
the user can specify the block size in the DD statement or dynamic
allocation. For some data set types (such as PDSEs and UNIX files) there
is no real block size; the system simulates any valid block size and
there is a default.
When your program is writing and you omit DCB BLKSIZE and code
DCBE BLKSIZE=0, this enables the user to select the block size in
the DD statement or dynamic allocation. The user should only do this
if there is a reason to do so, such as a reading program cannot accept
large blocks. If the user does not specify a block size, OPEN selects
one that is valid for the LRECL and RECFM and is optimal for the device.
Coding BLKSIZE=0 in the DCBE macro lets OPEN select a block size that
exceeds 32 760 bytes if large block interface (LBI) processing
is being used, thereby possibly shortening run time significantly.
If OPEN might select a block size that is larger than the reading
programs can handle, the user can code the BLKSZLIM keyword in the
DD statement or the dynamic allocation equivalent or rely on the block
size limit in the data class or in the DEVSUPxx PARMLIB member.
If you want to provide your own default for BLKSIZE and not let
OPEN do it, you can provide a DCB OPEN exit routine. See DCB OPEN Exit. The installation OPEN exit might
override your program's selection of DCB parameters.
- Omit BUFL (buffer length)
because it relies on the value of the sum of BLKSIZE and KEYLEN and
because it cannot exceed 32 760.
- Omit
BUFNO (number of buffers) for QSAM, BSAM, and BPAM and NCP if you
use BSAM or BPAM. Let OPEN select QSAM BUFNO. This is particularly
important with striped data sets. The user can experiment with different
values for QSAM BUFNO to see if it can improve run time.
With BSAM and BPAM, code MULTSDN and MULTACC
in the DCBE macro. See Improving Performance for Sequential Data Sets.
With QSAM, BSAM, and BPAM this generally has no effect on the EXCP
count that is reported in SMF type 14, 15, 21, and 30 records. On
DASD, this counts blocks that are transferred and not the number of
channel programs. This causes the counts to be repeatable and not
to depend on random factors in the system.
- Omit BUFOFF because it works only with tapes with ISO/ANSI standard
labels or no labels.
- If you choose BSAM or BPAM in 31-bit addressing mode, do not use
the BUILD or GETPOOL macro and do not request OPEN to build a buffer
pool. If you code a nonzero BUFNO value, you are requesting OPEN to
build a buffer pool. Such a buffer pool resides below the line. Use
your own code to allocate data areas above the line.
- Code A or M for RECFM or code OPTCD=J only if your program logic
requires reading or writing control characters. These are not the
EBCDIC or ASCII control characters such as carriage return, line feed,
or new page.
- Omit KEYLEN, DEVD, DEN, TRTCH, MODE, STACK, and FUNC because they
are device dependent. KEYLEN also makes the program run slower unless
you code KEYLEN=0. The user can code most of them in the DD statement
if needed.
- Omit BFALN, BFTEK, BUFCB, EROPT, and OPTCD because they probably
are not useful, except OPTCD=J. OPTCD=J specifies that the records
contain table reference characters. See Table Reference Character.
- LOCATE mode (MACRF=(GL,PL)) might be more efficient than move
mode. This depends on your program's logic. The move mode requires
QSAM to move the data an extra time.
- If your program runs with 31-bit addressing mode (AMODE), code
RMODE31=BUFF in the DCBE so that the QSAM buffers are above the 16
MB line. A nonreentrant, RMODE 24 program (residing below the 16 MB
line) is simpler than a reentrant or RMODE 31 program because the
DCB must reside below the line in storage that is separate for each
open data set.
- Code a SYNAD
(I/O error) routine to prevent the 001 ABEND that the system issues
when a data set has an I/O error. In the SYNAD routine, issue the
SYNADAF macro, write the message, and terminate the program. This
writes a message and avoids a dump because the dump is not likely
to be useful.
- Use extended-format data sets even if you are not using striping.
They tend to be more efficient, and OPEN provides a more efficient
default for BUFNO. Avoid writing many blocks that are shorter
than the maximum for the data set because short blocks waste disk
space.
- If using dynamic allocation on non-VSAM data sets
allocated by your application program, and if the NON_VSAM_XTIOT=YES
option of the DEVSUPxx member of PARMLIB is in effect, code LOC=ANY
on the DCBE macro in your program. You should always set this option
before issuing an OPEN macro as the application program signifies
that the allocation can have an XTIOT that can reside above the line
(instead of a TIOT entry), the UCB can reside above the line and the
DSAB can reside above the line. If any of these three is true, then
OPEN will set the two-byte DCBTIOT field to zero instead of setting
it to an offset in the TIOT, and the application program will be able
to OPEN and process the data set allocated dynamically with an associated
XTIOT. The XTIOT, NOCAPTURE, and DSAB above the line option of dynamic
allocation will give VSCR benefits because each XTIOT is above the
line. Additionally, with XTIOTs come an increase on the limit of non-VSAM
data sets that can be allocated and opened in an address space at
one time. This limit for non-VSAM, non-XTIOT, data sets is about 3200
single volume data sets. Whereas, the non-VSAM, XTIOT limit is 100,000
data sets. A major problem addressed by supporting more than 3200
single volume data sets is VSCR.
Note: If the application program sets the DCBE option before OPEN,
but the NON_VSAM_XTIOT option of the DEVSUPxx member of PARMLIB is
not in effect, then OPEN will issue an ABEND 113–4C and a message
IEC142I.
Figure 1 shows the simplest way to read
a sequential data set.
Figure 1. Reading a Sequential Data Set OPEN (INDCB,INPUT) Open to read
LTR R15,R15 Branch if DD name seems not
BNZ ... to be defined
* Loop to read all the records
LOOP GET INDCB Get address of a record in R1
... Process a record
B LOOP Branch to read next record
* I/O error routine for INDCB
IOERROR SYNADAF ACSMETH=QSAM Get message area
MVI 6(R1),X'80' Set WTO MCS flags
MVC 8(16,R1),=CL16'I/O Error' Put phrase on binary fields
MVC 128(4,R1),=X'00000020' Set ROUTCDE=11 (WTP)
WTO MF=(E,4(R1)) Write message to user
SYNADRLS Release SYNADAF area, fall through
* The GET macro branches here after all records have been read
EOD CLOSE (INDCB) Close the data set
FREEPOOL INDCB Free the QSAM buffer pool
... Rest of program
INDCB DCB DDNAME=INPUT,MACRF=GL,RECFM=VB, Must be format-V *
DCBE=INDCBE
INDCBE DCBE EODAD=EOD,SYNAD=IOERROR,BLKSIZE=0 Request LBI
Figure 2 is the same as Figure 1 but converted to be reentrant and reside
above the 16 MB line:
Figure 2. Reentrant—Above the 16 MB LineCOPYPROG CSECT
COPYPROG RMODE ANY
COPYPROG AMODE 31
GETMAIN R,LV=Arealen,LOC=(BELOW,64)
LR R11,R1
USING MYAREA,R11
USING IHADCB,InDCB
USING DCBE,INDCBE
MVC IHADCB(AreaLen),MYDCB Copy DCB and DCBE
LA R0,DCBE Point DCB copy to
ST R0,DCBDCBE DCBE copy
OPEN (IHADCB,),MF=(E,INOPEN) Open to read
LTR R15,R15 Branch if DDname seems not
BNZ ... to be defined
* Loop to read all the records
LOOP GET INDCB Get address of a record in R1
... Process a record
B LOOP Branch to read next record
* I/O error routine for INDCB
IOERROR SYNADAF ACSMETH=QSAM Get message area
MVI 6(R1),X'80' Set WTO MCS flags
MVC 8(16,R1),=CL16'I/O Error' Put phrase on binary fields
MVC 128(4,R1),=X'00000020' Set ROUTCDE=11 (WTP)
WTO MF=(E,4(R1)) Write message to user
SYNADRLS Release SYNADAF area, fall through
* The GET macro branches here after all records have been read
EOD CLOSE MF=(E,INOPEN) Close the data set
* FREEPOOL not needed due to RMODE31=BUFF
... Rest of program
MYDCB DCB DDNAME=INPUT,MACRF=GL,RECFM=VB, *
DCBE=MYDCBE
MYDCBE DCBE EODAD=EOD,SYNAD=IOERROR,BLKSIZE=0,RMODE31=BUFF
OPEN (,INPUT),MF=L,MODE=24
AreaLen EQU *-MYDCB
DCBD DSORG=QS,DEVD=DA
IHADCBE Could be above 16 MB line
MYAREA DSECT
INDCB DS XL(DCBLNGQS)
INDCBE DS XL(DCBEEND-DCBE)
INOPEN OPEN (,),MF=L
|