IBM Books

System Monitor Guide and Reference


Reading an Event Monitor Trace

Version 6 event monitors return their data in a self-describing format. Figure 5 shows the structure of the data stream and Table 1 provides some examples of the logical data groups and data elements that could be returned.
Note:In the examples and tables descriptive names are used for the identifiers. These names are prefixed by SQLM_ELM_ in the actual data stream. For example, db_event would appear as SQLM_ELM_DB_EVENT in the event monitor output. Types are prefixed with SQLM_TYPE_ in the actual data stream. For example, headers appear as SQLM_TYPE_HEADER in the data stream.

Figure 5. Event Monitor Data Stream


sqlf0601


  1. The structure of the sqlm_event_log_data_stream_header is different than the other headers in the data stream. The version field determines if the output can be processed as a Version 6 data stream.

    This header has the same size and type as pre-Version 6 event monitor streams. This allows applications to determine if the event monitor output is self-describing or is in the old static format.
    Note:This data element is extracted by reading sizeof(sqlm_event_log_data_stream) bytes from the data stream.

  2. Each logical data group begins with a header that indicates its size and element name.

  3. The size element in the header indicates the size of all the data in that logical data group.

  4. Data element information follows its logical data group header and is also self-describing.

Table 1. Sample Event Data Stream
Logical Data Group Data Stream Description
event_log_ stream_header
sqlm_little_endian 
1000
sqlm_dbmon_version6

Byte order of the event monitor data returned.
Not used (for compatibility with previous releases).
The version of the database manager that returned 
the data. Only version 6 monitors can write data in 
the self-describing format. 

log_header_event
100
header
log_header_event

Size of the logical data group.
Indicates the start of a logical data group.
Name of the logical data group.

4
u32bit
byte_order
little_endian 

Size of the data stored in  
Data element type - 32 bit numeric.
The name of the data element collected.
The collected value for this element.

2
u16bit
codepage_id
850

Size of the data stored in  
Data element type - unsigned 16 bit numeric. 
The name of the data element collected.
The collected value for this element.

db_event
100
header
db_event

Size of the logical data group.
Indicates the start of a logical data group.
Name of the logical data group.

4
u32bit
lock_waits
2

Size of the data stored in  
Data element type - unsigned 32 bit numeric. 
The name of the data element collected.
The collected value for this element.

Reading the Log Stream Header

The event_log_stream_header identifies the version of the database manager that returned the data. Only Version 6 monitors write their data in the self-describing format.

If you are working with a Version 6 monitor, then you can start processing the self-describing data stream. When reading the trace, you can use the size element to skip a logical data group in the trace.

An event monitor, unlike a snapshot monitor (see Snapshot Output), does not have a size element that returns the total size of the trace. You typically read an event monitor trace until you reach an end of file.

Reading the Log Header

The log header describes the characteristics of the trace, containing information such as the memory model (for example little endian) of the server where the trace was collected, and the codepage of the database. You may have to do byte swapping on numerical values, if the system where you read the trace has a different memory model than the server (for example, Windows NT to UNIX). Codepage translation may also need to be done, if the database is configured in a different language than the machine from which you read the trace.

The following code can be used to read a single record from the event monitor trace.

 
//------------------------------------------------------------------------------
// Read an event record  - returns:  0 (success) or EOF
// NOTE: This works for all records except sqlm_event_log_stream_header
//------------------------------------------------------------------------------
int read_event_record(EventLog *evtlog, char *buffer)
{
   sqlm_header_info*  pHeader = (sqlm_header_info*) buffer;
 
   //---------------------------------------------------------------------------
   // Read the record header
   //---------------------------------------------------------------------------
   int rc;
   rc=read_data(evtlog, (char *) pHeader, sizeof(sqlm_header_info));
   if (rc)
      return rc;  /* could be at EOF */
 
   if (evtlog->needByteReversal)
      swapBytes_sqlm_event_rec_header(pHeader);
 
   //---------------------------------------------------------------------------
   // Read the rest of the data
   //---------------------------------------------------------------------------
   rc=read_data(evtlog, buffer        + sizeof(sqlm_header_info),
                        pHeader->size);
 
   if (rc==0 && evtlog->needByteReversal)
      swapBytes(pHeader->type, buffer);
 
   return rc;
} /* end of read_event_record */

Reading the Data Stream

