MVS TOOLS AND TRICKS OF THE TRADE December 1996 Sam Golob MVS Systems Programmer sbgolob@cbttape.org Sam Golob is a Senior Systems Programmer ON FINDING THINGS This month, I'd like to discuss some novel approaches to solving system programming problems, all of which have to do with finding things. Once you see some examples and you understand what we're doing, you'll be able to come up with your own extensions to these techniques, or you can use them as is. I can testify that many problems which seemed difficult to approach with other methods, have fallen rather quickly when they were looked at from this angle. There are several different categories of "finding" which will concern us. Each category is a different type. The overall watchword for all of them is "speed". Also, the reason I am mentioning these particular categories here, is that standard IBM MVS techniques leave large gaps in all of the areas we will talk about today. I'd bet that many sysprogs, hearing what we're doing, will say: "I really didn't know there was a way to do that!" Let's start our discussion with an overview of the different categories of "finding" that we will talk about. First, is the problem of finding all occurrences of a particular member name in a concatenated list of partitioned datasets. This category lies at the root of many common system problems. For example, suppose you have several versions of the same program name in various libraries of the linklist concatenation, and you've encountered an error in this program's execution. Are you executing the right version of the program? This situation has to be diagnosed correctly. Another example: Suppose you have a jobstream which executes cataloged procedures. Is the job executing the correct version of your PROC? Maybe there are multiple versions in different libraries, and the correct PROC wasn't in a library that's higher in the list than an incorrect PROC. In modern versions of JES, the name of the procedure library containing the PROC is reported. That's good once the job was run. But to diagnose the situation beforehand, or to obtain other proc libraries containing a PROC with this name, do you have a good technique? The next category involves finding all occurrences of a data string which occur in multiple pds members, or in an entire library. If this can be done quickly, there are myriads of system problems which can be diagnosed using such an approach. In former times, I would use this method to discover the causing component of IBM system problems. This is an example of the way it worked. Suppose I had a system problem that produced an unusual IBM message. I would search SYS1.LPALIB for all occurrences of the message string (or part of it). This would show me some module names, and the message string within the load module. Then I would look in the Logic Manual (remember those?) to see how the module worked, and I would look in IBMlink or call the Support Center to see if any APARs were reported for these modules. Of course, nowadays the message manual often reports which module produced each message, but even so, this information isn't always mentioned for some components. Our technique is still very handy nowadays as a backup source of information. A third category involves creating a list of all member names in a pds which contain a specific data string. This can be used in conjunction with "find-replace" maintenance. For example, suppose a dataset is renamed, and you want to find all JCL streams or PROCs which reference the dataset. Then you can edit each member containing the dataset name, and fix it properly. Another example: Suppose you are searching in your own large JCL library, or in someone else's JCL library, and you want to find an example of an IEBCOPY or an IEHINITT job. If you have an appropriate searching tool, you can come up with a list of members containing PGM=IEBCOPY or PGM=IEHINITT, or whatever string which would be indicative of the type of job you are looking for. All of these three "finding categories", if they can be implemented with speed, can greatly help any system programmer in many areas of our everyday work. In the rest of this column, I'll try and suggest possible tools, among free products or vendor products, which will help achieve these results. Many free tools can be obtained from the CBT MVS Utilities Tape, an independently produced huge software collection, which can be ordered through the NaSPA office. In this column, I often refer to tools in various files of the CBT Tape, because those materials can be obtained by any MVS shop, without requiring a big budget. FINDING MEMBERS IN A DATASET CONCATENATION The principal MVS service which detects the presence or absence of a member in a partitioned dataset is the BLDL service which is implemented in SVC 18 (module IGC018). BLDL can either be run against an individual dataset or a concatenation. There is one hitch. If a utility runs BLDL against a dataset concatenation, only the first occurrence of the member is reported. Other occurrences afterward can only be shown if the utility opens the datasets following as individual datasets. REXX also has an implicit BLDL service built into it, implemented by the SYSDSN keyword. My late colleague, Tony Forte, wrote some nice REXX execs which take advantage of this service. Tony's REXX execs may be found on the CBT MVS Utilities Tape, File 219. Tony's LNKLOOK exec searches all of the Link List libraries for occurrences of a load module name. One enters LNKLOOK followed by a module name, for example: LNKLOOK IEFACTRT. Tony's JESLOOK exec finds all occurrences of a PROC name in all the libraries of the JES2 proc PROC00 concatenation. For example, one enters: JESLOOK CAS9 to find all occurrences of the PROC CAS9 in all PROC00 proclib libraries. Sample results from these two REXX execs are shown in Figure 1. A brand new tool in this category has been introduced with ISPF Release 4.2. It is a TSO command whose name is ISRDDN. If you type the command TSO ISRDDN on an ISPF command line, a panel displaying all the dataset allocations in your TSO session will be shown. Line commands and primary commands may be entered on this panel. If you enter the primary command MEMBER followed by a member name, all datasets allocated to your TSO session which contain that member name will be marked. It is easy to see how you can use this tool. Simply run a CLIST that allocates a dataset concatenation you want to look at, and then, in ISRDDN, enter its MEMBER primary command using the name you want to search for. ISRDDN has many other functions also. It is worth your while to invest some time learning how to use it. A third type of tool that is in this category is a free TSO command called LOCATE, which works for load modules. One place where you can find source code for this type of program is on File 270 of the CBT Tape. LOCATE will show occurrences of any program name, if it exists on your system. The program version on File 270 will (by default) show the first occurrence of the program and (optionally) show all occurrences of the program. I have seen other versions of LOCATE which behave a bit differently, but they are all useful. One good use of LOCATE, since it shows TTR disk locations of the program name, is to verify if an LLA refresh of the program was done. LOCATE does a BLDL for the program name, and BLDL uses the LLA service. If no refresh for a new program version has been done, LOCATE will show LLA's TTR location for the program, while a purely disk-based browser, such as REVIEW (CBT Tape File 134) will show the new TTR location. If they differ, you know that the LLA refresh was not yet done. FINDING STRINGS IN PDS MEMBERS The "champion tool" that I've found in my work, which finds strings in partitioned dataset members (source or load), is the PDS TSO command that can be found on File 182 of the CBT MVS Tape. There is a stabilized free version of "PDS", Version 8.4, on the CBT tape, which is available to all. The currently supported version of PDS is a vendor product called STARTOOL (formerly PDSTOOLS) that is distributed by Serena International of Burlingame, California. I do not like to write about vendor products in this column. But I am mentioning both products here, because for this purpose, although the vendor product is much better and has PDSE support, the free version is good enough. "Free PDS" will be very helpful to shops that don't have STARTOOL. The PDS command can be used in either of two modes: line mode or ISPF mode. Internally to the product, the ISPF mode is referred to as ISPMODE. ISPMODE operation of PDS is generally the better way to go, but most of our techniques will operate in either mode. Line mode operation of PDS will also work under TSO-in-batch. The PDS command must point to a dataset. We will give an example. Suppose we want to find all occurrences of a message string in SYS1.LPALIB. If PDS is installed, we issue the command: PDS 'SYS1.LPALIB'. Once we enter PDS, either in line mode or ISPMODE, we enter a subcommand, FIND. Our purpose is to find all occurrences of a message string in all members of SYS1.LPALIB, or in a subgroup of members. PDS keeps track of subgroups of members in many ways, but once a subgroup is established, the user can reference the current member subgroup with an asterisk, '*'. If the user wants to reference all members of a pds, a colon ':' is used. To accomplish our immediate purpose of finding all occurrences of a data string in SYS1.LPALIB, we enter the subcommand: FIND : /string/ The result of this command is a quick summary of all occurrences of the data string in the entire SYS1.LPALIB. This will accomplish the aim of the second category of "finding" which we mentioned above. However, the usefulness of the PDS command does not stop there. We can easily accomplish the aim of the third category of "finding", too. The FIND subcommand of PDS has THEN and ELSE logic attached to it. You can create a member subgroup which consists of all members in which the data string has been found. This can be done in several ways, but the most general is to enter the subcommand under PDS: FIND : /string/ THEN(SUBLIST) The result of this command is that a member subgroup is created, which consists of a list of only those member names which contain the specified data string. As we mentioned before, this subgroup of members can be referred to, in subsequent PDS subcommands, by using an asterisk '*' instead of the colon ':'. Let's finish by showing how PDS can easily accomplish the third type of "finding". Suppose we have changed a dataset name, mentioned frequently in SYS1.PROCLIB, from SYS1.USER.LOADLIB to SYS1.USERLIB. To fix all JCL in SYS1.PROCLIB, simply point PDS to SYS1.PROCLIB using the initial command: PDS 'SYS1.PROCLIB', or if PDS is already running and is pointing to a different dataset, enter the subcommand: CHANGE 'SYS1.PROCLIB'. To establish a member group containing the string, SYS1.USER.LOADLIB, enter the subcommand: FIND : /SYS1.USER.LOADLIB/ THEN(SUBLIST) Then, we can do either of two things. In ISPMODE, we can create a member sublist consisting of only members containing the string SYS1.USER.LOADLIB. This will enable us to conveniently edit only those members, using the ISPF editor. The PDS ISPMODE command which does this is: MEMLIST * RESET . PDS also has an additional "string replacement" feature which does an in-place rewrite of the records. The string replacement is invoked using the PDS "REPLACE" subcommand. One invokes the command: REPLACE * /SYS1.USER.LOADLIB/SYS1.USERLIB/ to do a dry run and display the results of the string replacement. This may be done with PDS running in line mode or TSO-in-batch. To make the changes final, enter: REPLACE * /SYS1.USER.LOADLIB/SYS1.USERLIB/ WRITE That's all there is to it, folks. Mission accomplished. If you try the PDS command for yourself, you'll also see that it works very fast. I trust that the techniques we've mentioned this month will be helpful to you. In the past, I've been able to make short work of some humongous tasks, using them. At the very least, they are time-saving and very convenient. Good luck and "happy finding". * * * * * * * * * * * * * * * * * * * * * * * Figure 1. Outputs of Tony Forte's LNKLOOK and JESLOOK REXX EXECs. This is an abbreviated sample output to the command: LNKLOOK IEFACTRT (for example) LINKLIST SEARCH ROUTINE ----------------------- SYS1.LINKLIB OK SYS1.MIGLIB MEMBER NOT FOUND SYS1.CSSLIB MEMBER NOT FOUND SYS1.USER.LINKLIB OK SYS1.ANO.USERLNK MEMBER NOT FOUND ISP.ISPLOAD MEMBER NOT FOUND ISR.ISRLOAD MEMBER NOT FOUND - - - - - - DATA ABBREVIATED FOR BREVITY - - - - - - This is an abbreviated sample output to the command: JESLOOK CAS9 JES2 SEARCH ROUTINE ----------------------- SYS1.PROCLIB MVSCAT OK SYS1.USER.PROCLIB MVSUSR MEMBER NOT FOUND SYS2.CICS.PROCLIB MVSSYS MEMBER NOT FOUND SYS1.ONLINES.PROCLIB MVSSYS MEMBER NOT FOUND CAI.CAIPROC MVSUTL OK CANDLE.PROCLIB MVSUTL MEMBER NOT FOUND - - - - - - DATA ABBREVIATED FOR BREVITY - - - - - -