MVS TOOLS AND TRICKS OF THE TRADE JUNE 2007 Sam Golob MVS Systems Programmer P.O. Box 906 Tallman, New York 10982 Sam Golob is a Senior Systems Programmer. He also participates in library tours and book signings with his wife, author Courtney Taylor. Sam can be contacted at sbgolob@cbttape.org. Information about the CBT MVS Tapes can be found on the web, at http://www.cbttape.org. THE STRUCTURE OF THE BROADCAST DATASET - PART 1 TSO has been around, on OS/360 (circa late-1960s) and on later MVT and MVS systems, for many years. Being the "terminal access" mechanism for the Operating System, and being "User and Userid oriented", TSO (in MVS) has always had a messaging system, so that one user could send messages to another user. An essential part of this messaging system is a dataset which holds the messages, if they can't be sent to the recipient user right away. This happens if (for example) that user is not currently logged on. This dataset, which used to be called SYS1.BRODCAST exclusively, is an essential part of all MVS systems, and therefore, it pays for us to know something about it. TSO itself provides two commands for sending and receiving messages. The TSO SEND command is used to send a message from one user to another user, or to a system console. As far as receiving messages goes, if the user is currently logged on, as soon as a terminal interrupt occurs, any outstanding messages will appear on the TSO terminal. But if the issuer of the SEND command used the SAVE option, then the sent message is saved in the SYS1.BRODCAST dataset and is not forwarded to the recipient user now. Any messages that were stored in the SYS1.BRODCAST dataset (more properly nowadays to be called the "Broadcast Dataset") are displayed, and deleted, by the TSO LISTBC command, which can be issued at any time by the user, or it is automatically issued on behalf of every user at LOGON time. That's why, when you LOGON to TSO, you always see your messages. It is the LISTBC command which displays (and deletes) them for you. How does LISTBC (which is a general system command) "know" which user has issued it, so it can display (and delete) the appropriate messages which are being saved for that user? The answer is that LISTBC interrogates a field in a control block, the PSCBUSER field in the PSCB control block, and whichever userid name appears there, that's the one which LISTBC will use, to go out to the Broadcast Dataset (or the TSO Userlog if it exists) and retrieve its messages. Usually the Userid name in the PSCBUSER control block belongs to the real TSO Userid, but if you "play games" and put another id in there, LISTBC won't know the difference. Of course, you need to create an APF authorized program to do that, and I don't recommend potentially violating the system integrity. But I can testify that this is what happens, that I've actually written such a program, and that it is publicly available if you really want to see it. So much said, by way of introduction. Now we can get to the nitty gritty of the internal structure of the Broadcast Dataset, where the messages are stored. PARTS OF THE BROADCAST DATASET The Broadcast Dataset is a Direct Access (DSORG=DA) dataset, and any of its "parts" can be anywhere in the dataset, except for the first record, or the "Header Record", which must be at the beginning. The Header Record tells you where all the other parts of the Broadcast Dataset are. More specifically, the Broadcast Dataset is "keyed", with a 1-byte key at the beginning of each record. And it is fixed, unblocked. That is, RECFM=F, KEYLEN=1. The record length, besides the key, is 129 bytes. Therefore, for each record in the Broadcast Dataset, there are 130 bytes. One byte is for the key, and 129 bytes are for the data. Therefore, LRECL=129. Keyed datasets are difficult to Browse, using ISPF. Since there are 130 bytes of information in each record, but the LRECL is only 129, ISPF Browse only looks at the first 129 bytes of data in each record, and drops the last character, which unfortunately contains very useful information. To correctly look at a Broadcast Dataset, and to see all of its data, use MVS Ditto, or (more conveniently) the free REVIEW TSO command, which can be found in the free CBT Tape collection of MVS Utilities, on File 134 (source) and File 135 (load modules). REVIEW will nicely display, in EBCDIC or in Hex, each record of the Broadcast Dataset accurately, and REVIEW is the tool I always use. (The CBT Tape collection is on the Internet. It is free, and you don't need a password to look at, or download, anything. To get its URL, just do a www.google.com search on "CBT Tape" and the correct URL should come out at, or near the top of the search.) Each "type of record" in the Broadcast Dataset is defined by the value in the "key" field. There are seven different types of record in the Broadcast Dataset, and therefore there are seven different key values. See Figure 1 for a table of the key values in the Broadcast Dataset, and the type of record that each key is used to define. The appropriate system macro which describes each type of Broadcast Dataset record, is listed there too. These macros are now in SYS1.MACLIB, but they used to be available only on the "Optional Materials" tapes for MVS. Being now in SYS1.MACLIB, they are much easier to find and use. Basically, three types of things are stored in the Broadcast Dataset, and these are covered by most of the record types. They are, first: Global Notices, which LISTBC displays to all TSO users when they issue a LISTBC command or when they LOGON. Global Notices are handled by two record types: X'00' which are Global Notices Directory Records, and X'02', which are the Global Notice messages themselves. Userids, which are defined for each user name who is allowed to store User Messages in the Broadcast Dataset, are stored in the type X'01' Userid Records. Each X'01' Userid Record can store up to nine Userids. These are the second type of thing stored in the Broadcast Dataset. The third thing is the User Messages which are the individual messages intended for each user. Each User's Messages are chained off its Userid Record, and if there is more than one message for a user, all those messages are chained to each other. Record types which handle User Messages are: X'03' for a User Message Record, and X'FF' for a Free Record which is eligible to be occupied by a new User Message. These three types of stored things cover five record types. The other two record types are type X'04' which is the Broadcast Dataset Header Record, and the type X'05' which is called the Free Search Record. The Free Search Record, which was added later for efficiency, usually points to the Relative Block Location (the three-byte RBA) of the first Free Message Record in the Broadcast Dataset. That covers all the record types in the Broadcast Dataset. If you know about them, then you know most of what you have to know. ENQUEUES ON THE BROADCAST DATASET It's obvious that if one user is busily in the process of issuing a SEND command to save a message in the Broadcast Dataset, you don't want another user to be doing something similar at the same time. Or you don't want to SEND a message to a user at the exact same time that the user is issuing a LISTBC command to display and delete his (or her) messages. To prevent interference between what more than one user (plus the system itself) are doing at the same time, the wise TSO developers have installed ENQUEUE protection. ENQUEUE protection works with 4 values. If an address space is the "holder" of the enqueue, and has registered the 4 values with the system, then any other address space attempting to obtain the same 4-values in its own enqueue, will be stopped, until the first address space lets the enqueue go, by issuing a DEQUEUE on this enqueue. There's a little more to it. There are "exclusive" enqueues and "shared" enqueues. Exclusive enqueues work as described above; they stop another address space which is attempting to acquire the same enqueue, whether it be exclusive or shared. But there can be many holders of the same SHARED enqueue. What a SHARED enqueue does, is to stop a new address space from obtaining the same 4-valued enqueue as an EXCLUSIVE enqueue. In other words, if a SHARED enqueue is in effect, and is held by one or more address spaces, then no other address space can obtain an EXCLUSIVE enqueue on the same resource until all the SHARED enqueues have been let go. What are the 4 values which constitute an enqueue? The first two are called the Q-name and the R-name, and they are two quite arbitrary values. IBM convention for enqueue assignment of Q-names is usually, that one component or resource-type will use the same Q-name always, or it will use just a minimally few different ones. For example, dataset protection uses a Q-name of SYSDSN, and an R-name of the actual dataset name. The third value is whether the enqueue is EXCLUSIVE or SHARED. And finally, the fourth value is the SCOPE, which tells you how widely this enqueue is to be distributed. The possible values of the SCOPE are "STEP", "SYSTEM", or "SYSTEMS". If two enqueues have identical Q-name, R-name, and exclusivity, but they have a different SCOPE, they are regarded as different enqueues, and the presence of one, will not stop the address space which holds the other. So now you've seen the four parts of an enqueue. In an Assembler program, enqueues are issued by the ENQ macro (found in SYS1.MACLIB) and they are destroyed by the DEQ macro (also found there). IBM convention for Broadcast Dataset enqueues is to use a Q-name of SYSIKJBC, and the R-name is the hex value of the 3-byte Relative Record Address (the RBA) of the particular Broadcast Dataset record which is being enqueued upon. For example, an enqueue on the Broadcast Header Record, which always has an RBA of X'000000', will have a Q-name of SYSIKJBC, an R-name of X'000000' and a scope of "SYSTEM". The reason why IBM uses a scope of SYSTEM, is that there is usually a separate Broadcast Dataset defined for each LPAR or MVS instance. So logically, and actually, the scope of the Broadcast Dataset should not go beyond the particular MVS instance which it is running on. So how is the enqueue on a Broadcast Dataset used? When LISTBC is trying to display and delete all messages belonging to a particular user, it enqueues on the Broadcast Header record, and on the particular Userid record (that is, the R-name on the ENQ is the RBA of the Userid Record) containing that Userid. It makes sense that as a particular User Message record is being deleted, there should be a quick ENQ and DEQ on that record, so it should not be modified by somebody else. And also, the Free Search Record is quickly enqueued and dequeued upon, as it is being modified after the User message deletions have been performed. Anybody who writes his (or her) own Broadcast Dataset management package (I have written two of them), must take these enqueues into account, whenever a program in his package is modifying an active Broadcast Dataset. Since anybody at any time, might be issuing a SEND or a LISTBC command against the active Broadcast Dataset too, your package has to temporarily stop them, by issuing the same enqueues as they do, whenever it modifies the active Broadcast Dataset. WHICH IS THE ACTIVE BROADCAST DATASET? Ever since TSO/E Release 3 came out (with z/OS 1.3), it is possible for a Broadcast Dataset to have a name other than SYS1.BRODCAST which is cataloged in the Master Catalog. Now, you can have a functioning active Broadcast Dataset, with any name, and which does not have to be cataloged. The name, and volume, of the active Broadcast Dataset is determined by the active IKJTSOxx member in PARMLIB. (See the z/OS MVS Initialization and Tuning Reference manual for coding details in the IKJTSOxx member of PARMLIB.) At IPL time, the system looks in the IEASYSnn member of PARMLIB first, to determine which initial IKJTSOxx member to use. And this will activate the INITIAL copy of the Broadcast Dataset. (If a different name isn't coded, the default is still SYS1.BRODCAST as cataloged in the Master Catalog.) But after the IPL, the Broadcast Dataset can be switched at any time, by using either the PARMLIB UPDATE(xx) TSO command, or the console SET IKJTSO=xx operator command. The effect of either of the latter two commands is to change which IKJTSOxx member in PARMLIB is currently the active one. How do you (yourself, as the sysprog) determine which is the active copy of the Broadcast Dataset that the system is currently using? The active Broadcast Dataset may be found by running a set of control block pointers, starting from the CVT, the TSVT (TSO Vector Table), the TPVT (TSO Private Vector Table) and the EESCB. I have written a TSO command which does this, and which displays all the relevant results using the TSO PUTLINE interface, on the TSO tube. This public domain command is called "EESCB", and it may be obtained from the CBT Tape collection on File 731. So instead of running the control block chain yourself, you can install this EESCB command, and get all the appropriate information for yourself very easily. ENOUGH FOR NOW I'm running out of space this month, so I'll continue, hopefully, next time. We've explained a lot of the overall facts about the Broadcast Dataset this month, and next time, I hope to get into more of the specifics about how User Messages are written and deleted, how Userids are written and deleted, and about how Global Notices are written and deleted. So I'm hoping to see you again soon, and I wish all of you the best of everything! * * * * * * * * * * * * * * * * * * * * * * * Figure 1. Types of Broadcast Dataset Records, as defined by their key. Key Value Type of Record Defined Macro --- ----- ---- -- ------ ------- ----- X'04' Broadcast Header Record IKJZT301 X'00' Global Notify Directory Record IKJZT302 X'02' Global Notice Record IKJZT303 X'05' Free Search Record IKJZT306 X'01' Userid Record IKJZT304 X'03' User Message Record (occupied) IKJZT305 X'FF' Free Message Record No Macro The X'FF' record has to have its relative position (on the track), in other words, the "R" of its CCHHR or TTR, as its first data byte, otherwise the Broadcast Dataset is considered "corrupted" by the system, and it will not function. This is why IBM says that you can't copy a Broadcast Dataset from one device type to another. The X'FF' records will come out on the wrong places in the track, if you do a dataset copy of the Broadcast Dataset using IBM tools.