z/OS DFSMS Using Data Sets
Previous topic | Next topic | Contents | Contact z/OS | Library | PDF


Retrieving a Member of a PDS

z/OS DFSMS Using Data Sets
SC23-6855-00

To retrieve a specific member from a PDS, you can use either BSAM or QSAM, as follows (see Figure 1):

  1. Code DSORG=PS or DSORG=PSU in the DCB macro.
  2. In the DD statement specify that the data is a member of an existing PDS by coding DSNAME=name(membername) and DISP=OLD, DISP=SHR or DISP=MOD.
  3. Process the member with an OPEN macro, a series of GET or READ macros, and the CLOSE macro.
Figure 1. Retrieving One Member of a PDS
   //PDSDD  DD    ---,DSN=MASTFILE(MEMBERK),DISP=SHR
            ...
            OPEN  (INDCB)            Open for input, automatic FIND
            ...
            GET   INDCB,INAREA       Read member record
            ...
            CLOSE (INDCB)
            ...
 
   INAREA   DS    CL80               Area to read into
   INDCB    DCB   ---,DSORG=PS,DDNAME=PDSDD,MACRF=GM

When your program is run, OPEN searches the directory automatically and positions the DCB to the member.

To process several members without closing and reopening, or to take advantage of additional data in the directory, use the procedure described in Figure 2 or Figure 3.

The system supplies a value for NCP during OPEN. For performance reasons, the example shown in Figure 3 automatically takes advantage of the NCP value calculated in OPEN or set by the user on the DD statement. If the FIND macro is omitted and DSORG on the DCB changed to PS, the example shown in Figure 3 works to read a sequential data set with BSAM. The logic to do that is summarized in Using Overlapped I/O with BSAM.

To retrieve a member of a PDS using the NOTE and POINT macros, take the following steps. Figure 2 is an example that uses note lists, which should not be used with PDSEs.

  1. Code DSORG=PO or POU in the DCB macro.
  2. In the DD statement specify the data set name of the PDS by coding DSNAME=name.
  3. Issue the BLDL macro to get the list of member entries you need from the directory.
  4. Repeat the following steps for each member to be retrieved:
    1. Use the FIND macro to prepare for reading the member records. If you use the POINT macro it will not work in a partitioned concatenation.
    2. The records can be read from the beginning of the member, or a note list can be read first, to obtain additional locations that point to subcategories within the member. If you want to read out of sequential order, use the POINT macro to point to blocks within the member.
    3. Read (and check) the records until all those required have been processed.
    4. Your end-of-data-set (EODAD) routine receives control at the end of each member. At that time, you can process the next member or close the data set.

Figure 2 shows the technique for processing several members without closing and reopening. This demonstrates synchronous reading.

Figure 2. Retrieving Several Members and Subgroups of a PDS without Overlapping I/O Time and CPU Time
   //PDSDD  DD    ---,DSN=D42.MASTFILE,DISP=SHR
 
            ...
            OPEN  (INDCB)               Open for input, no automatic FIND
            ...
            BLDL  INDCB,BLDLLIST        Retrieve the relative disk locations
   *                                      of several names in virtual storage
            LA    BLDLREG,BLDLLIST+4     Point to the first entry

Begin a member possibly in another concatenated data set
   MEMBER   FIND  INDCB,8(,BLDLREG),C   Position to member
            ...

Read the NOTE list:

            LA    NOTEREG,NOTELIST     Load address of NOTE list
            MVC   TTRN(4),14(BLDLREG)  Move NOTE list TTRN
   *                                   to fullword boundary
            POINT INDCB,TTRN           Point to the NOTE list record
            READ  DECBX,SF,INDCB,(NOTEREG)     Read the NOTE list
            CHECK DECBX
            ...

Read data from a subgroup:

   SUBGROUP POINT INDCB,(NOTEREG)    Point to subgroup
            READ  DECBY,SF,INDCB,INAREA  Read record in subgroup
            CHECK DECBY
            LA    NOTEREG,4(NOTEREG)  Increment to next subgroup TTRN
            ...
Repeat from label "SUBGROUP" for each additional subgroup
            AH    BLDLREG,BLDLLIST+2

Repeat from label "MEMBER" for each additional member
           ...
           CLOSE (INDCB)
           ...
 
   INAREA   DS    CL80
   INDCB    DCB   ---,DSORG=PO,DDNAME=PDSDD,MACRF=R
   TTRN     DS    F             TTRN of the NOTE list to point at
   NOTEREG  EQU   4             Register to address NOTE list entries
   NOTELIST DS    0F            NOTE list
            DS    F             NOTE list entry  (4 byte TTRN)
            DS    19F           one entry per subgroup
   BLDLREG  EQU   5             Register to address BLDL list entries
   BLDLLIST DS    0F            List of member names for BLDL
            DC    H'10'         Number of entries (10 for example)
            DC    H'18'         Number of bytes per entry
            DC    CL8'MEMBERA'  Name of  member
            DS    CL3           TTR of first record (created by BLDL)
            DS    X             K byte, concatenation number
            DS    X             Z byte, location code
            DS    X             C byte, flag and user data length
            DS    CL4           TTRN of NOTE list
            ...                 one list entry per member (18 bytes each)

