8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 21:23:03 +01:00

Trace plugin

This commit is contained in:
hvlad 2009-02-01 22:10:36 +00:00
parent 26bdd120e3
commit 130c67bf0f
14 changed files with 4025 additions and 0 deletions

View File

@ -0,0 +1,258 @@
/*
* PROGRAM: Firebird Trace Services
* MODULE: TraceConfiguration.h
* DESCRIPTION: Trace Configuration Reader
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Khorsun Vladyslav
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2009 Khorsun Vladyslav <hvlad@users.sourceforge.net>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#include "TraceConfiguration.h"
using namespace Firebird;
void TraceCfgReader::readTraceConfiguration(const char* text,
const PathName& databaseName,
TracePluginConfig& config)
{
TraceCfgReader cfgReader(text, databaseName, config);
cfgReader.readConfig();
}
#define PATH_PARAMETER(NAME, VALUE) \
if (!found && el->name == #NAME) { \
string temp = el->getAttributeName(0); \
expandPattern(temp); \
m_config.NAME = temp.c_str(); \
found = true; \
}
#define STR_PARAMETER(NAME, VALUE) \
if (!found && el->name == #NAME) { \
m_config.NAME = el->getAttributeName(0); \
found = true; \
}
#define BOOL_PARAMETER(NAME, VALUE) \
if (!found && el->name == #NAME) { \
m_config.NAME = parseBoolean(el->getAttributeName(0)); \
found = true; \
}
#define UINT_PARAMETER(NAME, VALUE) \
if (!found && el->name == #NAME) { \
m_config.NAME = parseUInteger(el->getAttributeName(0)); \
found = true; \
}
void TraceCfgReader::readConfig()
{
Firebird::AutoPtr<ConfigFile> cfgFile = new ConfigFile(Lex::LEX_none);
cfgFile->addText(m_text);
cfgFile->parse();
m_subpatterns[0].rm_so = 0;
m_subpatterns[0].rm_eo = m_databaseName.length();
for (size_t i = 1; i < FB_NELEM(m_subpatterns); i++)
{
m_subpatterns[i].rm_so = -1;
m_subpatterns[i].rm_eo = -1;
}
bool defDB = false, defSvc = false, exactMatch = false;
const Element *section = cfgFile->getObjects()->children;
for (; section && !exactMatch; section = section->sibling)
{
const bool isDatabase = (section->name == "database");
if (!isDatabase && section->name != "services")
continue;
string pattern = section->getAttributes() ? section->getAttributeName(0) : "";
bool match = false;
if (pattern.empty())
{
if (isDatabase)
{
if (defDB) {
fatal_exception::raiseFmt("line %d: second default database section is not allowed",
section->lineNumber + 1);
}
match = !m_databaseName.empty();
defDB = true;
}
else
{
if (defSvc) {
fatal_exception::raiseFmt("line %d: second default service section is not allowed",
section->lineNumber + 1);
}
match = m_databaseName.empty();
defSvc = true;
}
}
else if (isDatabase && !m_databaseName.empty())
{
if (m_databaseName == pattern.c_str()) {
match = exactMatch = true;
}
else
{
regex_t matcher;
int flags = REG_EXTENDED;
if (!CASE_SENSITIVITY)
flags |= REG_ICASE;
int errorCode = regcomp(&matcher, pattern.c_str(), flags);
if (errorCode)
{
char errBuf[256];
regerror(errorCode, NULL, errBuf, sizeof(errBuf));
fatal_exception::raiseFmt(
"line %d: error \"%s\" while compiling regular expression \"%s\"",
section->lineNumber + 1, errBuf, pattern.c_str());
}
errorCode = regexec(&matcher, m_databaseName.c_str(), FB_NELEM(m_subpatterns), m_subpatterns, 0);
if (errorCode && errorCode != REG_NOMATCH)
{
char errBuf[256];
regerror(errorCode, NULL, errBuf, sizeof(errBuf));
fatal_exception::raiseFmt(
"line %d: error \"%s\" while applying regular expression \"%s\" to database \"%s\"",
section->lineNumber + 1, errBuf, pattern.c_str(), m_databaseName.c_str());
}
if (errorCode == 0)
match = exactMatch = true;
}
}
if (!match)
continue;
const Element *el = section->children;
for (; el; el = el->sibling)
{
if (!el->getAttributes()) {
fatal_exception::raiseFmt("line %d: element \"%s\" have no attribute value set",
el->lineNumber + 1, el->name.c_str());
}
bool found = false;
if (isDatabase)
{
#define DATABASE_PARAMS
#include "paramtable.h"
#undef DATABASE_PARAMS
}
else
{
#define SERVICE_PARAMS
#include "paramtable.h"
#undef SERVICE_PARAMS
}
if (!found) {
fatal_exception::raiseFmt("line %d: element \"%s\" is unknown",
el->lineNumber + 1, el->name.c_str());
}
}
}
}
#undef PATH_PARAMETER
#undef STR_PARAMETER
#undef BOOL_PARAMETER
#undef UINT_PARAMETER
bool TraceCfgReader::parseBoolean(const string& value) const
{
string tempValue = value;
tempValue.upper();
if (value == "1" || tempValue == "ON" || tempValue == "YES" || tempValue == "TRUE")
return true;
if (value == "0" || tempValue == "OFF" || tempValue == "NO" || tempValue == "FALSE")
return false;
fatal_exception::raiseFmt("\"%s\" is not a valid boolean value", value.c_str());
return false; // Silence the compiler
}
ULONG TraceCfgReader::parseUInteger(const string& value) const
{
ULONG result = 0;
if (!sscanf(value.c_str(), "%"ULONGFORMAT, &result)) {
fatal_exception::raiseFmt("\"%s\" is not a valid integer value", value.c_str());
}
return result;
}
void TraceCfgReader::expandPattern(string& valueToExpand)
{
string::size_type pos = 0;
while (pos < valueToExpand.length())
{
string::char_type c = valueToExpand[pos];
if (c == '$')
{
if (pos + 1 >= valueToExpand.length()) {
fatal_exception::raiseFmt("pattern is invalid");
}
c = valueToExpand[pos+1];
if (c == '$')
{
// Kill one of the dollar signs and loop again
valueToExpand.erase(pos, 1);
continue;
}
if (c >= '0' && c <= '9')
{
regmatch_t *subpattern = m_subpatterns + (c - '0');
// Replace value with piece of database name
valueToExpand.erase(pos, 2);
if (subpattern->rm_eo != -1 && subpattern->rm_so != -1)
{
off_t subpattern_len = subpattern->rm_eo - subpattern->rm_so;
valueToExpand.insert(pos,
m_databaseName.substr(subpattern->rm_so, subpattern_len).c_str(),
subpattern_len);
pos += subpattern_len;
}
continue;
}
if (c == '&')
{
// Replace value with whole database file name
valueToExpand.erase(pos, 2);
const Firebird::PathName& filename = m_databaseName;
valueToExpand.insert(pos, filename.c_str(), filename.length());
pos += filename.length();
continue;
}
fatal_exception::raiseFmt("pattern is invalid");
}
pos++;
}
}

View File

@ -0,0 +1,72 @@
/*
* PROGRAM: Firebird Trace Services
* MODULE: TraceConfiguration.h
* DESCRIPTION: Trace Configuration Reader
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Khorsun Vladyslav
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2009 Khorsun Vladyslav <hvlad@users.sourceforge.net>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#ifndef TRACE_CONFIGURATION
#define TRACE_CONFIGURATION
#include "firebird.h"
#include "../../common/classes/auto.h"
#include "../../common/classes/fb_string.h"
#include "../../config/ConfigFile.h"
#include "../../config/ConfObj.h"
#include "../../config/ConfObject.h"
#include "../../config/Element.h"
#include "../../config/AdminException.h"
#include "TracePluginConfig.h"
#include <sys/types.h>
#include <regex.h>
using Firebird::string;
using Firebird::PathName;
class TraceCfgReader
{
public:
static void readTraceConfiguration(const char* text, const PathName& databaseName, TracePluginConfig& config);
private:
TraceCfgReader(const char* text, const PathName& databaseName, TracePluginConfig& config) :
m_text(text),
m_databaseName(databaseName),
m_config(config)
{}
void readConfig();
void expandPattern(string& valueToExpand);
bool parseBoolean(const string& value) const;
ULONG parseUInteger(const string& value) const;
const char* m_text;
const PathName& m_databaseName;
regmatch_t m_subpatterns[10];
TracePluginConfig& m_config;
};
#endif // TRACE_CONFIGURATION

View File

@ -0,0 +1,86 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: TracePluginConfig.h
* DESCRIPTION: Structure with plugin configuration parameters
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#ifndef TRACEPLUGINCONFIG_H
#define TRACEPLUGINCONFIG_H
#include "../../common/classes/fb_string.h"
enum LogFormat {lfText = 0, lfBinary = 1};
struct TracePluginConfig {
#define DATABASE_PARAMS
#define SERVICE_PARAMS
#define PATH_PARAMETER(NAME, VALUE) Firebird::PathName NAME;
#define STR_PARAMETER(NAME, VALUE) Firebird::string NAME;
#define BOOL_PARAMETER(NAME, VALUE) bool NAME;
#define UINT_PARAMETER(NAME, VALUE) ULONG NAME;
#include "paramtable.h"
#undef PATH_PARAMETER
#undef STR_PARAMETER
#undef BOOL_PARAMETER
#undef UINT_PARAMETER
Firebird::PathName db_filename;
// Default constructor. Pass pool to all string parameters, initialize everything to defaults
TracePluginConfig() :
#define PATH_PARAMETER(NAME, VALUE) NAME(*getDefaultMemoryPool(), VALUE, strlen(VALUE)),
#define STR_PARAMETER(NAME, VALUE) NAME(*getDefaultMemoryPool(), VALUE, strlen(VALUE)),
#define BOOL_PARAMETER(NAME, VALUE) NAME(VALUE),
#define UINT_PARAMETER(NAME, VALUE) NAME(VALUE),
#include "paramtable.h"
#undef PATH_PARAMETER
#undef STR_PARAMETER
#undef BOOL_PARAMETER
#undef UINT_PARAMETER
db_filename(*getDefaultMemoryPool())
{ }
// Copy constructor
TracePluginConfig(const TracePluginConfig& from) :
#define PATH_PARAMETER(NAME, VALUE) NAME(*getDefaultMemoryPool(), from.NAME),
#define STR_PARAMETER(NAME, VALUE) NAME(*getDefaultMemoryPool(), from.NAME),
#define BOOL_PARAMETER(NAME, VALUE) NAME(from.NAME),
#define UINT_PARAMETER(NAME, VALUE) NAME(from.NAME),
#include "paramtable.h"
#undef PATH_PARAMETER
#undef STR_PARAMETER
#undef BOOL_PARAMETER
#undef UINT_PARAMETER
db_filename(*getDefaultMemoryPool(), from.db_filename)
{ }
private:
// Not implemented
TracePluginConfig& operator=(const TracePluginConfig& from);
#undef DATABASE_PARAMS
#undef SERVICE_PARAMS
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,324 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: TracePluginImpl.h
* DESCRIPTION: Plugin implementation
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2008 Khorsun Vladyslav
*/
#ifndef TRACEPLUGINIMPL_H
#define TRACEPLUGINIMPL_H
#include "../../jrd/ntrace.h"
#include "TracePluginConfig.h"
#include "os/FileObject.h"
#include "../../common/classes/rwlock.h"
#include "../../common/classes/GenericMap.h"
#include "../../common/classes/locks.h"
// Bring in off_t
#include <sys/types.h>
#include <regex.h>
class TracePluginImpl {
public:
// Create skeletal plugin (to report initialization error)
static TracePlugin* createSkeletalPlugin();
// Create trace plugin for particular database
static TracePlugin* createFullPlugin(const TracePluginConfig &configuration, TraceInitInfo* initInfo);
// Serialize exception to TLS buffer to return it to user
static void marshal_exception(const Firebird::Exception& ex);
// Data for tracked (active) connections
struct ConnectionData {
int id;
Firebird::string* description;
// Deallocate memory used by objects hanging off this structure
void deallocate_references() {
delete description;
description = NULL;
}
static const int& generate(const void* sender, const ConnectionData& item) {
return item.id;
}
};
typedef Firebird::BePlusTree<ConnectionData, int, Firebird::MemoryPool, ConnectionData>
ConnectionsTree;
// Data for tracked (active) transactions
struct TransactionData {
int id;
Firebird::string* description;
// Deallocate memory used by objects hanging off this structure
void deallocate_references() {
delete description;
description = NULL;
}
static const int& generate(const void* sender, const TransactionData& item) {
return item.id;
}
};
typedef Firebird::BePlusTree<TransactionData, int, Firebird::MemoryPool, TransactionData>
TransactionsTree;
// Data for tracked (active) statements
struct StatementData {
unsigned int id;
Firebird::string* description; // NULL in this field indicates that tracing of this statement is not desired
static const unsigned int& generate(const void* sender, const StatementData& item) {
return item.id;
}
};
typedef Firebird::BePlusTree<StatementData, unsigned int, Firebird::MemoryPool, StatementData>
StatementsTree;
struct ServiceData {
ntrace_service_t id;
Firebird::string* description;
// Deallocate memory used by objects hanging off this structure
void deallocate_references() {
delete description;
description = NULL;
}
static const ntrace_service_t& generate(const void* sender, const ServiceData& item) {
return item.id;
}
};
typedef Firebird::BePlusTree<ServiceData, ntrace_service_t, Firebird::MemoryPool, ServiceData>
ServicesTree;
private:
TracePluginImpl(const TracePluginConfig &configuration, TraceInitInfo* initInfo);
~TracePluginImpl();
bool operational; // Set if plugin is fully initialized and is ready for logging
// Keep this member field first to ensure its correctness
// when destructor is called
int session_id; // trace session ID, set by Firebird
Firebird::string session_name; // trace session name, set by Firebird
FileObject *logFile; // Thread-safe
TraceLogWriter* logWriter;
TracePluginConfig config; // Immutable, thus thread-safe
// Data for currently active connections, transactions, statements
Firebird::RWLock connectionsLock;
ConnectionsTree connections;
Firebird::RWLock transactionsLock;
TransactionsTree transactions;
Firebird::RWLock statementsLock;
StatementsTree statements;
Firebird::RWLock servicesLock;
ServicesTree services;
// Lock for log rotation
Firebird::RWLock renameLock;
regex_t include_matcher;
regex_t exclude_matcher;
bool need_rotate(size_t added_bytes_length);
void rotateLog(size_t added_bytes_length);
void writePacket(const UCHAR* packet_data, const ULONG packet_size);
void appendGlobalCounts(PerformanceInfo *info, Firebird::string& line);
void appendTableCounts(PerformanceInfo *info, Firebird::string& line);
void appendParams(TraceParams *params, Firebird::string& line);
void appendServiceQueryParams(size_t send_item_length,
const ntrace_byte_t* send_items, size_t recv_item_length,
const ntrace_byte_t* recv_items, Firebird::string& line);
void formatStringArgument(Firebird::string& result, const UCHAR* str, size_t len);
// register various objects
void register_connection(TraceConnection* connection);
void register_transaction(TraceTransaction* transaction);
void register_sql_statement(TraceSQLStatement* statement);
void register_blr_statement(TraceBLRStatement* statement);
void register_service(TraceService* service);
// Write message to text log file
void logRecord(const char* action, Firebird::string& line);
void logRecordConn(const char* action, TraceConnection* connection, Firebird::string& line);
void logRecordTrans(const char* action, TraceConnection* connection,
TraceTransaction* transaction, Firebird::string& line);
void logRecordProc(const char* action, TraceConnection* connection,
TraceTransaction* transaction, const char* proc_name, Firebird::string& line);
void logRecordStmt(const char* action, TraceConnection* connection,
TraceTransaction* transaction, TraceStatement* statement,
bool isSQL, Firebird::string& line);
void logRecordServ(const char* action, TraceService* service, Firebird::string& line);
/* Methods which do logging of events to file */
void log_init();
void log_finalize();
void log_event_attach(
TraceConnection* connection, ntrace_boolean_t create_db,
ntrace_result_t att_result);
void log_event_detach(
TraceConnection* connection, ntrace_boolean_t drop_db);
void log_event_transaction_start(
TraceConnection* connection, TraceTransaction* transaction,
size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result);
void log_event_transaction_end(
TraceConnection* connection, TraceTransaction* transaction,
ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result);
void log_event_set_context(
TraceConnection* connection, TraceTransaction* transaction,
TraceContextVariable* variable);
void log_event_proc_execute(
TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure,
bool started, ntrace_result_t proc_result);
void log_event_trigger_execute(
TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger,
bool started, ntrace_result_t trig_result);
void log_event_dsql_prepare(
TraceConnection* connection, TraceTransaction* transaction,
TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result);
void log_event_dsql_free(
TraceConnection* connection, TraceSQLStatement* statement, unsigned short option);
void log_event_dsql_execute(
TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement,
bool started, ntrace_result_t req_result);
void log_event_blr_compile(
TraceConnection* connection, TraceTransaction* transaction,
TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result);
void log_event_blr_execute(
TraceConnection* connection, TraceTransaction* transaction,
TraceBLRStatement* statement, ntrace_result_t req_result);
void log_event_dyn_execute(
TraceConnection* connection, TraceTransaction* transaction,
TraceDYNRequest* request, ntrace_counter_t time_millis,
ntrace_result_t req_result);
void log_event_service_attach(
TraceService* service, ntrace_result_t att_result);
void log_event_service_start(
TraceService* service, size_t switches_length, const char* switches,
ntrace_result_t start_result);
void log_event_service_query(
TraceService* service, size_t send_item_length,
const ntrace_byte_t* send_items, size_t recv_item_length,
const ntrace_byte_t* recv_items, ntrace_result_t query_result);
void log_event_service_detach(
TraceService* service, ntrace_result_t detach_result);
/* Finalize plugin. Called when database is closed by the engine */
static ntrace_boolean_t ntrace_shutdown(const TracePlugin* tpl_plugin);
/* Function to return error string for hook failure */
static const char* ntrace_get_error(const TracePlugin* tpl_plugin);
/* Create/close attachment */
static ntrace_boolean_t ntrace_event_attach(const TracePlugin* tpl_plugin,
TraceConnection* connection, ntrace_boolean_t create_db,
ntrace_result_t att_result);
static ntrace_boolean_t ntrace_event_detach(const TracePlugin* tpl_plugin,
TraceConnection* connection, ntrace_boolean_t drop_db);
/* Start/end transaction */
static ntrace_boolean_t ntrace_event_transaction_start(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
size_t tpb_length, const ntrace_byte_t* tpb, ntrace_result_t tra_result);
static ntrace_boolean_t ntrace_event_transaction_end(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
ntrace_boolean_t commit, ntrace_boolean_t retain_context, ntrace_result_t tra_result);
/* Assignment to context variables */
static ntrace_boolean_t ntrace_event_set_context(const struct TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
TraceContextVariable* variable);
/* Stored procedure executing */
static ntrace_boolean_t ntrace_event_proc_execute(const struct TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction, TraceProcedure* procedure,
bool started, ntrace_result_t proc_result);
static ntrace_boolean_t ntrace_event_trigger_execute(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction, TraceTrigger* trigger,
bool started, ntrace_result_t trig_result);
/* DSQL statement lifecycle */
static ntrace_boolean_t ntrace_event_dsql_prepare(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
TraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result);
static ntrace_boolean_t ntrace_event_dsql_free(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceSQLStatement* statement, unsigned short option);
static ntrace_boolean_t ntrace_event_dsql_execute(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction, TraceSQLStatement* statement,
bool started, ntrace_result_t req_result);
/* BLR requests */
static ntrace_boolean_t ntrace_event_blr_compile(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
TraceBLRStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result);
static ntrace_boolean_t ntrace_event_blr_execute(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
TraceBLRStatement* statement, ntrace_result_t req_result);
/* DYN requests */
static ntrace_boolean_t ntrace_event_dyn_execute(const TracePlugin* tpl_plugin,
TraceConnection* connection, TraceTransaction* transaction,
TraceDYNRequest* request, ntrace_counter_t time_millis,
ntrace_result_t req_result);
/* Using the services */
static ntrace_boolean_t ntrace_event_service_attach(const TracePlugin* tpl_plugin,
TraceService* service, ntrace_result_t att_result);
static ntrace_boolean_t ntrace_event_service_start(const TracePlugin* tpl_plugin,
TraceService* service, size_t switches_length, const char* switches,
ntrace_result_t start_result);
static ntrace_boolean_t ntrace_event_service_query(const TracePlugin* tpl_plugin,
TraceService* service, size_t send_item_length,
const ntrace_byte_t* send_items, size_t recv_item_length,
const ntrace_byte_t* recv_items, ntrace_result_t query_result);
static ntrace_boolean_t ntrace_event_service_detach(const TracePlugin* tpl_plugin,
TraceService* service, ntrace_result_t detach_result);
};
#endif // TRACEPLUGINIMPL_H