The following routines illustrate how you can open, read, or skip bytes from a PIPE or FILE on a UNIX platform.

 
//------------------------------------------------------------------------------
// File functions  - Using the ANSI C library
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
//------------------------------------------------------------------------------
FILE* openFile(char *file_name) {
   return fopen(file_name,"rb"); /* returns NULL if file cannot be opened */
}
//------------------------------------------------------------------------------
int closeFile(FILE* handle) {
  return fclose(handle);
}
//------------------------------------------------------------------------------
int readFromFile(char* buffer, int size, FILE* fp) {
   int rc=0;                            // returns 0 (success); EOF; or errno
   int records_read = fread(buffer, size, 1, fp);
   if (records_read != 1) {
      if (feof(fp))
         rc = EOF;
      else rc = errno;
   } /* end if no data was returned */
   return rc;
} /* end readFromFile */
 
//------------------------------------------------------------------------------
// Pipe functions  -  for AIX
//------------------------------------------------------------------------------
#include <unistd.h>    /* for pipe functions on AIX */
#include <fcntl.h>     /* for definition of O_RDONLY and open() */
//------------------------------------------------------------------------------
int openNamedPipe (char   *pipe_name) {
   return open(pipe_name, O_RDONLY);
}
//------------------------------------------------------------------------------
int closeNamedPipe (int handle) {
  return close(handle);
}
//------------------------------------------------------------------------------
int readFromPipe(int handle, char* buffer, int size) {
   int rc=0;
   int num_bytes;
   num_bytes = read(handle, buffer, size);
   if (num_bytes != size) {
      if (num_bytes==0)
         rc=EOF;
      else rc = num_bytes;
   } /* end did not get the expected number of bytes back from read() */
   return rc;
} /* end readFromPipe */
 
//------------------------------------------------------------------------------
// Read data from Event Monitor trace (FILE or PIPE) returns 0 (success) or EOF
//------------------------------------------------------------------------------
int read_data(EventLog* evtlog,
              char*     buffer,
              int       size) {
   int rc=0;
   if (evtlog->type == EVMFile) {
      rc = readFromFile(buffer, size, evtlog->current_fp);
      if (rc && rc!=EOF) {
          fprintf(stderr, "ERROR: Could not read from: %s\n",
                       evtlog->current_fn);
          exit(1);
      } /* end cannot read the log header from the file */
   } /* end if the Event Monitor Log is read from a file */
   else {
      rc = readFromPipe(evtlog->handle, buffer, size);
      if (rc && rc!=EOF) {
         fprintf(stderr, "ERROR: Could not read a data from: %s\n",
                          evtlog->target);
         exit(2);
      } /* end cannot read from the pipe */
   } /* end else the Event Log is read from a pipe */
   return rc;
} /* end of read_data */
 
//------------------------------------------------------------------------------
// Skip n bytes from current position in the trace
//------------------------------------------------------------------------------
void skip_data(EventLog* evtlog, int n) {
   if (evtlog->type == EVMFile)
      fseek(evtlog->current_fp, n, SEEK_CUR);
   else if (evtlog->type == EVMPipe) {
      lseek(evtlog->handle, n, SEEK_CUR);
   } /* end else pipe event monitor */
} /* end skip_data *//

Swapping Bytes in Numerical Values

This code is required when transferring data between systems using different conventions for storing numerical values (for example, UNIX to Windows NT).

 
#include <sqlmon.h>   // DB2 Database Monitor interface
//------------------------------------------------------------------------------
// Byte conversion macros
//------------------------------------------------------------------------------
#define SWAP2(s) ((((s) >> 8) & 0xFF) | (((s) << 8) & 0xFF00))
 
#define SWAP4(l) ((((l) >> 24) & 0xFF) | ((((l) & 0xFF0000) >> 8) & 0xFF00) \
                      | (((l) & 0xFF00) << 8) | ((l) << 24))
 
//------------------------------------------------------------------------------
void swapBytes_sqlm_event_log_stream_header(sqlm_event_log_stream_header* r) {
   r->size =                       SWAP4(r->size);
   r->version =                    SWAP4(r->version);
} // end of swapBytes_sqlm_event_log_header)

Printing Event Records

All timestamps in event monitor records are returned in two unsigned 4 byte data elements (seconds and microsec). These represent the GMT time since January 1, 1970.

All strings in event monitor records are padded with blanks, up to their maximum size. Strings returned by DB2 are NOT NULL TERMINATED.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]

[ DB2 List of Books | Search the DB2 Books ]