バージョン 7 イベント・モニターは、データを自己記述型の形式で戻します。 図 5 では、データ・ストリームの構造を示し、 表 1 では、戻される論理データ・グループおよび データ要素のいくつかの例を示します。
注: | これらの例や表では、識別子として記述名を使用しています。 これらの名前は、実際のデータ・ストリームでは SQLM_ELM_ という接頭部が付きます。 たとえば db_event は、 イベント・モニター出力では SQLM_ELM_DB_EVENT と表示されます。 タイプは、実際のデータ・ストリームでは SQLM_TYPE_ という接頭部が付きます。 たとえば、ヘッダーはデータ・ストリームで SQLM_TYPE_HEADER と表示されます。 |
![]() |
このヘッダーのサイズとタイプは、 バージョン 7 以前のイベント・モニター・ストリームと同じです。 これにより、アプリケーションは、 イベント・モニター出力が自己記述型か古い静的形式かを判別できます。
注: | このデータ要素は、データ・ストリームから sizeof(sqlm_event_log_data_stream) のバイトを読み取ることにより抽出されます。 |
論理データ・グループ | データ・ストリーム | 説明 | ||
---|---|---|---|---|
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 (グリニッジ標準時) で表されます。
イベント・モニターのストリングのサイズ要素は、 ストリング要素の実際のデータ・サイズを表します。 このサイズには、ヌル終止符は入っていません。 また、ストリングがヌルで終了することはありません。