In the previous post I talked about getting our assembler monitor connected to DB2 for z/OS with the intention of getting some statistics traces running and gathering the data cut by DB2. This time we’re going to look at how we actually got the traces running.
As you’ll know from your extensive reading of the DB2 10 for z/OS manual Managing Performance (SC19-2978 – chapter 22, Programming for IFI), we need to setup a couple of things before we attempt to issue our start trace command. What may not be entirely clear is exactly how to provide them as the coding examples are a little vague.
Things You’ll Need To Start a Trace
Probably the most important thing to be clear on is what traces you want to start. We’re concentrating on Stats with our monitor code which are supplied directly from the READS call, but you may be a bit more ambitious. Let’s say you want to track Audit data in DB2 V10:
-START TRACE(AUDIT) CLASS(1,4,5,7) DEST(OPX)
The destination clause is important as it says that we want the output to be written to a buffer that we’re supplying. You should be aware that each DB2 subsystem only supports 8 of these, so it is extremely important that you tidy up after yourself when you’re finished (-STOP TRACE…). Note that the OPn buffer assigned to your code won’t be released until all traces writing to it are explicitly stopped. As DB2 writes to the supplied buffer as data becomes available losing the application that owns the buffer will cause the buffer to be cleared up and the traces to throw an error.
It’s also reasonably sensible to limit your application to using just one of these OPn destinations to ensure that other IFI users (e.g. replication and other monitoring solutions) aren’t excluded due to lack of resources. This means that if you want to monitor more than one trace type, you will need to issue your subsequent trace starts against the specific OPn assigned to your application, e.g.
-START TRACE(PERFM) CLASS(22) DEST(OP7)
For reference, the default destination (for the start trace command) varies depending on the trace type – for audit it’s SMF, but for performance traces it’s GTF. See the DB2 10 for z/OS Command Reference (SC19-2972) for details.
Having decided on the trace, we need to put the command in a data block that IFI can work with, like this:
+—-+—-+—————-+
| LL | 00 | Command |
+—-+—-+—————-+
<———–LL————->
E.g.
DS 0F
CMND DS 0CL50
LL DC H’49’ LENGTH OF COMMAND + HEADER
LLZZ DC H’0′ BINARY ZEROS
CMDSTR DC CL45′-START TRACE (AUDIT) CLASS(1,4,5,7) DEST(OPX)’
We’ve got the command sorted out, so next we need to supply the buffer. Two parameters have to be passed to establish this:
- The address of the buffer itself, and;
- The Buffer Information block (mapped by DSNDWBUF)
The buffer information block (WBUF) might be better referred to as the buffer control block. Its main purpose is to provide a threshold and notification route for data reaching the buffer. The programmer can specify an ECB to POST and a threshold number of bytes written to trigger this. This is the main means for DB2 to notify you that your buffer is being filled.
The last item required before we can start our trace is the Instrumentation Facility Component Area (IFCA). This is how DB2 returns state information to the caller, so includes return and reason codes as well as byte count for returned data and OPn destination identifier(s). It is mapped by DSNDIFCA and has to be properly initialised on first use – i.e. set to zeros, and then the following fields set:
- The length (IFCALEN)
- Scope flag (IFCAFLGS) set to global (IFCAGLBL) if required (default is local)
- Eyecatcher (IFCAID) set to ‘IFCA’
- OPn trace owner (IFCAOWNR) set – 4 characters
IFCAOWNR should be set when starting a trace as it sets the ownership identifier for the trace buffer. The owner of the buffer is the only process that can issue READA requests against it.
Issuing the Command Through IFI
The following call will issue the command:
CALL (15),(WLI2CMD,MYIFCA,(6),CMND,BUFFINF),VL,MF=(E,CBLK)
Where:
- R15 is the address of a stub to call DSNWLI2 (cf Assembler : Getting Connected to DB2 – https://db2dinosaur.blogspot.com/2013/05/assembler-getting-connected-to-db2.html) – code shown below
- WLI2CMD is an 8 character constant :
- WLI2CMD DC CL8 ‘COMMAND ‘
- MYIFCA is the IFCA that we initialised as in the previous section
- R6 is the pointer to our trace buffer. Note that the first full word should be set to it’s length.
- CMND is the command buffer (as shown in the previous section) which holds the start trace command.
- BUFFINF is the WBUF that we initialised as in the previous section.
DSNWLI Stub
The following is the stub code to drive the previously loaded DSNWLI2 CAF IFI EP:
DSNWLI DS 0H
USING DSNWLI,R15 ADDRESSABILITY
STM R14,R12,12(R13) SAVE CALLERS REGS
LA R8,WLI2SA OUR SAVE AREA
ST R13,4(R8) SAVE BACKWARD SA PTR
ST R8,8(R13) SAVE FORWARDS SA PTR
LR R13,R8 ESTABLISH NEW SA
LR R12,R15 SORT OUT ADDRESSABILITY
DROP R15
USING DSNWLI,R12
L R15,ADSNWLI2 GET DSNWLI2 EP
BALR R14,R15 AND CALL
L R13,WLI2SA+4 RESTORE CALLERS SA
L R14,12(R13) RESTORE CALLERS REGS
LM R0,R12,20(R13)
BR R14 RETURN RC=RC FROM DSNWLI2
DROP R12
Checking The Results
Okay, we made the call and it returned – did it work? As well as the return code returned in R15, it is also returned in the IFCA as IFCARC1, with the DB2 reason code returned in IFCARC2.
If these are both zero, then things are looking good. Any text returned by DB2 (you might have done a -DISPLAY TRACE first) will be indicated by a non-zero IFCABM (number of bytes in the return area – pointed to by R6 in our example). If your buffer wasn’t big enough for everything, then IFCABMN will be non-zero. This can be caused by the trace data being too big for a buffer that is too small, but it can also be an indicator that the monitor isn’t keeping up with the volume of data that DB2 is pushing.
If you need to work with READA, then you’ll need to note which OPn DB2 assigned you. This can be determined from the IFCAOPNL and IFCAOPNR array, which records up to 8 active OPn buffer assignments. Once you’ve picked a winner, put the value in IFCAOPN for subsequent READA calls.
If you find you’re struggling to get the command processing to work, it might be worth looking at IFCAR15 as well, which gives some additional diagnostics – which can be translated as :
0 = Okay
4 = Something weird happened
8 = Probably a syntax error on the supplied command
12 = See IFCAR0 for command handler return code
16 = See IFCAR0 for command handler return code
20 = DB2 couldn’t allocate storage to give you a text message back
24 = MSTR short on storage?
28 = Insufficient CSA available
32 = User not authorised to issue the command
Seeing Is Believing
Before:
-dis trace(*)
DSNW127I -DB2T CURRENT TRACE ACTIVITY IS –
TNO TYPE CLASS DEST QUAL
01 STAT 01,03,04,05, SMF NO
01 06
02 ACCTG 01 SMF NO
*********END OF DISPLAY TRACE SUMMARY DATA*********
DSN9022I -DB2T DSNWVCM1 ‘-DIS TRACE’ NORMAL COMPLETION
After:
-dis trace(*)
DSNW127I -DB2T CURRENT TRACE ACTIVITY IS –
TNO TYPE CLASS DEST QUAL
01 STAT 01,03,04,05, SMF NO
01 06
02 ACCTG 01 SMF NO
03 AUDIT 01,04,05,07 OP1 NO
*********END OF DISPLAY TRACE SUMMARY DATA*********
DSN9022I -DB2T DSNWVCM1 ‘-DIS TRACE’ NORMAL COMPLETION