The example in Figure 3 does not use large block interface (LBI). With BPAM there is no advantage in the current release to using LBI because the block size cannot exceed 32 760 bytes. You can convert the example to BSAM by omitting the FIND macro and changing DSORG in the DCB to PS. With BSAM LBI you can read tape blocks that are longer than 32 760 bytes.

The technique shown in Figure 3 is more efficient than the technique shown in Figure 2 because the access method is transferring data while the program is processing data that was previously read.
Figure 3. Reading a Member of a PDS or PDSE using Asynchronous BPAM
         OPEN  LIBDCB              Open DCB, setting RECFM, LRECL, BLKSIZE
         USING IHADCB,LIBDCB
         USING DCBE,MYDCBE         DCB addressability (needs HLASM)
         TM    DCBOFLGS,DCBOFPPC   Branch if open
         BZ    ---                   failed
         FIND  LIBDCB,MEMNAME,D    Position to member to read
         SR    R3,R3               GET NCP calculated by OPEN or
         IC    R3,DCBNCP             coded on DD statement
 (1)     LH    R1,DCBBLKSI         Get maximum size of a block
ROUND    LA    R1,DATAOFF+7(,R1)   Add length of DECB (READ MF=L) and pointer
         SRL   R1,3                  and round up to a
         SLL   R1,3                  doubleword length
         LR    R4,R1               Save length of DECB + pointer + block size
         MR    R0,R3               Calculate length of area to get
* Get area for DECB's, a pointer to the next DECB for each DECB and a data area
* for each DECB.  Each DECB is followed by a pointer to the next one and the
* associated data area.  The DECB's are chained in a circle.  DECB's must be
* below line; data areas can be above line if running in 31-bit mode, however,
* they will be retrieved below the line in this example.
         ST    R1,AREALEN          Save length of area
         GETMAIN R,LV=(R1),LOC=(BELOW,64) 
* DECB virtual addr below the line, but real above
         ST    R1,AREAAD
         LR    R5,R1
* Loop to build DECB's and issue first READ's.
BLDLOOP  MVC   0(NEXTDECBOFF,R5),MODELDECB  Create basic DECB
         LA    R1,0(R4,R5)                  Point to next DECB
         ST    R1,NEXTDECBOFF(,R5)          Set chain pointer to next DECB
         READ  (R5),SF,,DATAOFF(R5)         Store data address in DECB, issue READ
         AR    R5,R4                        Point to next DECB
         BCT   R3,BLDLOOP                   Branch if another READ to issue
         SR    R5,R4                        Point back to last DECB
         L     R1,AREAAD                    Point to first DECB
         ST    R1,NEXTDECBOFF(,R5)          Point last DECB to first DECB
         LR    R5,R1                        Point to first (oldest) DECB
* Loop to read until end-of-file is reached.
MAINLOOP CHECK (R5)                         Wait for READ, branch to EODATA if done
         L     R1,16(,R5)                   Point to status area
         LH    R0,DCBBLKSI                  Get length of read attempted
 (2)     SH    R0,14(,R1)                   Subtract residual count to read length
RECORD1  LA    R1,DATAOFF(,R5)              Point to first record in block
          .
          .    (Process records in block)
          .
         READ  (R5),SF,MF=E                 Issue new read
         L     R5,NEXTDECBOFF(,R5)          Point to next DECB
         B     MAINLOOP                     Branch to next block
* End-of-data.  
* CHECK branched here because DECB was for a READ after the last block.
EODATA   CLOSE LIBDCB
         L     R0,AREALEN
         L     R1,AREAAD
         FREEMAIN R,LV=(0),A=(1)
          .
          .
          .
AREAAD   DC    A(0)                               Address of gotten storage
AREALEN  DC    F'0'                               Length of gotten storage
LIBDCB   DCB   DSORG=PO,DCBE=MYDCBE,MACRF=R,DDNAME=DATA
MYDCBE   DCBE  MULTSDN=2,EODAD=EODATA,MULTACC=1   Request OPEN to supply NCP
         READ  MODELDECB,SF,LIBDCB,MF=L
NEXTDECBOFF EQU  *-MODELDECB                      Offset to addr of next DECB
DATAOFF  EQU   NEXTDECBOFF+4                      Offset to data
MEMNAME  DC    CL8'MASTER'                        Name of member to read
         DCBD  DSORG=PS,DEVD=DA
         IHADCBE ,
Tip: You can convert Figure 3 to use LBI by making the following changes:
  • Add BLKSIZE=0 in the DCBE macro. Coding a nonzero value also requests LBI, but it overrides the block size.
  • After line (1), test whether the access method supports LBI. This is in case the type of data set or the level of operating system does not support LBI. Insert these lines to get the maximum block size:
             TM    DCBEFLG1,DCBESLBI                  Branch if access method does
             BZ    ROUND                                not support LBI
             L     R1,DCBEBLKSI                       Get maximum size of a block
  • After line (2) get the size of the block:
             TM    DCBEFLG1,DCBESLBI                 Branch if
             BZ    RECORD1                            not using LBI
             SH    R1,=X'12'                        Point to size
             L     R0,0(,R1)                         Get size of block

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014