システム・モニター 手引きおよび解説書


イベント・モニター・トレースを読み取る

バージョン 7 イベント・モニターは、データを自己記述型の形式で戻します。 図 5 では、データ・ストリームの構造を示し、 表 1 では、戻される論理データ・グループおよび データ要素のいくつかの例を示します。
注:これらの例や表では、識別子として記述名を使用しています。 これらの名前は、実際のデータ・ストリームでは SQLM_ELM_ という接頭部が付きます。 たとえば db_event は、 イベント・モニター出力では SQLM_ELM_DB_EVENT と表示されます。 タイプは、実際のデータ・ストリームでは SQLM_TYPE_ という接頭部が付きます。 たとえば、ヘッダーはデータ・ストリームで SQLM_TYPE_HEADER と表示されます。

図 5. イベント・モニター・データ・ストリーム


sqlf0601


  1. sqlm_event_log_data_stream_header の構造は、 データ・ストリーム内のほかのヘッダーとは異なります。 バージョン・フィールドにより、 出力をバージョン 7 のデータ・ストリームとして処理できるかどうかが決まります。

    このヘッダーのサイズとタイプは、 バージョン 7 以前のイベント・モニター・ストリームと同じです。 これにより、アプリケーションは、 イベント・モニター出力が自己記述型か古い静的形式かを判別できます。
    注:このデータ要素は、データ・ストリームから sizeof(sqlm_event_log_data_stream) のバイトを読み取ることにより抽出されます。

  2. 各論理データ・グループは、サイズと要素名を示すヘッダーで始まります。
  3. ヘッダーのサイズ要素は、 論理データ・グループのデータ全体のサイズを示します。
  4. データ要素情報が、論理データ・グループ・ヘッダーに続きます。 これも自己記述型です。

表 1. イベント・データ・ストリームのサンプル
論理データ・グループ データ・ストリーム 説明
event_log_ stream_header
sqlm_little_endian
1000
sqlm_dbmon_version7


戻されたイベント・モニター・データのバイトの並び順。
使用されません (以前のリリースとの互換性のため)。
データを戻したデータベース・マネージャーのバージョン。
自己記述型の形式でデータを記述できるのは、
バージョン 6 とバージョン 7 のモニターだけです。

log_header_event
100
header
log_header_event


論理データ・グループのサイズ。
論理データ・グループが始まることを示す。
論理データ・グループの名前。


4
u32bit
byte_order
little_endian


このデータ要素に入っているデータのサイズ。
データ要素タイプ - 32 ビット数値。
収集されたデータ要素の名前。
この要素に対して収集された値。


2
u16bit
codepage_id
850


このデータ要素に入っているデータのサイズ。
データ要素タイプ - 符号なし 16 ビット数値。
収集されたデータ要素の名前。
この要素に対して収集された値。

db_event
100
header
db_event


論理データ・グループのサイズ。
論理データ・グループが始まることを示す。
論理データ・グループの名前。


4
u32bit
lock_waits
2


このデータ要素に入っているデータのサイズ。
データ要素タイプ - 符号なし 32 ビット数値。
収集されたデータ要素の名前。
この要素に対して収集された値。

ログ・ストリーム・ヘッダーの読み取り

event_log_stream_header は、 データを戻したデータベース・マネージャーのバージョンを示します。 データを自己記述形式で書き込むのは、 バージョン 6 およびバージョン 7 のモニターだけです。

バージョン 6 およびバージョン 7 のモニターで作業している場合、 自己記述型データ・ストリームの処理を開始できます。 トレースを読み取っているとき、 size 要素を使用して、 トレース内の論理データ・グループを読み飛ばせます。

スナップショット・モニター (スナップショット出力を参照) と違って、 イベント・モニターにはトレースの合計サイズを戻す size 要素がありません。 通常は、 ファイルの終わりに達するまで、 イベント・モニター・トレースを読み取ることになります。

ログ・ヘッダーの読み取り

ログ・ヘッダーではトレースの特性を記述します。これには、 トレースが収集されたサーバーのメモリー・モデル (たとえばリトル・エンディアン)、 およびデータベースのコード・ページなどの情報が含まれています。 トレースを読み取るシステムのメモリー・モデルがサーバーとは異なる場合 (たとえば、Windows NT と UNIX)、 数値に関してバイトのスワッピングを行う必要があります。 データベースが、トレースを読み取るマシンとは異なる言語で構成されている場合、 コード・ページ変換を行う必要が生じることもあります。

以下のコードを使って、イベント・モニター・トレースから 1 つのレコードを読み取ることができます。

 
//------------------------------------------------------------------------------
// 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 */

データ・ストリームの読み取り

以下のルーチンは、UNIX プラットフォーム上で PIPE または FILE からバイトのオープン、読み取り、 またはスキップを行う方法を示しています。

 
//------------------------------------------------------------------------------
// 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 *//

数値のバイトのスワッピング

数値を保管するための規則が異なるシステム間でデータを転送する場合には (たとえば、UNIX から 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)

イベント・レコードの印刷

イベント・モニター・レコードのすべてのタイム・スタンプは、 2 つの符号なし 4 バイト・データ要素 (秒およびマイクロ秒) で戻されます。 これは 1970 年 1 月 1 日以降の GMT (グリニッジ標準時) で表されます。

イベント・モニターのストリングのサイズ要素は、 ストリング要素の実際のデータ・サイズを表します。 このサイズには、ヌル終止符は入っていません。 また、ストリングがヌルで終了することはありません。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]