MVS TOOLS AND TRICKS OF THE TRADE October 1991 Sam Golob MVS Systems Programmer sbgolob@cbttape.org EXPLOITING PARTITIONED DATASET DIRECTORY FIELDS: PART II. SUMMARY OF PART I. This month, we shall continue on the subject of exploiting various fields in the partitioned dataset directories. Last month we discussed the structure of directory entries, and how each entry is variable in length, containing 12 bytes of required fields, and up to 62 bytes of user fields. To refresh your memory, see the DSECT description in Figure One. Load library directories are a specialized example of "official IBM use" of the "user fields" in the pds directory entry. Directory entry fields that are critical in the execution of load modules, are really "optional user fields" in the native pds architecture. IBM has merely adapted the directory architecture to support necessary functions in the linkage editing and program fetch components of MVS. ISPF statistics are another example of IBM's utilization of these "user" fields. Under the ISPF editor, fixed blocked or variable blocked pds members have statistics stored in each member's directory entry user fields. These stats help track things like creation and last-update dates, member size, and the last userid to update the member. See Figure Two for a DSECT description of "ISPF stats". Other IBM and vendor program products also make specialized usage of "optional" pds directory entry fields. SMP/E and IMS are IBM products which will utilize pds directory entry user fields for special purposes. Our aim here, is to try and notice points where a change in a directory entry field performs a useful or a critical function. For example, rather than re-linkediting a load module, flipping the proper directory entry bit(s) may accomplish the same purpose in less time. Knowing about such facts can save us much grief, and can help us in many other ways during our daily work. THE "STOW" MACRO. The principal data management macro dealing with pds directory entries is the STOW macro. "STOW" is usually involved when you want to add a pds member, delete a member, rename a member, or replace an existing member with a another one of the same name. It isn't too hard to use STOW in a program. I've included a coding example here (see Figure Three). However, the purpose of mentioning the STOW macro here, is not to teach you how to code it. Rather, my aim is to provide some insight into how a pds directory entry is created or changed. With that knowledge behind us, it'll be a lot easier to understand the directory entry manipulations that we'll talk about later. STOW needs three parts. Its first operand points to the DCB address of the partitioned dataset to be operated on. The second operand is the address of a data area. Finally the third operand is one of four function codes: "A" for adding a member, "R" for replacing an existing member, "C" for changing a member name (renaming), and "D" for deleting a member. In the case of adding ("A") or replacing ("R"), the data area will be an image of the directory entry itself. In the case of member deletion ("D"), the data area contains an 8-byte member name field. Finally, in the case of renaming a member or changing it ("C"), the data area is a 16-byte area containing the old name in the first 8 bytes, and the new name in the second 8 bytes. Each different function of STOW (A, R, C, or D) has its own set of return codes. These are explained in the Data Management Macro Instructions manual in detail. However, the ADD function will return a code of 0 if the member didn't previously exist and was successfully added. The ADD function will return a code of 4 if the name previously existed in that directory. The REPLACE function on the other hand, returns a code of 0 if a member replace was done successfully, and it returns a code of 8 if that member name was not previously there. You can see by looking at the coding example, that the results of the STOW macro can be neatly handled using a branch table. Our coding example involves either the ADD or REPLACE functions of STOW. Therefore, our data area is an image of the actual directory entry in both of these cases. Our example program does a CLIST format conversion, which is essentially a copy operation from an input dataset to an output dataset. If ISPF statistics existed for an input dataset member, they are copied into the STOW data area for the output dataset member. However it is possible, because of line splits occurring during the reformatting process, that the output record count will increase by the number of line splits. Our example shows how we discover the presence of ISPF statistics in a member, and how we increase an existing ISPF record count by the number of line splits, right before the STOW is done. RELATING THE STOW MACRO TO ISPF STATS. Most of us are familiar with the ISPF option 3.5, which can add ISPF statistics to "source-type" pds members if there weren't any. Option 3.5 can also be used to change the USERID field in the ISPF stats, or the version and modification number fields. It should now be obvious that this is done using the STOW macro with the REPLACE option. Record counts are taken by the appropriate ISPF service program. These are fed into a formatted data area in the program before the STOW REPLACE is done. The STOW re-creates the directory entry for the affected member, adding new ISPF stats in the user fields for the new entry, or changing pre-existing ones. As an exercise, you can write an assembler program to manipulate some ISPF stats (or any other directory entry format, for that matter). You'll first need a method of feeding parms or input control cards to your program. Then, you can access any member of your target dataset using BPAM (see the CVTCLIST program on the CBT Tape File 187 for a relevant coding example). You can then copy the directory information for each affected dataset member into a data area that's formatted for ISPF stats. Finally, you can do your directory entry field manipulations and do a STOW for the member, using the REPLACE option, and keeping the TTR the same. Although there are easier ways to change ISPF stats, this method actually works, and it can be generalized greatly to deal with other types and formats of directory entry user fields. WHAT'S LEFT? Next month, we'll continue with the large subject of load module directory entries, an "official IBM use" of pds directory entry user fields. These "user" fields contain essential load module information that can be useful to manipulate. Meanwhile, I hope that our current material is enough to chew on for now. Good luck. See you next month. * * * * * * * * * * * * * * * * * * * * * * * FIGURE ONE: DSECT Descriptions of Partitioned Data Set Directory Entries. The required portion of the directory entry (first 12 bytes) is shown here. This description was mostly taken from source code for the PDS Program Product, Version 8.4, which can be found on File 182 of the CBT MVS Utilities Tape, member @DIALOG. You can refer to the macro IHAPDS in SYS1.AMODGEN for IBM official field names. DIRLINK DS 0F *** DIRECTORY AREA MAPPING *** * DIRNAME DS CL8 Member Name DIRTTR DS XL3 TTR of beginning of the Member DIRFLAG DS X Contains 3 flags in high-order bits. * Low-order 5 bits contain number of * halfwords in user-defined fields to * follow this point (62 bytes maximum). * DIRALIAS EQU X'80' This member is an alias. DIR2TTR EQU X'40' Two TTR's to update DIR1TTR EQU X'20' One TTR to update * DIRUSER DS XL62 Maximum length of directory entry * user fields. Actual length depends on * the number of halfwords indicated by * the 5 low-order bits of DIRFLAG * (the 12th byte of the directory entry). * * * * * * * * * * * * * * * * * * * * * * * FIGURE TWO: DSECT Description of Partitioned Data Set Directory Entries. These are for source-type members that have ISPF statistics. ISPF statistics are merely a special use of partitioned data set directory user fields. DIRLINK DS 0F *** DIRECTORY AREA MAPPING *** * DIRNAME DS CL8 Member Name DIRTTR DS XL3 TTR of beginning of the Member DIRFLAG DS X Contains 3 flags in high-order bits. * Low-order 5 bits contain number of * halfwords in user-defined fields to * follow this point (62 bytes maximum). * DIRALIAS EQU X'80' This member is an alias. DIR2TTR EQU X'40' Two TTR's to update DIR1TTR EQU X'20' One TTR to update * DIRSPFOF EQU B'01110000' BITS ARE OFF IN ISPF STATS. DIRSPFON EQU B'00001111' BITS ARE ON IN ISPF STATS. * DIRUSER DS XL62 Directory Entry User Fields. 62 bytes max. (28 Bytes are used by ISPF Stats) * ORG DIRUSER FOLLOWING FOR MODULES SAVED BY ISPF EDIT. DIRSPFV DS XL1 Version Number in Binary DIRSPFR DS XL1 Revision Number in Binary DIRSPFZ DS XL2 Not currently used DIRSPFCR DS XL4 Creation Date in format 00YYDDDF DIRSPFCD DS XL4 Last Change Date in format 00YYDDDF DIRSPFCT DS XL2 Last Change Time in format HHMM DIRSPFSI DS XL2 Current Size in Binary (max 65535) DIRSPFIN DS XL2 Initial Size in Binary DIRSPFMD DS XL2 Modified Lines in Binary DIRSPFID DS CL8 ID of Last Person to Update * * * * * * * * * * * * * * * * * * * * * * * FIGURE THREE. Code (taken from CLIST Conversion program on File 187 of the CBT MVS Utilities Tape) which illustrates the testing for ISPF statistics, and for alias members. This code will increment the ISPF "size" statistics. When a CLIST is converted from VB-255 byte format to FB-80 byte format and line splits are performed, the new CLIST in FB-80 byte format has a record count equal to the old record count, plus the count of "line splits" done. The code below is used to increase the record count from the old ISPF stats, if they exist, by the count of line splits. This code also illustrates STOW ADD and STOW REPLACE with their varying return codes. For more information see the DFP Data Management Macro Instructions manual. BUMPSTTS DS 0H BUMP ISPF STATS IF WE SPLIT LINES. * ST R8,SAVE8REG SAVE R8 FOR WORK LA R8,DIRLIST LOAD R8 FOR MAPPING USING DIRSECT,R8 MAP DIRECTORY WKAREA * * DO WE HAVE SPF STATS LEGITIMATELY? THEN BUMP LINE COUNT. * (See Figure Two for the meanings of Field Labels.) * TM DIRFLAG,DIRSPFOF CK FOR BITS THAT SHOULD BE OFF BNZ ALISTEST THEY'RE NOT: NO SPF STATS TM DIRFLAG,DIRSPFON CK FOR BITS THAT SHOULD BE ON BNO ALISTEST THEY'RE NOT: NO SPF STATS CLI DIRSPFCR,0 00 OF 00YYDDDF ZEROS? BNZ ALISTEST NO, BRANCH CLI DIRSPFCD,0 00 OF OTHER 00YYDDDF ZERO? BNZ ALISTEST NO, BRANCH * * ALL TESTS PASSED: ASSUME WE HAVE SPF STATS ST R7,SAVE7REG SAVE R7 FOR WORK CP MEMSPLTS,ALWZERO WERE THERE ANY SPLITS? BNH BYPASADD NO. DON'T INCREMENT STATS. * * NUMBER OF SPLIT LINES MUST BE ADDED TO RECORD COUNT IN THE STATS ZAP PACKWORK,MEMSPLTS GET COUNT OF LINE SPLITS READY CVB R7,PACKWORK CONVERT NO OF SPLITS TO BINARY AH R7,DIRSPFSI ADD ORIGINAL NO OF RECORDS STH R7,DIRSPFSI STORE UPDATED COUNT IN DIRECTORY BYPASADD L R7,SAVE7REG RESTORE R7 DROP R8 * * COUNT THE NUMBER OF ALIAS MEMBERS BEING CONVERTED ALISTEST L R8,SAVE8REG RESTORE R8 NI FLAGG,255-ALIASED RESET ALIAS FLAG TM DIRLIST+11,X'80' IS MEMBER AN ALIAS? BNO GOSTOW NO, DON'T COUNT IT OI FLAGG,ALIASED FLAG AS ALIAS NI DIRLIST+11,X'7F' TURN OFF ALIAS BEFORE STOW GOSTOW DS 0H TM FLAGG,STOWADD THIS A NOREPLACE RUN? (set by a parm) BO STOWAD YES -- STOW ADD ONLY B STOWREP NO -- STOW REPLACE EJECT * - - - - - - - ILLUSTRATIONS OF THE "STOW" MACRO. - - - - - - - * * STOWREP STOW CLISTOUT,DIRLIST,R STOW WITH REPLACE SPACE 2 * Branch on return codes B STOWEND(R15) STOWEND B CHEKREPL GOOD REPLACE RC = 0 NOP ERRA B CHEKCOPY GOOD MEMBER ADD RC = 8 B ERRB B ERRC NOP ERRA ERRD MVC ERRORMSG,MSGD B ERR ERRC MVC ERRORMSG,MSGC B ERR ERRB MVC ERRORMSG,MSGB B ERR ERRA MVC ERRORMSG,MSGA B ERR INERROR MVC ERRORMSG,MSGRJI MVC RC,=H'04' B WRITERR OUTERROR MVC ERRORMSG,MSGRJO MVC RC,=H'04' B WRITERR ERR MVC RC,=H'12' B WRITERR EJECT * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * STOWAD STOW CLISTOUT,DIRLIST,A STOW WITH ADD SPACE 2 * Branch on return codes B STOWENDA(R15) STOWENDA B CHEKCOPY GOOD REPLACE RC = 0 B CHEKNORE NO REPLACE RC = 4 NOP ERRBA B ERRBA B ERRCA NOP ERRAA ERRDA MVC ERRORMSG,MSGD B ERA ERRCA MVC ERRORMSG,MSGC B ERA ERRBA MVC ERRORMSG,MSGB B ERA ERRAA MVC ERRORMSG,MSGA B ERA ERA MVC RC,=H'12' B WRITERR EJECT - - - - - DATA MISSING - - - - - - - DS 0F DIRLIST DS 0CL74 DIRECTORY RECORD NAME DC CL8' ' Member name TTR DS CL3 Start TTR of member C DS CL1 Required Flag byte. X'80' is Alias. USERDATA DS CL62 SPACE