/****************************************************************************
** (c) Copyright IBM Corp. 2007 All rights reserved.
**
** The following sample of source code ("Sample") is owned by International
** Business Machines Corporation or one of its subsidiaries ("IBM") and is
** copyrighted and licensed, not sold. You may use, copy, modify, and
** distribute the Sample in any form without payment to IBM, for the purpose of
** assisting you in the development of your applications.
**
** The Sample code is provided to you on an "AS IS" basis, without warranty of
** any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR
** IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do
** not allow for the exclusion or limitation of implied warranties, so the above
** limitations or exclusions may not apply to you. IBM shall not be liable for
** any damages you suffer as a result of using, copying, modifying or
** distributing the Sample, even if IBM has been advised of the possibility of
** such damages.
*****************************************************************************
**
** SOURCE FILE NAME: evm.sqC
**
** SAMPLE: How to create and parse file, pipe, and table event monitors.
**
** SQL STATEMENTS USED:
** CONNECT
** COMMIT
** DROP TABLE
** CREATE EVENT MONITOR
** SET EVENT MONITOR STATE
** DROP EVENT MONITOR
** PREPARE
** DECLARE
** OPEN
** FETCH
** CLOSE
**
**
*****************************************************************************
**
** For more information on the sample programs, see the README file.
**
** For information on developing embedded SQL applications see the Developing Embedded SQL Applications book.
**
** For information on using SQL statements, see the SQL Reference.
**
** For information on Event Monitors, see the System Monitor Guide and
** Reference.
**
** For the latest information on programming, building, and running DB2
** applications, visit the DB2 application development website:
** http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp
****************************************************************************/
#include <sqlmon.h>
#include "utilemb.h"
// Depending on the platform and compiler being used, either use the new
// <iostream> includes or the old <iostream.h> includes.
#if ((__cplusplus >= 199711L) && !defined DB2HP && !defined DB2AIX) || \
(DB2LINUX && (__LP64__ || (__GNUC__ >= 3)))
#include <iostream>
#include <iomanip>
#include <fstream>
using std::ios;
using std::ifstream;
#else
#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
#endif
#ifdef DB2NT // Windows
#include "utilsnap.cxx" // Contains the Snapshot class to parse the event
// monitor stream
#else // UNIX
#include "utilsnap.C"
#include <unistd.h> // Contains unlink function (to delete files)
#endif
// Boolean data type
#ifndef Boolean
typedef int Boolean;
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
#endif
// The following define allows us to change the endian notation of the event
// monitor files read by this sample (ie. to reverse the byte order of the
// header data that is parsed).
#if defined(__PPC__) || defined(__s390__) || defined(__s390x__)
#undef LITTLE_ENDIAN
#elif defined(WIN32)
#define LITTLE_ENDIAN
#endif
#define MAX_EVENT_DATA_SIZE 35072
#define MAX_FILE_LOCATION_SIZE 255
// Byte swap 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))
#define SWAP8(where) \
{ \
sqluint32 temp; \
temp = SWAP4(*(sqluint32 *)(where)); \
*(sqluint32 *)(where) = SWAP4(*(((sqluint32 *) (where)) + 1)); \
*(((sqluint32 *) (where)) + 1) = temp; \
}
// Event monitor file extension
#ifdef WIN32
#define EVENT_FILE_EXT ".EVT"
#else
#define EVENT_FILE_EXT ".evt"
#endif
char *usage =
"evm: Event Monitor code sample - Print an Event Monitor stream. \n"
" \n"
"Usage: \n"
" \n"
" evm [file] | [file <streamLocation>] | [pipe] | [table] \n"
" \n"
"Where: \n"
" \n"
" The first argument specifies whether the example stream \n"
" is a file, pipe, or table stream. \n"
" \n"
" NOTE: Pipe streams are supported by this sample application \n"
" only on AIX. \n"
" \n"
" The second argument (if file is specified as the first \n"
" argument) is the path containing existing event monitor \n"
" output files. \n"
" \n";
typedef enum streamType {filestream, pipestream, tablestream} streamType;
class EventMonitor
{
public:
int HeaderByteReverse(sqlm_header_info *pHeader);
int DataByteReverse(char *dataBuf, sqluint32 dataSize);
int EvmArgsRead(int argc, char *argv[]);
int GetNextFileName(char *location);
int FileDriver();
#ifdef DB2AIX
int PipeDriver();
#endif
int TableDriver();
int ReadFile();
char fileName[MAX_FILE_LOCATION_SIZE]; // The location and the name of
// the file (full path)
char *diagpath; // Path to where event monitor files will be written
streamType type; // The type of event monitor stream to demonstrate:
// file, pipe, or table
private:
Boolean needByteReversal; // True if running on a machine with a
// different memory model than the file format
char dataBuf[MAX_EVENT_DATA_SIZE]; // Data buffer that contains
// individual events read one by one
// from the event monitor files
sqlm_event_log_stream_header
eventLogStreamHeader; // Struct to hold event monitor log header
sqlm_header_info headerInfo; // Struct to hold event monitor header
// information
};
int main(int argc, char *argv[])
{
int rc = 0;
struct sqlca sqlca;
char nodeName[SQL_INSTNAME_SZ + 1];
char dbAlias[SQL_ALIAS_SZ + 1];
char user[USERID_SZ + 1];
char pswd[PSWD_SZ + 1];
EventMonitor evm; // An instance of the event monitor class
#ifdef DB2NT
char *db2path; // path where DB2 is installed
char *db2instance; // DB2 instance directory
#else
char *home; // instance owners home directory
#endif
// The following variables are for querying the dbm cfg for diagpath
db2CfgParam cfgParameters[1];
db2Cfg cfgStruct;
// Initialize cfgParameters
cfgParameters[0].flags = 0;
cfgParameters[0].token = SQLF_KTN_DIAGPATH;
cfgParameters[0].ptrvalue =
(char *)malloc(sizeof(char) * (SQL_FFDCPATH_SZ + 1));
// Initialize cfgStruct
cfgStruct.numItems = 1;
cfgStruct.paramArray = cfgParameters;
cfgStruct.flags = db2CfgDatabaseManager;
cfgStruct.dbname = dbAlias;
// Try getting the diagpath from db2CfgGet
db2CfgGet(db2Version970, (void *)&cfgStruct, &sqlca);
DB2_API_CHECK("DBM Config. Defaults -- Get");
evm.diagpath = cfgStruct.paramArray[0].ptrvalue;
// If diagpath wasn't obtainable from db2CfgGet, set diagpath to the
// default value (operating system dependent)
if(evm.diagpath[0] == '\0')
{
#ifdef DB2NT
db2path = getenv("DB2PATH");
db2instance = getenv("DB2INSTANCE");
if(db2path == NULL || db2instance == NULL)
{
cout << endl << "Error getting the diagpath, exiting.";
return 1;
}
sprintf(evm.diagpath, "%s\\%s\\", db2path, db2instance);
#else
home = getenv("HOME");
if(home == NULL)
{
cout << endl << "Error getting the diagpath, exiting.";
return 1;
}
sprintf(evm.diagpath, "%s/sqllib/db2dump/", home);
#endif
}
// Parse the command line arguments
rc = evm.EvmArgsRead(argc, argv);
if(rc != 0)
return rc;
// Decide what type of event monitor stream to demonstrate based on the
// supplied command line arguments, or parse a supplied filename
switch(evm.type)
{
case filestream:
if(argc == 3)
{
cout << "File supplied" << endl << endl;
evm.ReadFile();
}
else
{
cout << endl << "File driver" << endl << endl;
evm.FileDriver();
}
break;
#ifdef DB2AIX
case pipestream:
cout << endl << "Pipe driver" << endl << endl;
evm.PipeDriver();
break;
#endif
case tablestream:
cout << endl << "Table driver" << endl << endl;
evm.TableDriver();
break;
}
return rc;
} // main
int EventMonitor::EvmArgsRead(int argc, char *argv[])
{
int rc = 0;
switch(argc)
{
case 2:
if(strcmp(argv[1], "file") == 0 || strcmp(argv[1], "FILE") == 0)
{
// set file driver to be the active driver
type = filestream;
}
else if(strcmp(argv[1], "table") == 0 || strcmp(argv[1], "TABLE") == 0)
{
// set table driver to be the active driver
type = tablestream;
}
#ifdef DB2AIX
else if(strcmp(argv[1], "pipe") == 0 || strcmp(argv[1], "PIPE") == 0)
{
// set pipe driver to be the active driver
type = pipestream;
}
#endif
else
{
cerr << "First argument is invalid.";
cerr << endl << endl << usage;
rc = 1;
}
break;
case 3:
if(strcmp(argv[1], "file") == 0 || strcmp(argv[1], "FILE") == 0)
{
type = filestream;
strncpy(fileName, argv[2], sizeof(char)*MAX_FILE_LOCATION_SIZE);
// need to make sure there is enough room for \xxxxxxxx.evt, (13
// chars)
fileName[sizeof(char)*MAX_FILE_LOCATION_SIZE-13] = '\0';
}
else // something invalid for first argument
{
cerr << "First argument is invalid.";
cerr << endl << endl << usage;
rc = 1;
}
break;
default: // less than 2 or more than 3 arguments supplied.
cerr << "Incorrect number of arguments supplied.";
cerr << endl << endl << usage;
rc = 1;
break;
}
return rc;
} // EventMonitor::EvmArgsRead
int EventMonitor::FileDriver()
{
int rc;
struct sqlca sqlca;
char stmt[512];
char buf[512];
EXEC SQL CONNECT TO SAMPLE;
EMB_SQL_CHECK("connect");
sprintf(stmt,
"CREATE EVENT MONITOR dlmon FOR STATEMENTS WRITE TO FILE '%s' MAXFILESIZE 32",
diagpath);
EXEC SQL PREPARE Stmt FROM :stmt;
EMB_SQL_CHECK("prepare");
EXEC SQL EXECUTE Stmt;
EMB_SQL_CHECK("create dlmon");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
EXEC SQL SET EVENT MONITOR dlmon STATE 1;
EMB_SQL_CHECK("set dlmon state 1");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
cout << "Generating events:" << endl;
cout << "0 100" << endl;
cout << "|--------------------------------------------------|"
<< endl << " ";
for(int i = 0; i < 50; i++)
{
EXEC SQL COMMIT; // dummy statement to generate events
EMB_SQL_CHECK("commit");
cout << "*" << flush;
}
cout << endl;
EXEC SQL SET EVENT MONITOR dlmon STATE 0;
EMB_SQL_CHECK("set dlmon state 0");
EXEC SQL DROP EVENT MONITOR dlmon;
EMB_SQL_CHECK("drop dlmon");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
strcpy(fileName, diagpath);
rc = ReadFile();
if(rc != 0)
return rc;
// removes files created by the event monitor
sprintf(buf, "%s00000000%s", diagpath, EVENT_FILE_EXT);
unlink(buf);
sprintf(buf, "%s00000001%s", diagpath, EVENT_FILE_EXT);
unlink(buf);
sprintf(buf, "%s00000002%s", diagpath, EVENT_FILE_EXT);
unlink(buf);
return rc;
} // EventMonitor::FileDriver
#ifdef DB2AIX
int EventMonitor::PipeDriver()
{
int rc = 0;
struct sqlca sqlca;
int pid; // process id
char stmt[512];
char buf[512];
Snapshot ss;
// Create the pipe
sprintf(buf, "%spipe", diagpath);
mkfifo(buf, S_IWUSR | S_IRUSR);
pid = fork();
if(pid == 0) // parent will generate events
{
EXEC SQL CONNECT TO SAMPLE;
EMB_SQL_CHECK("connect");
sprintf(stmt,
"CREATE EVENT MONITOR dlmon FOR STATEMENTS WRITE TO PIPE '%s'",
buf);
EXEC SQL PREPARE Stmt FROM :stmt;
EMB_SQL_CHECK("prepare");
EXEC SQL EXECUTE Stmt;
EMB_SQL_CHECK("create dlmon");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
EXEC SQL SET EVENT MONITOR dlmon STATE 1;
EMB_SQL_CHECK("set dlmon state 1");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
for(int i = 0; i < 50; i++)
{
EXEC SQL COMMIT; // dummy statement to generate events
EMB_SQL_CHECK("commit");
}
// the asterisk symbol, "*" means that no more events will be generated
// for the purpose of this sample
ofstream outFile(buf, ios::binary);
outFile.write("*", 1);
outFile.close();
// wait for child to exit before cleaning up event monitor
waitpid(pid, NULL, WNOHANG);
EXEC SQL DROP EVENT MONITOR dlmon;
EMB_SQL_CHECK("drop dlmon");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
// removes the pipe that was made using mkfifo
unlink(buf);
return rc;
} // end parent
else // child will parse and print events
{
EXEC SQL CONNECT TO SAMPLE;
EMB_SQL_CHECK("connect");
ifstream inFile(buf, ios::binary);
if(inFile.fail())
{
cerr << "Error: Unable to read pipe at the specified location."
<< endl;
return 1;
}
inFile.read((char *) (&eventLogStreamHeader),
sizeof(eventLogStreamHeader));
while(inFile)
{
if(inFile.peek() == '*') // check if no more events will be generated
{
break;
}
else
{
inFile.read((char *) (&headerInfo), sizeof(headerInfo));
}
if(!inFile.eof())
{
if(headerInfo.size > MAX_EVENT_DATA_SIZE)
{
cerr << endl
<< "Error: incompatible or corrupted event stream." << endl
<< "Next event data has size: " << headerInfo.size
<< "!" << "(max is: " << MAX_EVENT_DATA_SIZE << ")" << endl;
return 1;
}
inFile.read((char *) (&dataBuf), headerInfo.size);
ss.ParseMonitorStream(" ",
dataBuf,
dataBuf+headerInfo.size);
}
}
inFile.close();
return rc;
} // end child
} // EventMonitor::PipeDriver
#endif
int EventMonitor::TableDriver()
{
int rc = 0;
struct sqlca sqlca;
char c1[] =
"(SELECT agent_id, appl_id, territory_code FROM CONNHEADER_dlmon)";
char c2[] =
"(SELECT event_monitor_name, message, message_time FROM CONTROL_dlmon)";
EXEC SQL BEGIN DECLARE SECTION;
// CONNHEADER_dlmon
sqlint32 agent_id;
char appl_id[32+1];
sqlint32 territory_code;
// CONTROL_dlmon
char event_monitor_name[128+1];
char message[128+1];
char message_time[26+1];
EXEC SQL END DECLARE SECTION;
EXEC SQL CONNECT TO SAMPLE;
EMB_SQL_CHECK("connect");
EXEC SQL CREATE EVENT MONITOR dlmon
FOR STATEMENTS, DEADLOCKS WITH DETAILS, CONNECTIONS
WRITE TO TABLE
CONNHEADER (TABLE CONNHEADER_dlmon,
INCLUDES (AGENT_ID,
APPL_ID,
APPL_NAME,
TERRITORY_CODE)),
DEADLOCK (TABLE DEADLOCK_dlmon),
DLCONN (TABLE CONNECTIONS_dlmon,
EXCLUDES (LOCK_OBJECT_NAME,
LOCK_OBJECT_TYPE,
TABLESPACE_NAME)),
STMT (TABLE STMT_dlmon,
INCLUDES (AGENT_ID,
APPL_ID,
CREATOR,
INT_ROWS_DELETED,
INT_ROWS_INSERTED,
INT_ROWS_UPDATED,
ROWS_READ,
ROWS_WRITTEN,
SQLCODE,
SQLSTATE,
SQLWARN,
START_TIME,
STMT_OPERATION,
STMT_TEXT)),
CONN, CONTROL (TABLE CONTROL_dlmon,
INCLUDES (EVENT_MONITOR_NAME,
MESSAGE,
MESSAGE_TIME))
BUFFERSIZE 8 NONBLOCKED MANUALSTART;
EMB_SQL_CHECK("create");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
EXEC SQL SET EVENT MONITOR dlmon STATE 1;
EMB_SQL_CHECK("set dlmon state 1");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
cout << "Generating events:" << endl;
cout << "0 100" << endl;
cout << "|--------------------------------------------------|"
<< endl << " ";
for(int i = 0; i < 50; i++)
{
EXEC SQL COMMIT; // dummy statement to generate events
EMB_SQL_CHECK("commit");
cout << "*" << flush;
}
cout << endl;
EXEC SQL PREPARE S1 FROM :c1;
EMB_SQL_CHECK("prepare");
EXEC SQL PREPARE S2 FROM :c2;
EMB_SQL_CHECK("prepare");
EXEC SQL DECLARE connheader_dlmon CURSOR FOR S1;
EMB_SQL_CHECK("declare");
EXEC SQL DECLARE control_dlmon CURSOR FOR S2;
EMB_SQL_CHECK("declare");
EXEC SQL OPEN connheader_dlmon;
EMB_SQL_CHECK("open");
EXEC SQL OPEN control_dlmon;
EMB_SQL_CHECK("open");
EXEC SQL FETCH connheader_dlmon INTO :agent_id, :appl_id, :territory_code;
EMB_SQL_CHECK("fetch");
cout <<
"\nSELECT agent_id, appl_id, territory_code FROM connheader_dlmon\n\n";
cout <<
"AGENT_ID APPL_ID TERRITORY_CODE\n";
cout <<
"-------------------- -------------------------------- --------------\n";
while(sqlca.sqlcode != 100)
{
cout << setw(20) << agent_id << setw(37) << appl_id << setw(11)
<< territory_code << "\n";
EXEC SQL FETCH connheader_dlmon
INTO :agent_id, :appl_id, :territory_code;
EMB_SQL_CHECK("fetch");
}
EXEC SQL CLOSE connheader_dlmon;
EMB_SQL_CHECK("close");
EXEC SQL FETCH control_dlmon
INTO :event_monitor_name, :message, :message_time;
EMB_SQL_CHECK("fetch");
cout <<
"\nSELECT event_monitor_name, message, message_time FROM control_dlmon\n\n";
cout <<
"EVENT_MONITOR_NAME MESSAGE MESSAGE_TIME\n";
cout <<
"-------------------- -------------------------------- -----------------------------\n";
while(sqlca.sqlcode != 100)
{
cout << setw(20) << event_monitor_name << setw(33) << message << setw(30)
<< message_time << "\n";
EXEC SQL FETCH control_dlmon
INTO :event_monitor_name, :message, :message_time;
EMB_SQL_CHECK("fetch");
}
EXEC SQL CLOSE control_dlmon;
EMB_SQL_CHECK("close");
EXEC SQL SET EVENT MONITOR dlmon STATE 0;
EMB_SQL_CHECK("set dlmon state 0");
EXEC SQL DROP EVENT MONITOR dlmon;
EMB_SQL_CHECK("drop dlmon");
EXEC SQL DROP TABLE CONNHEADER_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL DROP TABLE DEADLOCK_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL DROP TABLE CONNECTIONS_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL DROP TABLE STMT_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL DROP TABLE CONN_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL DROP TABLE CONTROL_dlmon;
EMB_SQL_CHECK("drop table");
EXEC SQL COMMIT;
EMB_SQL_CHECK("commit");
return rc;
} // EventMonitor::TableDriver
// Build a fully qualified Event Monitor filename
// A File Event Monitor writes to files that are created into the directory
// identified by its target. When initially turned on, it starts writing to
// file: 00000000.evt, when this file is full (as specified by the
// MAXFILESIZE parameter on create event monitor), it moves on to file:
// 00000001.evt, and so on.
int EventMonitor::GetNextFileName(char *location)
{
int rc = 0;
static int fileNumber = -1; // Used in generating the filename, needs
// to be static since this function will
// be called multiple times.
int path_sep = MAX_FILE_LOCATION_SIZE; // Path separation character
// location
char fileName[MAX_FILE_LOCATION_SIZE]; // Full filename (path + filename)
fileNumber++; // Increment the file number (begins at 0)
// Build the full filename (path + filename)
// Case one: location ends in EVENT_FILE_EXT and this is the first time
// that this function is being entered. This case only applies when the
// user passes a filename to be processed. Return the location which
// already contains the filename. (i.e. /path/00000000.EVT was specified,
// return it)
if(strcmp(&location[strlen(location)-4], EVENT_FILE_EXT) == 0)
{
if(fileNumber == 0)
{
return rc;
}
// Case two: location ends in EVENT_FILE_EXT, increment the
// filename. (i.e. /path/00000000.EVT to /path/00000001.EVT)
for(int i=0; i < MAX_FILE_LOCATION_SIZE; i++)
{
if(location[i] == PATH_SEP[0])
{
path_sep = i;
}
}
location[path_sep+1] = '\0';
sprintf(fileName, "%s%.8d%s", location, fileNumber, EVENT_FILE_EXT);
}
// Case three: location ends in PATH_SEP, append the filename.
// (i.e. /path/ to /path/00000000.EVT)
else if(strcmp(&location[strlen(location)-1], PATH_SEP) == 0)
{
sprintf(fileName, "%s%.8d%s", location, fileNumber, EVENT_FILE_EXT);
}
// Case four: location does not end with PATH_SEP or EVENT_FILE_EXT,
// assume that a directory name has been provided. Append PATH_SEP and
// the filename. (i.e. /path to /path/00000000.EVT)
else
{
sprintf(fileName, "%s%s%.8d%s", location, PATH_SEP, fileNumber,
EVENT_FILE_EXT);
}
strncpy(location, fileName, sizeof(char)*MAX_FILE_LOCATION_SIZE);
return rc;
} // EventMonitor::GetNextFileName
// This routine byte reverses the event header or the element header
// using the macros defined in this file to restore it to its original
// endian format.
int EventMonitor::HeaderByteReverse(sqlm_header_info *pHeader)
{
int rc = 0;
pHeader->size = SWAP4(pHeader->size);
pHeader->type = SWAP2(pHeader->type);
pHeader->element = SWAP2(pHeader->element);
return rc;
} // EventMonitor::HeaderByteReverse
// This routine reverses the event data or the element data.
// An event is considered to be an element.
int EventMonitor::DataByteReverse(char *dataBuf, sqluint32 dataSize)
{
int rc = 0;
sqlm_header_info *pElemHeader = NULL;
char *pElemData = NULL;
sqluint32 dataOffset = 0;
sqluint32 elemDataSize = 0;
sqluint32 elemHeaderSize = sizeof(sqlm_header_info);
// for each of the elements in the datastream that are numeric, perform
// byte reversal
while(dataOffset < dataSize)
{
// byte reverse the element header
pElemHeader = (sqlm_header_info *) (dataBuf + dataOffset);
rc = HeaderByteReverse(pElemHeader);
if(rc != 0)
return rc;
// remember the element data's size...it will be byte reversed
// before we skip to the next element
elemDataSize = pElemHeader->size;
// byte reverse the element data
pElemData = (char *) (dataBuf + dataOffset + elemHeaderSize);
if(pElemHeader->type == SQLM_TYPE_HEADER)
{
rc = DataByteReverse(pElemData, pElemHeader->size);
if(rc != 0)
return rc;
}
else
{
switch(pElemHeader->type)
{
case SQLM_TYPE_16BIT:
case SQLM_TYPE_U16BIT:
*(sqluint16 *)(pElemData) = SWAP2(*(short *)(pElemData));
break;
case SQLM_TYPE_32BIT:
case SQLM_TYPE_U32BIT:
*(sqluint32 *)(pElemData) = SWAP4(*(sqluint32 *)(pElemData));
break;
case SQLM_TYPE_64BIT:
case SQLM_TYPE_U64BIT:
SWAP8(pElemData);
break;
default:
break; // not a numeric type, do nothing
}
}
dataOffset = dataOffset + elemHeaderSize + elemDataSize;
}
return rc;
} // EventMonitor::DataByteReverse
int EventMonitor::ReadFile()
{
int rc = 0;
Snapshot ss; // This class parses the event monitor data
rc = GetNextFileName(fileName); // This function should not be
// called before EvmArgsRead. It
// assumes that fileName is in a
// specific format.
if(rc != 0)
return rc;
ifstream inFile(fileName, ios::in | ios::binary);
if (!inFile)
{
cerr << "Error: Unable to read event monitor data at the specified "
<< "location."
<< endl;
return 1;
}
else
{
inFile.close();
inFile.open(fileName, ios::out | ios::binary);
}
inFile.read((char *) (&eventLogStreamHeader),
sizeof(eventLogStreamHeader));
while(inFile)
{
inFile.read((char *) (&headerInfo), sizeof(headerInfo));
if(!inFile.eof())
{
switch(eventLogStreamHeader.byte_order)
{
case SQLM_BIG_ENDIAN:
#ifdef LITTLE_ENDIAN
needByteReversal = true;
#else
needByteReversal = false;
#endif
break;
case SQLM_LITTLE_ENDIAN:
#ifdef LITTLE_ENDIAN
needByteReversal = false;
#else
needByteReversal = true;
#endif
break;
default:
cerr << endl
<< "Error: Unexpected memory model specified in stream."
<< endl;
rc = 1;
break;
}
if(needByteReversal == true)
{
rc = HeaderByteReverse(&headerInfo);
if(rc != 0)
return rc;
}
if(headerInfo.size > MAX_EVENT_DATA_SIZE)
{
cerr << endl
<< "Error: incompatible or corrupted event stream." << endl
<< "Next event data has size: " << headerInfo.size
<< "!" << "(max is: " << MAX_EVENT_DATA_SIZE << ")" << endl;
return 1;
}
inFile.read((char *) (&dataBuf), headerInfo.size);
if(needByteReversal == true)
{
rc = DataByteReverse(dataBuf, headerInfo.size);
if(rc != 0)
return rc;
}
ss.ParseMonitorStream(" ",
dataBuf,
dataBuf+headerInfo.size);
}
if(inFile.eof())
{
inFile.clear();
inFile.close();
rc = GetNextFileName(fileName);
if(rc != 0)
return rc;
inFile.open(fileName, ios::binary);
inFile.open(fileName, ios::in | ios::binary);
if (!inFile)
{
// file doesn't exist
}
else //file exists
{
inFile.close();
inFile.open(fileName, ios::out | ios::binary);
}
}
}
if(!inFile.eof())
inFile.close();
return 0;
} // EventMonitor::ReadFile