View File

@ -0,0 +1,152 @@
# Trace configuration. Following rules are used :
# - configuration is processed from top to bottom
# - there is two kind of sections allowed : "database" and "services"
# - parameters at "default" section used for all databases or services
# - if database name matches pattern options are immediately applied,
# search does not continue
#
# Pattern is either database name without path or POSIX 1falsefalse2.3 extended regular
# expression in square braces which is matched against fully qualified database
# path name.
#
# For log file name Apache/Perl syntax for substitutions is supported.
# I.e. $& - whole matched string, $1 ... $9 - braced subexpressions.
# $$ is dollar sign.
<database>
# Do we trace database events or not
enabled false
# Operations log file name. For use by system audit trace only
#log_filename =
# Maximum size of log file (megabytes). Used by system audit trace for
# log's rotation : when current log file reached this limit its renamed
# using current date and time and new log file is created
max_log_size 0
# SQL query filters.
#
# Only SQL statements falling under given regular expression are reported in the log.
#include_filter
# SQL statements falling under given regular expression are NOT reported in the log.
#exclude_filter =
# Put attach/detach log records
log_connections false
# Trace only given connection id. If zero - trace all connections
#connection_id 0
# Put transaction start/end records
log_transactions false
# Put sql statement prepare records
log_statement_prepare false
# Put sql statement free records
log_statement_free false
# Put sql statement execution start records
log_statement_start false
# Put sql statement execution finish\fetch to eof records
log_statement_finish false
# Put record when stored procedure is start execution
log_procedure_start false
# Put record when stored procedure is finish execution
log_procedure_finish false
# Put trigger execute records
log_trigger_start false
# Put trigger execute records
log_trigger_finish false
# Put context variable change records (RDB$SET_CONTEXT)
#log_context false
# Print access path (plan) with sql statement
print_plan false
# Print detailed performance info when applicable
print_perf false
# Put blr requests compile/execute records
log_blr_requests false
# Print blr requests or not
print_blr false
# Put dyn requests execute records
log_dyn_requests false
# Print dyn requests or not
print_dyn false
# Put xxx_finish record only if its timing exceeds this number of milliseconds
time_threshold 100
# Maximum length of SQL string logged
# Beware when adjusting max_xxx parameters! Maximum length of log record
# for one event should never exceed 64K.
max_sql_length 300
# Maximum length of blr request logged
max_blr_length 500
# Maximum length of dyn request logged
max_dyn_length 500
# Maximum length of individual string argument we log
max_arg_length 80
# Maximum number of query arguments to put in log
max_arg_count 30
</database>
<services>
# Do we trace services events or not
enabled false
# Operations log file name. For use by system audit trace only
#log_filename =
# Maximum size of log file (megabytes). Used by system audit trace for
# log's rotation
max_log_size 0
# Put service attach, detach and start records
log_services false
# Put service query records
log_service_query false
</services>
# Example of trace customization:
#
# Enable logging for my_database.fdb in any folder
<database my_database.fdb>
enabled 1
</database>
# Enable logging for test.fdb, azk2.fdb and rulez.fdb in any directory
# into log file name matching database name - test.log, azk2.log and
# rulez.log appropriately
#
<database ^.*[\/](test|azk2|rulez)\.fdb$>
enabled 1
log_filename $1.log
</database>

