mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 21:23:03 +01:00
Trace plugin
This commit is contained in:
parent
26bdd120e3
commit
130c67bf0f
258
src/utilities/ntrace/TraceConfiguration.cpp
Normal file
258
src/utilities/ntrace/TraceConfiguration.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
|
72
src/utilities/ntrace/TraceConfiguration.h
Normal file
72
src/utilities/ntrace/TraceConfiguration.h
Normal 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
|
86
src/utilities/ntrace/TracePluginConfig.h
Normal file
86
src/utilities/ntrace/TracePluginConfig.h
Normal 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
|
2154
src/utilities/ntrace/TracePluginImpl.cpp
Normal file
2154
src/utilities/ntrace/TracePluginImpl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
324
src/utilities/ntrace/TracePluginImpl.h
Normal file
324
src/utilities/ntrace/TracePluginImpl.h
Normal 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
|
152
src/utilities/ntrace/fbtrace.conf
Normal file
152
src/utilities/ntrace/fbtrace.conf
Normal 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>
|
173
src/utilities/ntrace/os/FileObject.h
Normal file
173
src/utilities/ntrace/os/FileObject.h
Normal 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
|
37
src/utilities/ntrace/os/platform.h
Normal file
37
src/utilities/ntrace/os/platform.h
Normal 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
|
179
src/utilities/ntrace/os/posix/FileObject.cpp
Normal file
179
src/utilities/ntrace/os/posix/FileObject.cpp
Normal 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;
|
||||
}
|
90
src/utilities/ntrace/os/posix/platform.cpp
Normal file
90
src/utilities/ntrace/os/posix/platform.cpp
Normal 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();
|
||||
}
|
257
src/utilities/ntrace/os/win32/FileObject.cpp
Normal file
257
src/utilities/ntrace/os/win32/FileObject.cpp
Normal 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;
|
||||
}
|
85
src/utilities/ntrace/os/win32/platform.cpp
Normal file
85
src/utilities/ntrace/os/win32/platform.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
71
src/utilities/ntrace/paramtable.h
Normal file
71
src/utilities/ntrace/paramtable.h
Normal 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
|
87
src/utilities/ntrace/traceplugin.cpp
Normal file
87
src/utilities/ntrace/traceplugin.cpp
Normal 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"
|
Loading…
Reference in New Issue
Block a user