View File

@ -0,0 +1,173 @@
/*
* PROGRAM: Client/Server Common Code
* MODULE: FileObject.h
* DESCRIPTION: Wrapper class for platform IO
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#ifndef FILEOBJECT_H
#define FILEOBJECT_H
#include "../../../common/classes/fb_string.h"
#include "../../../common/classes/locks.h"
#include "../../../jrd/common.h"
#ifdef WIN_NT
#define NEWLINE "\r\n"
#else
#define NEWLINE "\n"
#endif
enum FileOpenFlags {
fo_rdonly = 0x0000, /* open for reading only */
fo_wronly = 0x0001, /* open for writing only */
fo_rdwr = 0x0002, /* open for reading and writing */
fo_append = 0x0008, /* writes done at eof */
fo_creat = 0x0100, /* create and open file */
fo_trunc = 0x0200, /* open and truncate */
fo_excl = 0x0400, /* open only if file doesn't already exist */
/* Temporary file bit - file is deleted when last handle is closed */
fo_temporary = 0x0040, /* temporary file bit */
/* temporary access hint */
fo_short_lived = 0x1000, /* temporary storage file, try not to flush */
/* sequential/random access hints */
fo_sequential = 0x0020, /* file access is primarily sequential */
fo_random = 0x0010 /* file access is primarily random */
};
enum SeekOrigin {
so_from_beginning,
so_from_current,
so_from_end
};
class FileObject : public Firebird::AutoStorage {
public:
FileObject(const Firebird::PathName& afilename, int flags, int pflags = 0666) :
filename(getPool(), afilename),
#ifdef WIN_NT
file(INVALID_HANDLE_VALUE),
append_mutex(INVALID_HANDLE_VALUE)
#else
file(-1)
#endif
{
open(flags, pflags);
}
FileObject(Firebird::MemoryPool& pool, const Firebird::PathName& afilename, int flags, int pflags = 0666) :
Firebird::AutoStorage(pool), filename(getPool(), afilename),
#ifdef WIN_NT
file(INVALID_HANDLE_VALUE),
append_mutex(INVALID_HANDLE_VALUE)
#else
file(-1)
#endif
{
open(flags, pflags);
}
~FileObject();
// Platform-specific stuff
size_t blockRead(void* buffer, size_t bytesToRead);
void blockWrite(const void* buffer, size_t bytesToWrite);
void writeHeader(const void* buffer, size_t bytesToWrite);
SINT64 seek(SINT64 offset, SeekOrigin origin);
FB_UINT64 size();
//This method used when log file was renamed by another process
void reopen();
bool renameFile(const Firebird::PathName new_filename);
// Generic stuff. Let it be inline for the moment.
// If there will be a more than a few such methods we need to use inheritance
bool readLine(Firebird::string &dest) {
// This method is not very efficient, but is still much better then
// reading characters one-by-one. Plus it can handle line breaks in
// Windows, Linux and Macintosh format nicely on all platforms
char buffer[100];
size_t bytesRead;
dest.resize(0);
bool prevCR = false;
do {
bytesRead = blockRead(buffer, sizeof(buffer));
for (int pos = 0; pos < bytesRead; pos++) {
switch(buffer[pos]) {
case '\n':
dest.append(buffer, pos);
// Adjust file pointer
seek(pos - bytesRead + 1, so_from_current);
// Kill trailing CR if present (Windows)
if (prevCR)
dest.resize(dest.length() - 1);
return true;
case '\r':
prevCR = true;
break;
default:
if (prevCR) {
dest.append(buffer, pos);
// Adjust file pointer
seek(pos - bytesRead, so_from_current);
return true;
}
}
}
dest.append(buffer, bytesRead);
} while (bytesRead == sizeof(buffer));
// Kill trailing CR if present
if (prevCR)
dest.resize(dest.length() - 1);
return dest.length() || bytesRead;
}
void writeLine(const Firebird::string &from) {
// Line should be written in a single BlockWrite call to handle file append properly
Firebird::string temp = from.substr(0, from.max_length() - 2) + NEWLINE;
blockWrite(temp.c_str(), temp.length());
}
private:
// Forbid copy and assignment operators
FileObject(const FileObject &);
FileObject& operator= (const FileObject &);
void open(int flags, int pflags);
Firebird::PathName filename;
#ifdef WIN_NT
HANDLE file;
HANDLE append_mutex;
#else
int file;
#endif
};
#endif // FILEOBJECT_H

View File

@ -0,0 +1,37 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: TracePluginImpl.h
* DESCRIPTION: Platform specifics
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#ifndef PLATFORM_H
#define PLATFORM_H
const char* get_error_string();
void set_error_string(const char* str);
SLONG get_process_id();
#endif // PLATFORM_H

View File

@ -0,0 +1,179 @@
/*
* PROGRAM: Client/Server Common Code
* MODULE: FileObject.cpp
* DESCRIPTION: Wrapper class for platform IO
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#include "../../../include/firebird.h"
#include "../FileObject.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
using namespace Firebird;
Firebird::Mutex open_mutex;
void FileObject::open(int flags, int pflags) {
open_mutex.enter();
int oflags = 0;
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr)) {
case fo_rdonly:
oflags = O_RDONLY;
break;
case fo_wronly:
oflags = O_WRONLY;
break;
default:
oflags = O_RDWR;
break;
}
if (flags & fo_append)
oflags |= O_APPEND;
if (flags & fo_creat)
oflags |= O_CREAT;
if (flags & fo_trunc)
oflags |= O_TRUNC;
if (flags & fo_excl)
oflags |= O_EXCL;
file = ::open(filename.c_str(), oflags, pflags);
open_mutex.leave();
if (file < 0)
fatal_exception::raiseFmt("Error (%d) opening file: %s", errno, filename.c_str());
if (flags & fo_temporary)
unlink(filename.c_str());
}
FileObject::~FileObject() {
close(file);
}
//Size of file, given by descriptor
FB_UINT64 FileObject::size() {
off_t nFileLen = 0;
struct stat file_stat;
if (!fstat(file, &file_stat))
nFileLen = file_stat.st_size;
else
fatal_exception::raiseFmt("IO error (%d) file stat: %s", errno, filename.c_str());
return nFileLen;
}
size_t FileObject::blockRead(void* buffer, size_t bytesToRead) {
ssize_t bytesDone = read(file, buffer, bytesToRead);
if (bytesDone < 0)
fatal_exception::raiseFmt("IO error (%d) reading file: %s",
errno,
filename.c_str());
return bytesDone;
}
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
ssize_t bytesDone = write(file, buffer, bytesToWrite);
if (bytesDone != static_cast<ssize_t>(bytesToWrite))
{
fatal_exception::raiseFmt("IO error (%d) writing file: %s",
errno,
filename.c_str());
}
}
// Write data to header only if file is empty
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
if (seek(0, so_from_end) != 0)
return;
ssize_t bytesDone = write(file, buffer, bytesToWrite);
if (bytesDone != static_cast<ssize_t>(bytesToWrite))
{
fatal_exception::raiseFmt("IO error (%d) writing file: %s",
errno,
filename.c_str());
}
}
void FileObject::reopen() {
if (file >= 0)
close(file);
open(fo_rdwr | fo_append | fo_creat, 0666);
// fchmod(file, PMASK);
}
bool FileObject::renameFile(const Firebird::PathName new_filename) {
if (rename(filename.c_str(), new_filename.c_str()))
{
int rename_err = errno;
if (rename_err == ENOENT || rename_err == EEXIST) {
// Another process renames our file just now. Open new it.
reopen();
return false;
}
fatal_exception::raiseFmt("IO error (%d) renaming file: %s",
rename_err, filename.c_str());
}
else
reopen();
return true;
}
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
if (newOffset != (SINT64) LSEEK_OFFSET_CAST newOffset) {
fatal_exception::raiseFmt(
"Attempt to seek file %s past platform size limit",
filename.c_str());
}
int moveMethod;
switch(origin) {
case so_from_beginning:
moveMethod = SEEK_SET;
break;
case so_from_current:
moveMethod = SEEK_CUR;
break;
case so_from_end:
moveMethod = SEEK_END;
break;
}
off_t result = lseek(file, newOffset, moveMethod);
if (result == (off_t) -1)
{
fatal_exception::raiseFmt("IO error (%d) seeking file: %s",
errno,
filename.c_str());
}
return result;
}

View File

@ -0,0 +1,90 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: TracePluginImpl.h
* DESCRIPTION: Platform specifics (Win32)
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#include "firebird.h"
#include "../platform.h"
#include "../common/classes/fb_tls.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#define TEST
//#undef TEST
#ifndef TEST
class MallocClear {
public:
static void clear(char* error_string) {
free(error_string);
}
};
Firebird::TlsValue<char*, MallocClear> error_value;
const char* get_error_string() {
return error_value.get();
}
void set_error_string(const char* str) {
char* org_str = error_value.get();
if (org_str) {
free(org_str);
error_value.set(NULL);
}
if (str) {
size_t len = strlen(str);
char* new_str = (char*) malloc(len + 1);
if (new_str) {
memcpy(new_str, str, len + 1);
error_value.set(new_str);
}
}
}
#else
TLS_DECLARE(char*, error_string);
const char* get_error_string(){
return TLS_GET(error_string);
}
void set_error_string(const char* str){
char* org_str = TLS_GET(error_string);
if (org_str){
free(org_str);
TLS_SET(error_string,NULL);
}
if (str){
size_t len = strlen(str);
char* new_str = (char*) malloc(len + 1);
if (new_str) {
memcpy(new_str, str, len + 1);
TLS_SET(error_string, new_str);
}
}
}
#endif
SLONG get_process_id() {
return getpid();
}

View File

@ -0,0 +1,257 @@
/*
* PROGRAM: Client/Server Common Code
* MODULE: FileObject.cpp
* DESCRIPTION: Wrapper class for platform IO
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#include "firebird.h"
#include "../FileObject.h"
using namespace Firebird;
Firebird::Mutex open_mutex;
void FileObject::open(int flags, int pflags) {
open_mutex.enter();
DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
DWORD filecreate = 0;
DWORD desiredAccess = 0;
switch (flags & (fo_rdonly | fo_wronly | fo_rdwr)) {
case fo_rdonly:
desiredAccess = GENERIC_READ;
break;
case fo_wronly:
desiredAccess = GENERIC_WRITE;
break;
default:
desiredAccess = GENERIC_READ | GENERIC_WRITE;
}
if (flags & fo_append) {
// This is going to be tricky. Need to use global named mutex to achieve
// multi-process happiness
string temp(filename.c_str());
for (string::size_type i = 0; i < temp.length(); i++)
switch (temp[i]) {
case '\\':
case '/':
case ':':
temp[i] = '_';
}
temp.append("_mutex");
append_mutex = CreateMutex(NULL, FALSE, temp.c_str());
if (append_mutex == NULL) {
append_mutex = INVALID_HANDLE_VALUE;
system_call_failed::raise("CreateMutex");
}
}
/*
* decode open/create method flags
*/
switch ( flags & (fo_creat | fo_excl | fo_trunc) ) {
case 0:
case fo_excl: // ignore EXCL w/o CREAT
filecreate = OPEN_EXISTING;
break;
case fo_creat:
filecreate = OPEN_ALWAYS;
break;
case fo_creat | fo_excl:
case fo_creat | fo_trunc | fo_excl:
filecreate = CREATE_NEW;
break;
case fo_trunc:
case fo_trunc | fo_excl: // ignore EXCL w/o CREAT
filecreate = TRUNCATE_EXISTING;
break;
case fo_creat | fo_trunc:
filecreate = CREATE_ALWAYS;
break;
default:
// this can't happen ... all cases are covered
fb_assert(false);
}
if (flags & fo_temporary)
flagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
if (flags & fo_short_lived)
flagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
if (flags & fo_sequential)
flagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
if (flags & fo_random)
flagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
file = CreateFile(filename.c_str(),
desiredAccess,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
filecreate,
flagsAndAttributes, NULL);
open_mutex.leave();
if (file == INVALID_HANDLE_VALUE)
fatal_exception::raiseFmt("Error (%d) opening file: %s", GetLastError(), filename.c_str());
}
FileObject::~FileObject() {
CloseHandle(file);
CloseHandle(append_mutex);
}
UINT64 FileObject::size() {
UINT64 nFileLen = 0;
if (file != INVALID_HANDLE_VALUE)
{
DWORD dwSizeHigh = 0;
DWORD dwSizeLow = 0;
dwSizeLow = GetFileSize(file, &dwSizeHigh);
nFileLen = (dwSizeHigh * (MAXDWORD + 1)) + dwSizeLow;
}
return nFileLen;
}
void FileObject::reopen()
{
CloseHandle(file);
if (append_mutex != INVALID_HANDLE_VALUE)
{
ReleaseMutex(append_mutex);
CloseHandle(append_mutex);
}
open(fo_rdwr | fo_append | fo_creat, 0);
FlushFileBuffers(file);
}
size_t FileObject::blockRead(void* buffer, size_t bytesToRead) {
DWORD bytesDone;
if (!ReadFile(file, buffer, bytesToRead, &bytesDone, NULL))
fatal_exception::raiseFmt("IO error (%d) reading file: %s",
GetLastError(),
filename.c_str());
return bytesDone;
}
void FileObject::blockWrite(const void* buffer, size_t bytesToWrite) {
if (append_mutex != INVALID_HANDLE_VALUE) {
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
system_call_failed::raise("WaitForSingleObject");
seek(0, so_from_end);
}
DWORD bytesDone;
if (!WriteFile(file, buffer, bytesToWrite, &bytesDone, NULL) ||
bytesDone != bytesToWrite)
{
if (append_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(append_mutex);
fatal_exception::raiseFmt("IO error (%d) writing file: %s",
GetLastError(),
filename.c_str());
}
if (append_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(append_mutex);
}
// Write data to header only if file is empty
void FileObject::writeHeader(const void* buffer, size_t bytesToWrite) {
if (append_mutex != INVALID_HANDLE_VALUE) {
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
system_call_failed::raise("WaitForSingleObject");
}
if (seek(0, so_from_end) != 0)
return;
DWORD bytesDone;
if (!WriteFile(file, buffer, bytesToWrite, &bytesDone, NULL) ||
bytesDone != bytesToWrite)
{
if (append_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(append_mutex);
fatal_exception::raiseFmt("IO error (%d) writing file: %s",
GetLastError(),
filename.c_str());
}
if (append_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(append_mutex);
}
bool FileObject::renameFile(const Firebird::PathName new_filename) {
if (append_mutex != INVALID_HANDLE_VALUE)
if (WaitForSingleObject(append_mutex, INFINITE) != WAIT_OBJECT_0)
system_call_failed::raise("WaitForSingleObject");
if (!MoveFile(filename.c_str(), new_filename.c_str())) {
DWORD rename_err = GetLastError();
if (rename_err == ERROR_ALREADY_EXISTS || rename_err == ERROR_FILE_NOT_FOUND) {
// Another process renames our file just now. Open new it.
reopen();
return false;
}
if (append_mutex != INVALID_HANDLE_VALUE)
ReleaseMutex(append_mutex);
fatal_exception::raiseFmt("IO error (%d) renaming file: %s",
rename_err,
filename.c_str());
}
else
reopen();
return true;
}
SINT64 FileObject::seek(SINT64 newOffset, SeekOrigin origin) {
LARGE_INTEGER offset;
offset.QuadPart = newOffset;
DWORD error;
DWORD moveMethod;
switch(origin) {
case so_from_beginning:
moveMethod = FILE_BEGIN;
break;
case so_from_current:
moveMethod = FILE_CURRENT;
break;
case so_from_end:
moveMethod = FILE_END;
break;
}
if ((offset.LowPart = SetFilePointer(file, offset.LowPart,
&offset.HighPart, moveMethod)) == INVALID_SET_FILE_POINTER
&&
(error = GetLastError()) != NO_ERROR)
{
fatal_exception::raiseFmt("IO error (%d) seeking file: %s",
error,
filename.c_str());
}
return offset.QuadPart;
}

View File

@ -0,0 +1,85 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: TracePluginImpl.h
* DESCRIPTION: Platform specifics (Win32)
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#include "firebird.h"
#include <windows.h>
#include "../platform.h"
#include "../common/classes/fb_tls.h"
TLS_DECLARE(char*, error_string);
const char* get_error_string()
{
return TLS_GET(error_string);
}
void set_error_string(const char* str)
{
char* org_str = TLS_GET(error_string);
if (org_str)
{
LocalFree(org_str);
TLS_SET(error_string, NULL);
}
if (str)
{
size_t len = strlen(str);
char* new_str = (char*) LocalAlloc(LMEM_FIXED, len + 1);
if (new_str)
{
memcpy(new_str, str, len + 1);
TLS_SET(error_string, new_str);
}
}
}
SLONG get_process_id()
{
return GetCurrentProcessId();
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved
)
{
if (fdwReason == DLL_THREAD_DETACH)
{
char* str = TLS_GET(error_string);
if (str)
{
LocalFree(str);
TLS_SET(error_string, NULL);
}
}
return TRUE;
}

View File

@ -0,0 +1,71 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: paramtable.h
* DESCRIPTION: Definitions for configuration file parameters
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2008 Khorsun Vladyslav
*/
// The table with parameters used by Trace API
// User of this header is supposed to define:
// PATH_PARAMETER, STR_PARAMETER, BOOL_PARAMETER, UINT_PARAMETER
// DATABASE_PARAMS, SERVICE_PARAMS
PATH_PARAMETER(log_filename, "")
BOOL_PARAMETER(enabled, false)
UINT_PARAMETER(max_log_size, 0)
#ifdef DATABASE_PARAMS
STR_PARAMETER(include_filter, "")
STR_PARAMETER(exclude_filter, "")
BOOL_PARAMETER(log_connections, false)
UINT_PARAMETER(connection_id, 0)
BOOL_PARAMETER(log_transactions, false)
BOOL_PARAMETER(log_statement_prepare, false)
BOOL_PARAMETER(log_statement_free, false)
BOOL_PARAMETER(log_statement_start, false)
BOOL_PARAMETER(log_statement_finish, false)
BOOL_PARAMETER(log_procedure_start, false)
BOOL_PARAMETER(log_procedure_finish, false)
BOOL_PARAMETER(log_trigger_start, false)
BOOL_PARAMETER(log_trigger_finish, false)
BOOL_PARAMETER(print_plan, false)
BOOL_PARAMETER(print_perf, false)
BOOL_PARAMETER(log_context, false)
BOOL_PARAMETER(log_blr_requests, false)
BOOL_PARAMETER(print_blr, false)
BOOL_PARAMETER(log_dyn_requests, false)
BOOL_PARAMETER(print_dyn, false)
UINT_PARAMETER(max_sql_length, 300)
UINT_PARAMETER(max_blr_length, 500)
UINT_PARAMETER(max_dyn_length, 500)
UINT_PARAMETER(max_arg_length, 80)
UINT_PARAMETER(max_arg_count, 30)
UINT_PARAMETER(time_threshold, 100)
#endif
#ifdef SERVICE_PARAMS
BOOL_PARAMETER(log_services, false)
BOOL_PARAMETER(log_service_query, false)
#endif

View File

@ -0,0 +1,87 @@
/*
* PROGRAM: SQL Trace plugin
* MODULE: traceplugin.cpp
* DESCRIPTION: Exported entrypoints for the plugin
*
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* Software distributed under the License is distributed AS IS,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights
* and limitations under the License.
*
* The Original Code was created by Nickolay Samofatov
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2008 Khorsun Vladyslav
*/
#include "TraceConfiguration.h"
#include "TracePluginImpl.h"
extern "C" {
FB_DLL_EXPORT ntrace_boolean_t trace_create(TraceInitInfo* initInfo, const TracePlugin** plugin)
{
try
{
const char *dbname = initInfo->getDatabaseName();
TracePluginConfig config;
TraceCfgReader::readTraceConfiguration(
initInfo->getConfigText(),
dbname ? dbname : "",
config);
TraceConnection *connection = initInfo->getConnection();
if (!config.enabled ||
config.connection_id && connection && (connection->getConnectionID() != config.connection_id))
{
*plugin = NULL;
return true; // Plugin is not needed, no error happened.
}
TraceLogWriter *logWriter = initInfo->getLogWriter();
if (logWriter) {
config.log_filename = "";
}
*plugin = TracePluginImpl::createFullPlugin(config, initInfo);
return true; // Everything is ok, we created a plugin
}
catch(Firebird::Exception& ex)
{
try
{
// Create skeletal plugin object in order to return error to caller
*plugin = TracePluginImpl::createSkeletalPlugin();
// Stuff exception to error buffer now
TracePluginImpl::marshal_exception(ex);
}
catch(Firebird::Exception&)
{
// We faced total lack of luck here. Most probably this is
// out-of-memory error, but nothing we can tell to our caller
// about it.
*plugin = NULL;
}
return false;
}
}
} // extern "C"