diff --git a/builds/posix/make.shared.variables b/builds/posix/make.shared.variables
index 5074e5cf68..e11e9dd792 100644
--- a/builds/posix/make.shared.variables
+++ b/builds/posix/make.shared.variables
@@ -65,9 +65,13 @@ SecDbCache:= $(call makeObjects,auth,SecDbCache.cpp)
# Remote
+Remote_Trace:= $(call makeObjects,jrd/trace,TraceConfigStorage.cpp) \
+ $(call makeObjects,jrd/trace,TraceLog.cpp) \
+ $(call makeObjects,supplement/trace,TraceManager.cpp)
Remote_Common:= $(call dirObjects,remote) $(call dirObjects,auth/SecureRemotePassword)
Remote_Server:= $(call dirObjects,remote/server) $(call dirObjects,auth/SecureRemotePassword/server) \
- $(call makeObjects,jrd/replication,Config.cpp Utils.cpp) $(SecDbCache)
+ $(call makeObjects,jrd/replication,Config.cpp Utils.cpp) $(SecDbCache) \
+ $(Remote_Trace)
Remote_Client:= $(call dirObjects,remote/client) $(call dirObjects,auth/SecureRemotePassword/client) \
$(call makeObjects,auth/SecurityDatabase,LegacyClient.cpp) \
$(call dirObjects,plugins/crypt/arc4)
@@ -89,7 +93,8 @@ AllObjects += $(Profiler_Objects)
Engine_Objects:= $(call dirObjects,jrd) $(call dirObjects,dsql) $(call dirObjects,jrd/extds) \
$(call dirObjects,jrd/optimizer) $(call dirObjects,jrd/recsrc) $(call dirObjects,jrd/replication) \
$(call dirObjects,jrd/sys-packages) $(call dirObjects,jrd/trace) \
- $(call makeObjects,lock,lock.cpp)
+ $(call makeObjects,lock,lock.cpp) \
+ $(call dirObjects,supplement/trace)
Engine_Test_Objects:= $(call dirObjects,jrd/tests)
diff --git a/builds/win32/msvc15/engine_static.vcxproj b/builds/win32/msvc15/engine_static.vcxproj
index c326eb491a..b1ea69039f 100644
--- a/builds/win32/msvc15/engine_static.vcxproj
+++ b/builds/win32/msvc15/engine_static.vcxproj
@@ -172,9 +172,10 @@
-
+
+
@@ -358,7 +359,7 @@
-
+
diff --git a/builds/win32/msvc15/engine_static.vcxproj.filters b/builds/win32/msvc15/engine_static.vcxproj.filters
index b1e3589847..6bfa243f13 100644
--- a/builds/win32/msvc15/engine_static.vcxproj.filters
+++ b/builds/win32/msvc15/engine_static.vcxproj.filters
@@ -198,7 +198,7 @@
JRD files\Trace
-
+
JRD files\Trace
@@ -207,6 +207,9 @@
JRD files\Trace
+
+ JRD files\Trace
+
JRD files
@@ -656,7 +659,7 @@
Header files
-
+
Header files
diff --git a/builds/win32/msvc15/fbserver.vcxproj b/builds/win32/msvc15/fbserver.vcxproj
index 4c8003a4d4..c469d3b20a 100644
--- a/builds/win32/msvc15/fbserver.vcxproj
+++ b/builds/win32/msvc15/fbserver.vcxproj
@@ -205,6 +205,9 @@
+
+
+
@@ -231,4 +234,4 @@
-
\ No newline at end of file
+
diff --git a/builds/win32/msvc15/fbserver.vcxproj.filters b/builds/win32/msvc15/fbserver.vcxproj.filters
index d20a985e5f..dfca62c35a 100644
--- a/builds/win32/msvc15/fbserver.vcxproj.filters
+++ b/builds/win32/msvc15/fbserver.vcxproj.filters
@@ -34,6 +34,15 @@
Remote server
+
+ Remote server
+
+
+ Remote server
+
+
+ Remote server
+
AUTH files
@@ -68,4 +77,4 @@
AUTH files
-
\ No newline at end of file
+
diff --git a/src/dsql/DsqlCursor.cpp b/src/dsql/DsqlCursor.cpp
index 676a9d72f7..f1feb3ac82 100644
--- a/src/dsql/DsqlCursor.cpp
+++ b/src/dsql/DsqlCursor.cpp
@@ -23,7 +23,7 @@
#include "firebird.h"
#include "../common/classes/ClumpletWriter.h"
#include "../jrd/tra_proto.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceDSQLHelpers.h"
#include "../dsql/dsql_proto.h"
@@ -86,10 +86,10 @@ void DsqlCursor::close(thread_db* tdbb, DsqlCursor* cursor)
trace.fetch(true, ITracePlugin::RESULT_SUCCESS);
}
- if (dsqlRequest->req_traced && TraceManager::need_dsql_free(attachment))
+ if (dsqlRequest->req_traced && JrdTraceManager::need_dsql_free(attachment))
{
TraceSQLStatementImpl stmt(dsqlRequest, NULL);
- TraceManager::event_dsql_free(attachment, &stmt, DSQL_close);
+ JrdTraceManager::event_dsql_free(attachment, &stmt, DSQL_close);
}
JRD_unwind_request(tdbb, dsqlRequest->getRequest());
diff --git a/src/dsql/DsqlRequests.cpp b/src/dsql/DsqlRequests.cpp
index b9d0b2f4ca..9b242cc21e 100644
--- a/src/dsql/DsqlRequests.cpp
+++ b/src/dsql/DsqlRequests.cpp
@@ -200,11 +200,11 @@ void DsqlRequest::destroy(thread_db* tdbb, DsqlRequest* dsqlRequest)
}
Jrd::Attachment* att = dsqlRequest->req_dbb->dbb_attachment;
- const bool need_trace_free = dsqlRequest->req_traced && TraceManager::need_dsql_free(att);
+ const bool need_trace_free = dsqlRequest->req_traced && JrdTraceManager::need_dsql_free(att);
if (need_trace_free)
{
TraceSQLStatementImpl stmt(dsqlRequest, NULL);
- TraceManager::event_dsql_free(att, &stmt, DSQL_drop);
+ JrdTraceManager::event_dsql_free(att, &stmt, DSQL_drop);
}
if (dsqlRequest->req_cursor_name.hasData())
@@ -818,7 +818,7 @@ void DsqlDmlRequest::executeReceiveWithRestarts(thread_db* tdbb, jrd_tra** traHa
"\tQuery:\n%s\n", numTries, request->getStatement()->sqlText->c_str() );
}
- TraceManager::event_dsql_restart(req_dbb->dbb_attachment, req_transaction, this, numTries);
+ JrdTraceManager::event_dsql_restart(req_dbb->dbb_attachment, req_transaction, this, numTries);
// When restart we must execute query
exec = true;
diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp
index 67a200fd27..d4f16085dd 100644
--- a/src/dsql/ExprNodes.cpp
+++ b/src/dsql/ExprNodes.cpp
@@ -61,7 +61,7 @@
#include "../dsql/DSqlDataTypeUtil.h"
#include "../jrd/DataTypeUtil.h"
#include "../jrd/Collation.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceObjects.h"
#include "../jrd/trace/TraceJrdHelpers.h"
diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp
index e6f9351f1d..a70dcaeb21 100644
--- a/src/dsql/StmtNodes.cpp
+++ b/src/dsql/StmtNodes.cpp
@@ -41,7 +41,7 @@
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/replication/Publisher.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/dfw_proto.h"
diff --git a/src/dsql/dsql.cpp b/src/dsql/dsql.cpp
index 18ad503847..60dbf2656a 100644
--- a/src/dsql/dsql.cpp
+++ b/src/dsql/dsql.cpp
@@ -66,7 +66,7 @@
#include "../jrd/optimizer/Optimizer.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/replication/Publisher.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceDSQLHelpers.h"
#include "../common/classes/init.h"
#include "../common/utils_proto.h"
diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp
index a0ea8190e9..fb6426bf0d 100644
--- a/src/jrd/Attachment.cpp
+++ b/src/jrd/Attachment.cpp
@@ -28,7 +28,7 @@
#include "../jrd/Database.h"
#include "../jrd/Function.h"
#include "../jrd/nbak.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/PreparedStatement.h"
#include "../jrd/tra.h"
#include "../jrd/intl.h"
@@ -252,7 +252,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider
att_ext_connection(NULL),
att_ext_parent(NULL),
att_ext_call_depth(0),
- att_trace_manager(FB_NEW_POOL(*att_pool) TraceManager(this)),
+ att_trace_manager(FB_NEW_POOL(*att_pool) JrdTraceManager(this)),
att_bindings(*pool),
att_dest_bind(&att_bindings),
att_original_timezone(TimeZoneUtil::getSystemTimeZone()),
diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h
index 7771cf58ef..97c204ae0a 100644
--- a/src/jrd/Attachment.h
+++ b/src/jrd/Attachment.h
@@ -92,7 +92,7 @@ namespace Jrd
class jrd_fld;
class dsql_dbb;
class PreparedStatement;
- class TraceManager;
+ class JrdTraceManager;
template class vec;
class jrd_rel;
class jrd_prc;
@@ -636,7 +636,7 @@ public:
EDS::Connection* att_ext_connection; // external connection executed by this attachment
EDS::Connection* att_ext_parent; // external connection, parent of this attachment
ULONG att_ext_call_depth; // external connection call depth, 0 for user attachment
- TraceManager* att_trace_manager; // Trace API manager
+ JrdTraceManager* att_trace_manager; // Trace API manager
CoercionArray att_bindings;
CoercionArray* att_dest_bind;
diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp
index b32c116cc5..657ccf5b7c 100644
--- a/src/jrd/SysFunction.cpp
+++ b/src/jrd/SysFunction.cpp
@@ -54,7 +54,7 @@
#include "../jrd/scl_proto.h"
#include "../common/os/guid.h"
#include "../jrd/license.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceObjects.h"
#include "../jrd/Collation.h"
#include "../common/classes/FpeControl.h"
diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp
index e2bc658639..2336183a2a 100644
--- a/src/jrd/exe.cpp
+++ b/src/jrd/exe.cpp
@@ -102,7 +102,7 @@
#include "../jrd/rpb_chain.h"
#include "../jrd/RecordSourceNodes.h"
#include "../jrd/VirtualTable.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../dsql/Nodes.h"
diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp
index a52f165914..6c9c34d4f7 100644
--- a/src/jrd/jrd.cpp
+++ b/src/jrd/jrd.cpp
@@ -120,7 +120,7 @@
#include "../common/db_alias.h"
#include "../jrd/replication/Publisher.h"
#include "../jrd/replication/Applier.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceObjects.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../jrd/IntlManager.h"
@@ -1565,7 +1565,7 @@ static void trace_failed_attach(const char* filename, const DatabaseOptions& opt
const char* func = flags & UNWIND_CREATE ? "JProvider::createDatabase" : "JProvider::attachDatabase";
// Perform actual trace
- TraceManager tempMgr(origFilename, callback, flags & UNWIND_NEW);
+ JrdTraceManager tempMgr(origFilename, callback, flags & UNWIND_NEW);
if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ATTACH))
tempMgr.event_attach(&conn, flags & UNWIND_CREATE, result);
@@ -4696,9 +4696,9 @@ void JProvider::shutdown(CheckStatusWrapper* status, unsigned int timeout, const
shutdown_thread(NULL);
}
- // Do not put it into separate shutdown thread - during shutdown of TraceManager
+ // Do not put it into separate shutdown thread - during shutdown of JrdTraceManager
// PluginManager wants to lock a mutex, which is sometimes already locked in current thread
- TraceManager::shutdown();
+ JrdTraceManager::shutdown();
Mapping::shutdownIpc();
}
@@ -8701,7 +8701,7 @@ static void unwindAttach(thread_db* tdbb, const char* filename, const Exception&
try
{
const auto att = tdbb->getAttachment();
- TraceManager* traceManager = att ? att->att_trace_manager : nullptr;
+ JrdTraceManager* traceManager = att ? att->att_trace_manager : nullptr;
if (att && traceManager && traceManager->isActive())
{
TraceConnectionImpl conn(att);
@@ -8766,7 +8766,7 @@ static void unwindAttach(thread_db* tdbb, const char* filename, const Exception&
sAtt->manualLock(flags);
if (sAtt->getHandle())
{
- TraceManager* traceManager = attachment->att_trace_manager;
+ JrdTraceManager* traceManager = attachment->att_trace_manager;
TraceConnectionImpl conn(attachment);
if (traceManager->needs(ITraceFactory::TRACE_EVENT_DETACH))
diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h
index a4e5257948..b70ce31a04 100644
--- a/src/jrd/jrd.h
+++ b/src/jrd/jrd.h
@@ -129,7 +129,7 @@ class Parameter;
class jrd_fld;
class dsql_dbb;
class PreparedStatement;
-class TraceManager;
+class JrdTraceManager;
class MessageNode;
diff --git a/src/jrd/recsrc/ProcedureScan.cpp b/src/jrd/recsrc/ProcedureScan.cpp
index a351d4a99d..cb0b9dc376 100644
--- a/src/jrd/recsrc/ProcedureScan.cpp
+++ b/src/jrd/recsrc/ProcedureScan.cpp
@@ -27,7 +27,7 @@
#include "../jrd/exe_proto.h"
#include "../jrd/mov_proto.h"
#include "../jrd/vio_proto.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../jrd/optimizer/Optimizer.h"
diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp
index 1f87f10634..948fa33f97 100644
--- a/src/jrd/svc.cpp
+++ b/src/jrd/svc.cpp
@@ -56,7 +56,7 @@
#include "../common/db_alias.h"
#include "../jrd/scl.h"
#include "../common/msg_encode.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceObjects.h"
#include "../jrd/EngineInterface.h"
#include "../jrd/Mapping.h"
@@ -739,7 +739,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
#ifdef DEV_BUILD
if (svc_debug)
{
- svc_trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) TraceManager(this);
+ svc_trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) JrdTraceManager(this);
svc_user_flag = SVC_user_dba;
return;
}
@@ -803,11 +803,11 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
svc_perm_sw = switches;
svc_user_flag = user_flag;
- svc_trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) TraceManager(this);
+ svc_trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) JrdTraceManager(this);
} // try
catch (const Firebird::Exception& ex)
{
- TraceManager* trace_manager = NULL;
+ JrdTraceManager* trace_manager = NULL;
FbLocalStatus status_vector;
try
@@ -817,7 +817,7 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
if (hasTrace)
trace_manager = svc_trace_manager;
else
- trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) TraceManager(this);
+ trace_manager = FB_NEW_POOL(*getDefaultMemoryPool()) JrdTraceManager(this);
if (trace_manager->needs(ITraceFactory::TRACE_EVENT_SERVICE_ATTACH))
{
diff --git a/src/jrd/svc.h b/src/jrd/svc.h
index 66cf96790f..ea38b85dc9 100644
--- a/src/jrd/svc.h
+++ b/src/jrd/svc.h
@@ -102,7 +102,7 @@ const int SVC_cmd_line = 0x80;
// forward decl.
class thread_db;
-class TraceManager;
+class JrdTraceManager;
// Service manager
class Service : public Firebird::UtilSvc, public TypedHandle
@@ -151,7 +151,7 @@ public:
Firebird::ICryptKeyCallback* getCryptCallback() override;
int getParallelWorkers() override { return svc_parallel_workers; }
- TraceManager* getTraceManager()
+ virtual JrdTraceManager* getTraceManager()
{
return svc_trace_manager;
}
@@ -336,7 +336,7 @@ private:
Firebird::string svc_remote_process;
SLONG svc_remote_pid;
- TraceManager* svc_trace_manager;
+ JrdTraceManager* svc_trace_manager;
Firebird::ICryptKeyCallback* svc_crypt_callback;
public:
diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp
index e9d73cec7c..428835d41f 100644
--- a/src/jrd/tra.cpp
+++ b/src/jrd/tra.cpp
@@ -69,7 +69,7 @@
#include "../dsql/dsql_proto.h"
#include "../common/StatusArg.h"
#include "../jrd/replication/Publisher.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../jrd/Function.h"
#include "../jrd/Collation.h"
@@ -4183,7 +4183,7 @@ TraceSweepEvent::TraceSweepEvent(thread_db* tdbb)
m_sweep_info.getOST(),
m_sweep_info.getNext());
- TraceManager* trace_mgr = att->att_trace_manager;
+ JrdTraceManager* trace_mgr = att->att_trace_manager;
m_start_clock = fb_utils::query_performance_counter();
m_need_trace = trace_mgr->needs(ITraceFactory::TRACE_EVENT_SWEEP);
@@ -4250,7 +4250,7 @@ void TraceSweepEvent::endSweepRelation(jrd_rel* relation)
m_sweep_info.setPerf(stats.getPerf());
TraceConnectionImpl conn(att);
- TraceManager* trace_mgr = att->att_trace_manager;
+ JrdTraceManager* trace_mgr = att->att_trace_manager;
trace_mgr->event_sweep(&conn, &m_sweep_info, ITracePlugin::SWEEP_STATE_PROGRESS);
}
@@ -4282,7 +4282,7 @@ void TraceSweepEvent::report(ntrace_process_state_t state)
return;
Database* dbb = m_tdbb->getDatabase();
- TraceManager* trace_mgr = att->att_trace_manager;
+ JrdTraceManager* trace_mgr = att->att_trace_manager;
TraceConnectionImpl conn(att);
diff --git a/src/jrd/trace/TraceConfigStorage.cpp b/src/jrd/trace/TraceConfigStorage.cpp
index 6dd2280999..9ac6e5005e 100644
--- a/src/jrd/trace/TraceConfigStorage.cpp
+++ b/src/jrd/trace/TraceConfigStorage.cpp
@@ -33,10 +33,12 @@
#include "../../jrd/err_proto.h"
#include "../../common/isc_proto.h"
#include "../../common/isc_s_proto.h"
-#include "../../jrd/jrd.h"
#include "../../common/os/path_utils.h"
#include "../../common/os/os_utils.h"
#include "../../jrd/trace/TraceConfigStorage.h"
+#include "../../common/file_params.h"
+#include "../../common/config/config.h"
+#include "../../common/status.h"
#ifdef HAVE_UNISTD_H
#include
diff --git a/src/jrd/trace/TraceDSQLHelpers.h b/src/jrd/trace/TraceDSQLHelpers.h
index 8561b321c3..f180363cc8 100644
--- a/src/jrd/trace/TraceDSQLHelpers.h
+++ b/src/jrd/trace/TraceDSQLHelpers.h
@@ -28,7 +28,7 @@
#ifndef JRD_TRACE_DSQL_HELPERS_H
#define JRD_TRACE_DSQL_HELPERS_H
-#include "../../jrd/trace/TraceManager.h"
+#include "../../supplement/trace/JrdTraceManager.h"
#include "../../jrd/trace/TraceObjects.h"
namespace Jrd {
@@ -47,7 +47,7 @@ public:
m_string_len(string_length),
m_string(string)
{
- m_need_trace = !isInternal && TraceManager::need_dsql_prepare(m_attachment);
+ m_need_trace = !isInternal && JrdTraceManager::need_dsql_prepare(m_attachment);
if (!m_need_trace)
return;
@@ -86,14 +86,14 @@ public:
if ((result == ITracePlugin::RESULT_SUCCESS) && m_request)
{
TraceSQLStatementImpl stmt(m_request, NULL);
- TraceManager::event_dsql_prepare(m_attachment, m_transaction, &stmt, millis, result);
+ JrdTraceManager::event_dsql_prepare(m_attachment, m_transaction, &stmt, millis, result);
}
else
{
Firebird::string str(*getDefaultMemoryPool(), m_string, m_string_len);
TraceFailedSQLStatement stmt(str);
- TraceManager::event_dsql_prepare(m_attachment, m_transaction, &stmt, millis, result);
+ JrdTraceManager::event_dsql_prepare(m_attachment, m_transaction, &stmt, millis, result);
}
}
@@ -115,13 +115,13 @@ public:
m_attachment(attachment),
m_dsqlRequest(dsqlRequest)
{
- m_need_trace = m_dsqlRequest->req_traced && TraceManager::need_dsql_execute(m_attachment);
+ m_need_trace = m_dsqlRequest->req_traced && JrdTraceManager::need_dsql_execute(m_attachment);
if (!m_need_trace)
return;
{ // scope
TraceSQLStatementImpl stmt(dsqlRequest, NULL);
- TraceManager::event_dsql_execute(m_attachment, dsqlRequest->req_transaction, &stmt, true,
+ JrdTraceManager::event_dsql_execute(m_attachment, dsqlRequest->req_transaction, &stmt, true,
ITracePlugin::RESULT_SUCCESS);
}
@@ -157,7 +157,7 @@ public:
m_dsqlRequest->req_fetch_rowcount);
TraceSQLStatementImpl stmt(m_dsqlRequest, stats.getPerf());
- TraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction, &stmt, false, result);
+ JrdTraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction, &stmt, false, result);
m_dsqlRequest->req_fetch_baseline = NULL;
}
@@ -181,7 +181,7 @@ public:
m_attachment(attachment),
m_dsqlRequest(request)
{
- m_need_trace = m_dsqlRequest->req_traced && TraceManager::need_dsql_execute(m_attachment) &&
+ m_need_trace = m_dsqlRequest->req_traced && JrdTraceManager::need_dsql_execute(m_attachment) &&
m_dsqlRequest->getRequest() && (m_dsqlRequest->getRequest()->req_flags & req_active);
if (!m_need_trace)
@@ -217,7 +217,7 @@ public:
TraceSQLStatementImpl stmt(m_dsqlRequest, stats.getPerf());
- TraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction,
+ JrdTraceManager::event_dsql_execute(m_attachment, m_dsqlRequest->req_transaction,
&stmt, false, result);
m_dsqlRequest->req_fetch_elapsed = 0;
diff --git a/src/jrd/trace/TraceJrdHelpers.h b/src/jrd/trace/TraceJrdHelpers.h
index 3a4614c462..21b803ae58 100644
--- a/src/jrd/trace/TraceJrdHelpers.h
+++ b/src/jrd/trace/TraceJrdHelpers.h
@@ -29,7 +29,7 @@
#define JRD_TRACE_JRD_HELPERS_H
#include "../../jrd/jrd.h"
-#include "../../jrd/trace/TraceManager.h"
+#include "../../supplement/trace/JrdTraceManager.h"
#include "../../jrd/trace/TraceObjects.h"
namespace Jrd {
@@ -616,7 +616,7 @@ public:
m_start_clock = (fb_utils::query_performance_counter() - m_start_clock) * 1000 /
fb_utils::query_performance_frequency();
- TraceManager* trace_mgr = m_tdbb->getAttachment()->att_trace_manager;
+ JrdTraceManager* trace_mgr = m_tdbb->getAttachment()->att_trace_manager;
TraceConnectionImpl conn(m_tdbb->getAttachment());
TraceTransactionImpl tran(m_tdbb->getTransaction());
@@ -691,7 +691,7 @@ public:
TraceTransactionImpl tran(m_tdbb->getTransaction());
TraceBLRStatementImpl stmt(m_request->getStatement(), stats.getPerf());
- TraceManager* trace_mgr = m_tdbb->getAttachment()->att_trace_manager;
+ JrdTraceManager* trace_mgr = m_tdbb->getAttachment()->att_trace_manager;
trace_mgr->event_blr_execute(&conn, &tran, &stmt, result);
m_request->req_fetch_baseline = NULL;
diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp
index dc6bab8889..8ff0dba16b 100644
--- a/src/jrd/trace/TraceObjects.cpp
+++ b/src/jrd/trace/TraceObjects.cpp
@@ -29,7 +29,7 @@
#include "../../common/classes/auto.h"
#include "../../common/utils_proto.h"
-#include "../../jrd/trace/TraceManager.h"
+#include "../../supplement/trace/JrdTraceManager.h"
#include "../../jrd/trace/TraceLog.h"
#include "../../jrd/trace/TraceObjects.h"
#include "../../common/isc_proto.h"
@@ -475,73 +475,6 @@ void TraceDscFromMsg::fillParams()
}
-/// TraceLogWriterImpl
-
-class TraceLogWriterImpl final :
- public RefCntIface >
-{
-public:
- TraceLogWriterImpl(const TraceSession& session) :
- m_log(getPool(), session.ses_logfile, false),
- m_sesId(session.ses_id)
- {
- string s;
- s.printf("\n--- Session %d is suspended as its log is full ---\n", session.ses_id);
- m_log.setFullMsg(s.c_str());
- }
-
- // TraceLogWriter implementation
- FB_SIZE_T write(const void* buf, FB_SIZE_T size);
- FB_SIZE_T write_s(CheckStatusWrapper* status, const void* buf, FB_SIZE_T size);
-
-private:
- TraceLog m_log;
- ULONG m_sesId;
-};
-
-FB_SIZE_T TraceLogWriterImpl::write(const void* buf, FB_SIZE_T size)
-{
- const FB_SIZE_T written = m_log.write(buf, size);
- if (written == size)
- return size;
-
- if (!m_log.isFull())
- return written;
-
- ConfigStorage* storage = TraceManager::getStorage();
- StorageGuard guard(storage);
-
- TraceSession session(*getDefaultMemoryPool());
- session.ses_id = m_sesId;
- if (storage->getSession(session, ConfigStorage::FLAGS))
- {
- if (!(session.ses_flags & trs_log_full))
- {
- // suspend session
- session.ses_flags |= trs_log_full;
- storage->updateFlags(session);
- }
- }
-
- // report successful write
- return size;
-}
-
-FB_SIZE_T TraceLogWriterImpl::write_s(CheckStatusWrapper* status, const void* buf, FB_SIZE_T size)
-{
- try
- {
- return write(buf, size);
- }
- catch (Exception &ex)
- {
- ex.stuffException(status);
- }
-
- return 0;
-}
-
-
/// TraceInitInfoImpl
const char* TraceInitInfoImpl::getFirebirdRootDirectory()
@@ -553,7 +486,7 @@ ITraceLogWriter* TraceInitInfoImpl::getLogWriter()
{
if (!m_logWriter && !m_session.ses_logfile.empty())
{
- m_logWriter = FB_NEW TraceLogWriterImpl(m_session);
+ m_logWriter = TraceManager::createSessionLogWriter(m_session);
}
if (m_logWriter)
{
diff --git a/src/jrd/trace/TraceService.cpp b/src/jrd/trace/TraceService.cpp
index 1da97d5634..18ce427f08 100644
--- a/src/jrd/trace/TraceService.cpp
+++ b/src/jrd/trace/TraceService.cpp
@@ -37,7 +37,7 @@
#include "../../jrd/svc.h"
#include "../../common/os/guid.h"
#include "../../jrd/trace/TraceLog.h"
-#include "../../jrd/trace/TraceManager.h"
+#include "../../supplement/trace/JrdTraceManager.h"
#include "../../jrd/trace/TraceService.h"
#include "../../jrd/scl.h"
#include "../../jrd/Mapping.h"
@@ -103,7 +103,7 @@ void TraceSvcJrd::setAttachInfo(const string& /*svc_name*/, const string& user,
void TraceSvcJrd::startSession(TraceSession& session, bool interactive)
{
- if (!TraceManager::pluginsCount())
+ if (!JrdTraceManager::pluginsCount())
{
m_svc.printf(false, "Can not start trace session. There are no trace plugins loaded\n");
return;
@@ -148,7 +148,7 @@ void TraceSvcJrd::stopSession(ULONG id)
{
m_svc.started();
- ConfigStorage* storage = TraceManager::getStorage();
+ ConfigStorage* storage = JrdTraceManager::getStorage();
StorageGuard guard(storage);
TraceSession session(*getDefaultMemoryPool());
@@ -187,7 +187,7 @@ void TraceSvcJrd::setActive(ULONG id, bool active)
bool TraceSvcJrd::changeFlags(ULONG id, int setFlags, int clearFlags)
{
- ConfigStorage* storage = TraceManager::getStorage();
+ ConfigStorage* storage = JrdTraceManager::getStorage();
StorageGuard guard(storage);
TraceSession session(*getDefaultMemoryPool());
@@ -219,7 +219,7 @@ void TraceSvcJrd::listSessions()
{
m_svc.started();
- ConfigStorage* storage = TraceManager::getStorage();
+ ConfigStorage* storage = JrdTraceManager::getStorage();
StorageGuard guard(storage);
storage->restart();
@@ -307,7 +307,7 @@ void TraceSvcJrd::readSession(TraceSession& session)
bool TraceSvcJrd::checkAliveAndFlags(ULONG sesId, int& flags)
{
- ConfigStorage* storage = TraceManager::getStorage();
+ ConfigStorage* storage = JrdTraceManager::getStorage();
bool alive = (m_chg_number == storage->getChangeNumber());
if (!alive)
diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp
index 44640038fa..087f280ad6 100644
--- a/src/jrd/vio.cpp
+++ b/src/jrd/vio.cpp
@@ -88,7 +88,7 @@
#include "../common/StatusArg.h"
#include "../jrd/GarbageCollector.h"
#include "../jrd/ProfilerManager.h"
-#include "../jrd/trace/TraceManager.h"
+#include "../supplement/trace/JrdTraceManager.h"
#include "../jrd/trace/TraceJrdHelpers.h"
#include "../common/Task.h"
#include "../jrd/WorkerAttachment.h"
diff --git a/src/remote/server/server.cpp b/src/remote/server/server.cpp
index 8d62159283..cfb30d1e0f 100644
--- a/src/remote/server/server.cpp
+++ b/src/remote/server/server.cpp
@@ -75,6 +75,13 @@
#include "../common/os/os_utils.h"
#include "../common/security.h"
+#include "../supplement/trace/TraceManager.h"
+#include "../common/db_alias.h"
+#ifdef WIN_NT
+#include
+#define getpid _getpid
+#endif
+
using namespace Firebird;
@@ -431,6 +438,151 @@ public:
}
};
+
+// For Trace
+
+class TraceFailedAuthImpl :
+ public Firebird::AutoIface >
+{
+public:
+ TraceFailedAuthImpl() :
+ filename(NULL),
+ userName(*getDefaultMemoryPool()),
+ roleName(*getDefaultMemoryPool()),
+ charSet(*getDefaultMemoryPool()),
+ networkProtocol(*getDefaultMemoryPool()),
+ remoteAddress(*getDefaultMemoryPool()),
+ remotePid(0),
+ processName(*getDefaultMemoryPool()),
+ hasUtf8(false)
+ { }
+
+ void setData(const UCHAR* dpb, USHORT dpb_length)
+ {
+ ClumpletReader rdr(ClumpletReader::dpbList, dpb, dpb_length);
+ dumpAuthBlock("TraceFailedAuthImpl::setData()", &rdr, isc_dpb_auth_block);
+
+ hasUtf8 = rdr.find(isc_dpb_utf8_filename);
+
+ for (rdr.rewind(); !rdr.isEof(); rdr.moveNext())
+ {
+ switch (rdr.getClumpTag())
+ {
+ case isc_dpb_user_name:
+ getString(rdr, userName);
+ break;
+
+ case isc_dpb_sql_role_name:
+ getString(rdr, roleName);
+ break;
+
+ case isc_dpb_set_db_charset:
+ getString(rdr, charSet);
+ fb_utils::dpbItemUpper(charSet);
+ break;
+
+ case isc_dpb_address_path:
+ {
+ ClumpletReader address_stack(ClumpletReader::UnTagged,
+ rdr.getBytes(), rdr.getClumpLength());
+ while (!address_stack.isEof())
+ {
+ if (address_stack.getClumpTag() != isc_dpb_address)
+ {
+ address_stack.moveNext();
+ continue;
+ }
+ ClumpletReader address(ClumpletReader::UnTagged,
+ address_stack.getBytes(), address_stack.getClumpLength());
+ while (!address.isEof())
+ {
+ switch (address.getClumpTag())
+ {
+ case isc_dpb_addr_protocol:
+ address.getString(networkProtocol);
+ break;
+ case isc_dpb_addr_endpoint:
+ address.getString(remoteAddress);
+ break;
+ default:
+ break;
+ }
+
+ address.moveNext();
+ }
+ break; // While
+ }
+ break; // Case
+ }
+
+ case isc_dpb_process_id:
+ remotePid = rdr.getInt();
+ break;
+
+ case isc_dpb_process_name:
+ getPath(rdr, processName);
+ break;
+ }
+ }
+ }
+
+ bool hasUtf8InDpb()
+ {
+ return hasUtf8;
+ }
+
+ void setFilename(const char* filename)
+ {
+ this->filename = filename;
+ }
+
+ unsigned getKind() { return KIND_DATABASE; };
+ int getProcessID() { return getpid(); }
+ const char* getUserName() { return userName.c_str(); }
+ const char* getRoleName() { return roleName.c_str(); }
+ const char* getCharSet() { return charSet.c_str(); }
+ const char* getRemoteProtocol() { return networkProtocol.c_str(); }
+ const char* getRemoteAddress() { return remoteAddress.c_str(); }
+ int getRemoteProcessID() { return remotePid; }
+ const char* getRemoteProcessName() { return processName.c_str(); }
+
+ // TraceDatabaseConnection implementation
+ ISC_INT64 getConnectionID() { return 0; }
+ const char* getDatabaseName() { return filename; }
+
+private:
+ void getPath(ClumpletReader& reader, PathName& s)
+ {
+ reader.getPath(s);
+ if (!hasUtf8)
+ ISC_systemToUtf8(s);
+ ISC_unescape(s);
+ }
+
+ void getString(ClumpletReader& reader, string& s)
+ {
+ reader.getString(s);
+ if (!hasUtf8)
+ ISC_systemToUtf8(s);
+ ISC_unescape(s);
+ }
+
+ const char* filename;
+ string userName;
+ string roleName;
+ string charSet;
+ string networkProtocol;
+ string remoteAddress;
+ SLONG remotePid;
+ PathName processName;
+ bool hasUtf8;
+};
+
+void traceFailedConnection(const rem_port* port, const char* dbPath,
+ const string& userName, ntrace_result_t attResult);
+
+// !Trace
+
GlobalPtr usernameFailedLogins;
GlobalPtr remoteFailedLogins;
bool server_shutdown = false;
@@ -510,12 +662,13 @@ public:
virtual void accept(PACKET* send, Auth::WriterImplementation* authBlock) = 0;
ServerAuth(ClumpletReader* aPb, const ParametersSet& aTags,
- rem_port* port, bool multiPartData = false)
+ rem_port* port, bool multiPartData = false, const PathName db = "")
: authItr(NULL),
userName(getPool()),
authServer(NULL),
tags(&aTags),
hopsCount(0),
+ dbName(getPool(), db),
authPort(port)
{
if (!authPort->port_srv_auth_block)
@@ -603,6 +756,11 @@ public:
}
}
+ void saveForTrace(const PathName& db)
+ {
+ dbName = db;
+ }
+
~ServerAuth()
{ }
@@ -641,6 +799,8 @@ public:
}
}
+ int authResult = IAuth::AUTH_FAILED;
+
while (authItr && working && authItr->hasData())
{
if (!authServer)
@@ -753,6 +913,11 @@ public:
// no success - perform failure processing
loginFail(userName, authPort->getRemoteId());
+ if (authResult != IAuth::AUTH_SUCCESS)
+ {
+ traceFailedConnection(authPort, dbName.c_str(), userName, ITracePlugin::RESULT_UNAUTHORIZED);
+ }
+
if (st.hasData())
{
switch (st.getErrors()[1])
@@ -784,6 +949,7 @@ private:
unsigned int hopsCount;
protected:
+ PathName dbName;
rem_port* authPort;
};
@@ -792,8 +958,7 @@ class DatabaseAuth : public ServerAuth
{
public:
DatabaseAuth(rem_port* port, const PathName& db, ClumpletWriter* dpb, P_OP op)
- : ServerAuth(dpb, dpbParam, port),
- dbName(getPool(), db),
+ : ServerAuth(dpb, dpbParam, port, false, db),
pb(dpb),
operation(op)
{ }
@@ -801,7 +966,6 @@ public:
void accept(PACKET* send, Auth::WriterImplementation* authBlock);
private:
- PathName dbName;
AutoPtr pb;
P_OP operation;
};
@@ -1247,6 +1411,46 @@ inline bool bad_service(IStatus* status_vector, Rdb* rdb)
}
+namespace {
+
+void traceFailedConnection(const rem_port* port, const char* dbPath, const string& userName, ntrace_result_t attResult)
+{
+ ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
+ dpb.insertString(isc_dpb_user_name, userName.c_str(), userName.length());
+ addClumplets(&dpb, dpbParam, port);
+
+ TraceFailedAuthImpl connection;
+ connection.setData(dpb.getBuffer(), dpb.getBufferLength());
+
+ Firebird::PathName originalPath(dbPath);
+ Firebird::PathName expandedName;
+ RefPtr config;
+ // Resolve given alias name
+
+ if (!connection.hasUtf8InDpb())
+ ISC_systemToUtf8(originalPath);
+
+ ISC_unescape(originalPath);
+
+ bool is_alias = expandDatabaseName(originalPath, expandedName, &config);
+ if (!is_alias)
+ {
+ expandedName = originalPath;
+ }
+
+ connection.setFilename(expandedName.c_str());
+
+ TraceManager tempMgr(&connection, expandedName.c_str());
+ tempMgr.initServerTrace();
+ if (tempMgr.needs(ITraceFactory::TRACE_EVENT_ATTACH))
+ {
+ connection.setFilename(originalPath.c_str()); // Write alias
+ tempMgr.event_attach(&connection, false, attResult);
+ }
+}
+
+} // !namespace
+
class Worker
{
public:
@@ -1995,6 +2199,7 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
connect->p_cnct_user_id.cstr_address,
connect->p_cnct_user_id.cstr_length);
+ PathName bkDbName;
if (accepted)
{
// Setup correct configuration for port
@@ -2013,6 +2218,7 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
if (version >= PROTOCOL_VERSION13)
{
ConnectAuth* cnctAuth = FB_NEW ConnectAuth(port, id);
+ cnctAuth->saveForTrace(bkDbName);
port->port_srv_auth = cnctAuth;
if (port->port_srv_auth->authenticate(send, ServerAuth::AUTH_COND_ACCEPT))
{
@@ -2127,9 +2333,15 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
// Send off out gracious acceptance or flag rejection
if (!accepted)
{
+ ntrace_result_t connectResult = ITracePlugin::RESULT_UNAUTHORIZED;
+
HANDSHAKE_DEBUG(fprintf(stderr, "!accepted, sending reject\n"));
+
if (status.getState() & Firebird::IStatus::STATE_ERRORS)
{
+ if (status.getErrors()[1] != isc_login)
+ connectResult = ITracePlugin::RESULT_FAILED;
+
switch (status.getErrors()[1])
{
case isc_missing_data_structures:
@@ -2151,7 +2363,12 @@ static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send)
}
}
else
+ {
port->send(send);
+ }
+
+ ::traceFailedConnection(port, bkDbName.c_str(), port->port_login, connectResult);
+
return false;
}
@@ -7236,6 +7453,7 @@ void Worker::shutdown()
static int shut_server(const int, const int, void*)
{
+ TraceManager::shutdown(); // This storage is separate from the jrd one
server_shutdown = true;
return 0;
}
diff --git a/src/jrd/trace/TraceManager.cpp b/src/supplement/trace/JrdTraceManager.cpp
similarity index 62%
rename from src/jrd/trace/TraceManager.cpp
rename to src/supplement/trace/JrdTraceManager.cpp
index 347b5465bf..768d83bbec 100644
--- a/src/jrd/trace/TraceManager.cpp
+++ b/src/supplement/trace/JrdTraceManager.cpp
@@ -1,6 +1,6 @@
/*
* PROGRAM: JRD Access Method
- * MODULE: TraceManager.cpp
+ * MODULE: JrdTraceManager.cpp
* DESCRIPTION: Trace API manager
*
* The contents of this file are subject to the Initial
@@ -28,7 +28,7 @@
#include "firebird.h"
-#include "../../jrd/trace/TraceManager.h"
+#include "JrdTraceManager.h"
#include "../../jrd/trace/TraceObjects.h"
#include "../../jrd/Mapping.h"
#include "../../common/os/path_utils.h"
@@ -50,79 +50,43 @@ namespace
namespace Jrd {
-GlobalPtr TraceManager::storageInstance;
-TraceManager::Factories* TraceManager::factories = NULL;
-GlobalPtr TraceManager::init_factories_lock;
-volatile bool TraceManager::init_factories;
-
-bool TraceManager::check_result(ITracePlugin* plugin, const char* module, const char* function,
- bool result)
-{
- if (result)
- return true;
-
- if (!plugin)
- {
- gds__log("Trace plugin %s returned error on call %s, "
- "did not create plugin and provided no additional details on reasons of failure",
- module, function);
- return false;
- }
-
- const char* errorStr = plugin->trace_get_error();
-
- if (!errorStr)
- {
- gds__log("Trace plugin %s returned error on call %s, "
- "but provided no additional details on reasons of failure", module, function);
- return false;
- }
-
- gds__log("Trace plugin %s returned error on call %s.\n\tError details: %s",
- module, function, errorStr);
- return false;
-}
-
-TraceManager::TraceManager(Attachment* in_att) :
+JrdTraceManager::JrdTraceManager(Attachment* in_att) :
+ TraceManager(NULL, *in_att->att_pool),
attachment(in_att),
service(NULL),
- filename(NULL),
callback(NULL),
- trace_sessions(*in_att->att_pool),
active(false)
{
init();
}
-TraceManager::TraceManager(Service* in_svc) :
+JrdTraceManager::JrdTraceManager(Service* in_svc) :
+ TraceManager(NULL, in_svc->getPool()),
attachment(NULL),
service(in_svc),
- filename(NULL),
callback(NULL),
- trace_sessions(in_svc->getPool()),
active(true)
{
init();
}
-TraceManager::TraceManager(const char* in_filename, ICryptKeyCallback* cb, bool failed) :
+JrdTraceManager::JrdTraceManager(const char* in_filename, ICryptKeyCallback* cb, bool failed) :
+ TraceManager(in_filename, *getDefaultMemoryPool()),
attachment(NULL),
service(NULL),
- filename(in_filename),
callback(cb),
- trace_sessions(*getDefaultMemoryPool()),
active(true),
failedAttach(failed)
{
init();
}
-TraceManager::~TraceManager()
+JrdTraceManager::~JrdTraceManager()
{
}
-void TraceManager::init()
+void JrdTraceManager::init()
{
// ensure storage is initialized
getStorage();
@@ -130,100 +94,19 @@ void TraceManager::init()
changeNumber = 0;
}
-void TraceManager::load_plugins()
-{
- // Initialize all trace needs to false
- trace_needs = 0;
-
- if (init_factories)
- return;
-
- WriteLockGuard guard(init_factories_lock, FB_FUNCTION);
- if (init_factories)
- return;
-
- factories = FB_NEW_POOL(*getDefaultMemoryPool()) TraceManager::Factories(*getDefaultMemoryPool());
- for (GetPlugins traceItr(IPluginManager::TYPE_TRACE); traceItr.hasData(); traceItr.next())
- {
- FactoryInfo info;
- info.factory = traceItr.plugin();
- info.factory->addRef();
- string name(traceItr.name());
- name.copyTo(info.name, sizeof(info.name));
- factories->add(info);
- }
-
- init_factories = true;
-}
-void TraceManager::shutdown()
-{
- if (init_factories)
- {
- WriteLockGuard guard(init_factories_lock, FB_FUNCTION);
-
- if (init_factories)
- {
- init_factories = false;
- delete factories;
- factories = NULL;
- }
- }
-
- getStorage()->shutdown();
-}
-
-
-void TraceManager::update_sessions()
+void JrdTraceManager::update_sessions()
{
// Let be inactive until database is creating
if (attachment && (attachment->att_database->dbb_flags & DBB_creating))
return;
MemoryPool& pool = *getDefaultMemoryPool();
- SortedArray > liveSessions(pool);
HalfStaticArray newSessions(pool);
- { // scope
- ConfigStorage* storage = getStorage();
+ reload_sessions_lists(newSessions);
- StorageGuard guard(storage);
- storage->restart();
-
- TraceSession session(pool);
- while (storage->getNextSession(session, ConfigStorage::FLAGS))
- {
- if ((session.ses_flags & trs_active) && !(session.ses_flags & trs_log_full))
- {
- FB_SIZE_T pos;
- if (trace_sessions.find(session.ses_id, pos))
- liveSessions.add(session.ses_id);
- else
- {
- storage->getSession(session, ConfigStorage::ALL);
- newSessions.add(FB_NEW_POOL(pool) TraceSession(pool, session));
- }
- }
- }
-
- changeNumber = storage->getChangeNumber();
- }
-
- // remove sessions not present in storage
- FB_SIZE_T i = 0;
- while (i < trace_sessions.getCount())
- {
- FB_SIZE_T pos;
- if (liveSessions.find(trace_sessions[i].ses_id, pos)) {
- i++;
- }
- else
- {
- trace_sessions[i].plugin->release();
- trace_sessions.remove(i);
- }
- }
// add new sessions
new_needs = trace_needs;
@@ -246,7 +129,7 @@ void TraceManager::update_sessions()
}
}
-void TraceManager::update_session(const TraceSession& session)
+void JrdTraceManager::update_session(const TraceSession& session)
{
// if this session is already known, nothing to do
FB_SIZE_T pos;
@@ -392,23 +275,24 @@ void TraceManager::update_session(const TraceSession& session)
}
}
-bool TraceManager::need_dsql_prepare(Attachment* att)
+bool JrdTraceManager::need_dsql_prepare(Attachment* att)
{
return att->att_trace_manager->needs(ITraceFactory::TRACE_EVENT_DSQL_PREPARE);
}
-bool TraceManager::need_dsql_free(Attachment* att)
+bool JrdTraceManager::need_dsql_free(Attachment* att)
{
return att->att_trace_manager->needs(ITraceFactory::TRACE_EVENT_DSQL_FREE);
}
-bool TraceManager::need_dsql_execute(Attachment* att)
+bool JrdTraceManager::need_dsql_execute(Attachment* att)
{
return att->att_trace_manager->needs(ITraceFactory::TRACE_EVENT_DSQL_EXECUTE);
}
-void TraceManager::event_dsql_prepare(Attachment* att, jrd_tra* transaction,
- ITraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result)
+void JrdTraceManager::event_dsql_prepare(Attachment* att, jrd_tra* transaction,
+ ITraceSQLStatement* statement,
+ ntrace_counter_t time_millis, ntrace_result_t req_result)
{
TraceConnectionImpl conn(att);
TraceTransactionImpl tran(transaction);
@@ -417,7 +301,7 @@ void TraceManager::event_dsql_prepare(Attachment* att, jrd_tra* transaction,
time_millis, req_result);
}
-void TraceManager::event_dsql_free(Attachment* att, ITraceSQLStatement* statement,
+void JrdTraceManager::event_dsql_free(Attachment* att, ITraceSQLStatement* statement,
unsigned short option)
{
TraceConnectionImpl conn(att);
@@ -425,7 +309,7 @@ void TraceManager::event_dsql_free(Attachment* att, ITraceSQLStatement* statemen
att->att_trace_manager->event_dsql_free(&conn, statement, option);
}
-void TraceManager::event_dsql_execute(Attachment* att, jrd_tra* transaction,
+void JrdTraceManager::event_dsql_execute(Attachment* att, jrd_tra* transaction,
ITraceSQLStatement* statement, bool started, ntrace_result_t req_result)
{
TraceConnectionImpl conn(att);
@@ -435,7 +319,7 @@ void TraceManager::event_dsql_execute(Attachment* att, jrd_tra* transaction,
started, req_result);
}
-void TraceManager::event_dsql_restart(Attachment* att, jrd_tra* transaction,
+void JrdTraceManager::event_dsql_restart(Attachment* att, jrd_tra* transaction,
DsqlRequest* statement, int number)
{
TraceConnectionImpl conn(att);
@@ -446,40 +330,7 @@ void TraceManager::event_dsql_restart(Attachment* att, jrd_tra* transaction,
(unsigned) number);
}
-#define EXECUTE_HOOKS(METHOD, PARAMS) \
- FB_SIZE_T i = 0; \
- while (i < trace_sessions.getCount()) \
- { \
- SessionInfo* plug_info = &trace_sessions[i]; \
- if (check_result(plug_info->plugin, plug_info->factory_info->name, #METHOD, \
- plug_info->plugin->METHOD PARAMS)) \
- { \
- i++; /* Move to next plugin */ \
- } \
- else { \
- plug_info->plugin->release(); \
- trace_sessions.remove(i); /* Remove broken plugin from the list */ \
- } \
- }
-
-
-void TraceManager::event_attach(ITraceDatabaseConnection* connection,
- bool create_db, ntrace_result_t att_result)
-{
- EXECUTE_HOOKS(trace_attach,
- (connection, create_db, att_result));
-
- trace_needs &= ~(FB_CONST64(1) << ITraceFactory::TRACE_EVENT_ATTACH);
-}
-
-void TraceManager::event_detach(ITraceDatabaseConnection* connection, bool drop_db)
-{
- EXECUTE_HOOKS(trace_detach, (connection, drop_db));
-
- trace_needs &= ~(FB_CONST64(1) << ITraceFactory::TRACE_EVENT_DETACH);
-}
-
-void TraceManager::event_transaction_start(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_transaction_start(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, unsigned tpb_length, const ntrace_byte_t* tpb,
ntrace_result_t tra_result)
{
@@ -487,7 +338,7 @@ void TraceManager::event_transaction_start(ITraceDatabaseConnection* connection,
(connection, transaction, tpb_length, tpb, tra_result));
}
-void TraceManager::event_transaction_end(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_transaction_end(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, bool commit, bool retain_context,
ntrace_result_t tra_result)
{
@@ -495,56 +346,56 @@ void TraceManager::event_transaction_end(ITraceDatabaseConnection* connection,
(connection, transaction, commit, retain_context, tra_result));
}
-void TraceManager::event_set_context(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_set_context(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, ITraceContextVariable* variable)
{
EXECUTE_HOOKS(trace_set_context,
(connection, transaction, variable));
}
-void TraceManager::event_proc_compile(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_proc_compile(ITraceDatabaseConnection* connection,
ITraceProcedure* procedure, ntrace_counter_t time_millis, ntrace_result_t proc_result)
{
EXECUTE_HOOKS(trace_proc_compile,
(connection, procedure, time_millis, proc_result));
}
-void TraceManager::event_proc_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_proc_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceProcedure* procedure, bool started, ntrace_result_t proc_result)
{
EXECUTE_HOOKS(trace_proc_execute,
(connection, transaction, procedure, started, proc_result));
}
-void TraceManager::event_func_compile(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_func_compile(ITraceDatabaseConnection* connection,
ITraceFunction* function, ntrace_counter_t time_millis, ntrace_result_t func_result)
{
EXECUTE_HOOKS(trace_func_compile,
(connection, function, time_millis, func_result));
}
-void TraceManager::event_func_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_func_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceFunction* function, bool started, ntrace_result_t func_result)
{
EXECUTE_HOOKS(trace_func_execute,
(connection, transaction, function, started, func_result));
}
-void TraceManager::event_trigger_compile(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_trigger_compile(ITraceDatabaseConnection* connection,
ITraceTrigger* trigger, ntrace_counter_t time_millis, ntrace_result_t trig_result)
{
EXECUTE_HOOKS(trace_trigger_compile,
(connection, trigger, time_millis, trig_result));
}
-void TraceManager::event_trigger_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_trigger_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceTrigger* trigger, bool started, ntrace_result_t trig_result)
{
EXECUTE_HOOKS(trace_trigger_execute,
(connection, transaction, trigger, started, trig_result));
}
-void TraceManager::event_dsql_prepare(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_dsql_prepare(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceSQLStatement* statement, ntrace_counter_t time_millis, ntrace_result_t req_result)
{
EXECUTE_HOOKS(trace_dsql_prepare,
@@ -552,37 +403,37 @@ void TraceManager::event_dsql_prepare(ITraceDatabaseConnection* connection, ITra
time_millis, req_result));
}
-void TraceManager::event_dsql_free(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_dsql_free(ITraceDatabaseConnection* connection,
ITraceSQLStatement* statement, unsigned short option)
{
EXECUTE_HOOKS(trace_dsql_free,
(connection, statement, option));
}
-void TraceManager::event_dsql_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_dsql_execute(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceSQLStatement* statement, bool started, ntrace_result_t req_result)
{
EXECUTE_HOOKS(trace_dsql_execute,
(connection, transaction, statement, started, req_result));
}
-void TraceManager::event_dsql_restart(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
+void JrdTraceManager::event_dsql_restart(ITraceDatabaseConnection* connection, ITraceTransaction* transaction,
ITraceSQLStatement* statement, unsigned number)
{
EXECUTE_HOOKS(trace_dsql_restart,
(connection, transaction, statement, number));
}
-void TraceManager::event_blr_compile(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_blr_compile(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, ITraceBLRStatement* statement,
- ntrace_counter_t time_millis, ntrace_result_t req_result)
+ ntrace_counter_t time_millis, ntrace_result_t req_result)
{
EXECUTE_HOOKS(trace_blr_compile,
(connection, transaction, statement,
time_millis, req_result));
}
-void TraceManager::event_blr_execute(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_blr_execute(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, ITraceBLRStatement* statement,
ntrace_result_t req_result)
{
@@ -590,7 +441,7 @@ void TraceManager::event_blr_execute(ITraceDatabaseConnection* connection,
(connection, transaction, statement, req_result));
}
-void TraceManager::event_dyn_execute(ITraceDatabaseConnection* connection,
+void JrdTraceManager::event_dyn_execute(ITraceDatabaseConnection* connection,
ITraceTransaction* transaction, ITraceDYNRequest* request,
ntrace_counter_t time_millis, ntrace_result_t req_result)
{
@@ -599,13 +450,13 @@ void TraceManager::event_dyn_execute(ITraceDatabaseConnection* connection,
req_result));
}
-void TraceManager::event_service_attach(ITraceServiceConnection* service, ntrace_result_t att_result)
+void JrdTraceManager::event_service_attach(ITraceServiceConnection* service, ntrace_result_t att_result)
{
EXECUTE_HOOKS(trace_service_attach,
(service, att_result));
}
-void TraceManager::event_service_start(ITraceServiceConnection* service,
+void JrdTraceManager::event_service_start(ITraceServiceConnection* service,
unsigned switches_length, const char* switches,
ntrace_result_t start_result)
{
@@ -613,7 +464,7 @@ void TraceManager::event_service_start(ITraceServiceConnection* service,
(service, switches_length, switches, start_result));
}
-void TraceManager::event_service_query(ITraceServiceConnection* service,
+void JrdTraceManager::event_service_query(ITraceServiceConnection* service,
unsigned send_item_length, const ntrace_byte_t* send_items,
unsigned recv_item_length, const ntrace_byte_t* recv_items,
ntrace_result_t query_result)
@@ -623,20 +474,20 @@ void TraceManager::event_service_query(ITraceServiceConnection* service,
recv_item_length, recv_items, query_result));
}
-void TraceManager::event_service_detach(ITraceServiceConnection* service, ntrace_result_t detach_result)
+void JrdTraceManager::event_service_detach(ITraceServiceConnection* service, ntrace_result_t detach_result)
{
EXECUTE_HOOKS(trace_service_detach,
(service, detach_result));
}
-void TraceManager::event_error(ITraceConnection* connection, ITraceStatusVector* status, const char* function)
+void JrdTraceManager::event_error(ITraceConnection* connection, ITraceStatusVector* status, const char* function)
{
EXECUTE_HOOKS(trace_event_error,
(connection, status, function));
}
-void TraceManager::event_sweep(ITraceDatabaseConnection* connection, ITraceSweepInfo* sweep,
+void JrdTraceManager::event_sweep(ITraceDatabaseConnection* connection, ITraceSweepInfo* sweep,
ntrace_process_state_t sweep_state)
{
EXECUTE_HOOKS(trace_event_sweep,
diff --git a/src/jrd/trace/TraceManager.h b/src/supplement/trace/JrdTraceManager.h
similarity index 72%
rename from src/jrd/trace/TraceManager.h
rename to src/supplement/trace/JrdTraceManager.h
index 047663d50e..caaf8b3d2c 100644
--- a/src/jrd/trace/TraceManager.h
+++ b/src/supplement/trace/JrdTraceManager.h
@@ -1,6 +1,6 @@
/*
* PROGRAM: JRD Access Method
- * MODULE: TraceManager.h
+ * MODULE: JrdTraceManager.h
* DESCRIPTION: Trace API manager
*
* The contents of this file are subject to the Initial
@@ -29,15 +29,7 @@
#ifndef JRD_TRACEMANAGER_H
#define JRD_TRACEMANAGER_H
-#include
-#include "../../jrd/ntrace.h"
-#include "../../common/classes/array.h"
-#include "../../common/classes/fb_string.h"
-#include "../../common/classes/init.h"
-#include "../../common/classes/rwlock.h"
-#include "../../common/classes/ImplementHelper.h"
-#include "../../jrd/trace/TraceConfigStorage.h"
-#include "../../jrd/trace/TraceSession.h"
+#include "TraceManager.h"
namespace Firebird {
@@ -53,27 +45,17 @@ class jrd_tra;
class DsqlRequest;
class Service;
-class TraceManager
+class JrdTraceManager : public TraceManager
{
public:
/* Initializes plugins. */
- explicit TraceManager(Attachment* in_att);
- explicit TraceManager(Service* in_svc);
- TraceManager(const char* in_filename, Firebird::ICryptKeyCallback* callback, bool failedAttach);
+ explicit JrdTraceManager(Attachment* in_att);
+ explicit JrdTraceManager(Service* in_svc);
+ JrdTraceManager(const char* in_filename, Firebird::ICryptKeyCallback* callback, bool failedAttach);
/* Finalize plugins. Called when database is closed by the engine */
- ~TraceManager();
+ ~JrdTraceManager();
- static ConfigStorage* getStorage()
- { return storageInstance->getStorage(); }
-
- static size_t pluginsCount()
- { return factories->getCount(); }
-
- void event_attach(Firebird::ITraceDatabaseConnection* connection, bool create_db,
- ntrace_result_t att_result);
-
- void event_detach(Firebird::ITraceDatabaseConnection* connection, bool drop_db);
/* Start/end transaction */
void event_transaction_start(Firebird::ITraceDatabaseConnection* connection, Firebird::ITraceTransaction* transaction,
@@ -182,80 +164,18 @@ public:
static void event_dsql_restart(Attachment* att, jrd_tra* transaction, DsqlRequest* statement,
int number);
- static void shutdown();
private:
Attachment* attachment;
Service* service;
- const char* filename;
Firebird::ICryptKeyCallback* callback;
- NotificationNeeds trace_needs, new_needs;
- // This structure should be POD-like to be stored in Array
- struct FactoryInfo
- {
- FactoryInfo() : factory(NULL)
- {
- memset(name, 0, sizeof(name));
- }
- Firebird::ITraceFactory* factory;
- char name[MAXPATHLEN];
- };
-
- class Factories : public Firebird::Array
- {
- public:
- explicit Factories(Firebird::MemoryPool& p)
- : Firebird::Array(p)
- { }
-
- ~Factories()
- {
- Firebird::PluginManagerInterfacePtr pi;
-
- for (unsigned int i = 0; i < getCount(); ++i)
- pi->releasePlugin(getElement(i).factory);
- }
- };
-
- static Factories* factories;
- static Firebird::GlobalPtr init_factories_lock;
- static volatile bool init_factories;
-
- struct SessionInfo
- {
- FactoryInfo* factory_info;
- Firebird::ITracePlugin* plugin;
- ULONG ses_id;
-
- static ULONG generate(const SessionInfo& item)
- { return item.ses_id; }
- };
- class Sessions : public Firebird::SortedArray, ULONG, SessionInfo>
- {
- public:
- explicit Sessions(MemoryPool& p)
- : Firebird::SortedArray, ULONG, SessionInfo>(p)
- { }
-
- ~Sessions()
- {
- for (unsigned int i = 0; i < getCount(); ++i)
- {
- getElement(i).plugin->release();
- }
- }
- };
- Sessions trace_sessions;
void init();
- void load_plugins();
void update_sessions();
void update_session(const Firebird::TraceSession& session);
- bool check_result(Firebird::ITracePlugin* plugin, const char* module, const char* function, bool result);
-
/* DSQL statement lifecycle. To be moved to public and used directly when DSQL becomes a part of JRD */
void event_dsql_prepare(Firebird::ITraceDatabaseConnection* connection, Firebird::ITraceTransaction* transaction,
Firebird::ITraceSQLStatement* statement,
@@ -271,9 +191,6 @@ private:
void event_dsql_restart(Firebird::ITraceDatabaseConnection* connection, Firebird::ITraceTransaction* transaction, Firebird::ITraceSQLStatement* statement,
unsigned number);
- static Firebird::GlobalPtr storageInstance;
-
- ULONG changeNumber;
bool active, failedAttach;
};
diff --git a/src/supplement/trace/TraceManager.cpp b/src/supplement/trace/TraceManager.cpp
new file mode 100644
index 0000000000..e757e45bbe
--- /dev/null
+++ b/src/supplement/trace/TraceManager.cpp
@@ -0,0 +1,417 @@
+/*
+ * PROGRAM: JRD Access Method
+ * MODULE: JrdTraceManager.cpp
+ * DESCRIPTION: Trace API manager
+ *
+ * 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
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ *
+ * 2008 Khorsun Vladyslav
+ */
+
+#include "firebird.h"
+
+#include "TraceManager.h"
+#include "../../common/os/path_utils.h"
+#include "../../common/ScanDir.h"
+#include "../../common/isc_proto.h"
+#include "../../common/classes/GetPlugins.h"
+#include "../../common/db_alias.h"
+#include "../../jrd/trace/TraceLog.h"
+
+#ifdef WIN_NT
+#include
+#endif
+
+using namespace Firebird;
+
+
+class TraceLogWriterImpl final :
+ public RefCntIface >
+{
+public:
+ TraceLogWriterImpl(const TraceSession& session) :
+ m_log(*getDefaultMemoryPool(), session.ses_logfile, false),
+ m_sesId(session.ses_id)
+ {
+ string s;
+ s.printf("\n--- Session %d is suspended as its log is full ---\n", session.ses_id);
+ m_log.setFullMsg(s.c_str());
+ }
+
+ // TraceLogWriter implementation
+
+ FB_SIZE_T write(const void* buf, FB_SIZE_T size)
+ {
+ const FB_SIZE_T written = m_log.write(buf, size);
+ if (written == size)
+ return size;
+
+ if (!m_log.isFull())
+ return written;
+
+ Jrd::ConfigStorage* storage = TraceManager::getStorage();
+ Jrd::StorageGuard guard(storage);
+
+ TraceSession session(*getDefaultMemoryPool());
+ session.ses_id = m_sesId;
+ if (storage->getSession(session, Jrd::ConfigStorage::FLAGS))
+ {
+ if (!(session.ses_flags & trs_log_full))
+ {
+ // suspend session
+ session.ses_flags |= trs_log_full;
+ storage->updateFlags(session);
+ }
+ }
+
+ // report successful write
+ return size;
+ }
+
+ FB_SIZE_T write_s(CheckStatusWrapper* status, const void* buf, FB_SIZE_T size)
+ {
+ try
+ {
+ return write(buf, size);
+ }
+ catch (Exception &ex)
+ {
+ ex.stuffException(status);
+ }
+
+ return 0;
+ }
+
+ int release()
+ {
+ if (--refCounter == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return 1;
+ }
+
+private:
+ Jrd::TraceLog m_log;
+ ULONG m_sesId;
+};
+
+
+class ServerTraceInitInfoImpl :
+ public AutoIface >
+{
+public:
+ ServerTraceInitInfoImpl(const TraceSession& session, ITraceDatabaseConnection* conn,
+ const char* dbName) :
+ session(session),
+ dbName(dbName),
+ logWriter(),
+ connection(conn)
+ { }
+
+ // TraceInitInfo implementation
+ const char* getConfigText() { return session.ses_config.c_str(); }
+ int getTraceSessionID() { return session.ses_id; }
+ const char* getTraceSessionName() { return session.ses_name.c_str(); }
+ int getTraceSessionFlags() { return session.ses_flags; }
+
+ const char* getFirebirdRootDirectory() { return Config::getRootDirectory(); }
+ const char* getDatabaseName() { return dbName; }
+
+ Firebird::ITraceDatabaseConnection* getConnection()
+ {
+ return connection;
+ }
+
+ Firebird::ITraceServiceConnection* getService()
+ {
+ return NULL;
+ }
+
+ Firebird::ITraceLogWriter* getLogWriter()
+ {
+ if (!logWriter && !session.ses_logfile.empty())
+ {
+ logWriter = FB_NEW TraceLogWriterImpl(session);
+ }
+ if (logWriter)
+ {
+ logWriter->addRef();
+ }
+ return logWriter;
+ }
+
+private:
+ const Firebird::TraceSession& session;
+ const char* dbName;
+ Firebird::RefPtr logWriter;
+ ITraceDatabaseConnection* connection;
+};
+
+
+GlobalPtr TraceManager::storageInstance;
+TraceManager::Factories* TraceManager::factories = NULL;
+GlobalPtr TraceManager::init_factories_lock;
+volatile bool TraceManager::init_factories;
+
+
+bool TraceManager::check_result(ITracePlugin* plugin, const char* module, const char* function,
+ bool result)
+{
+ if (result)
+ return true;
+
+ if (!plugin)
+ {
+ gds__log("Trace plugin %s returned error on call %s, "
+ "did not create plugin and provided no additional details on reasons of failure",
+ module, function);
+ return false;
+ }
+
+ const char* errorStr = plugin->trace_get_error();
+
+ if (!errorStr)
+ {
+ gds__log("Trace plugin %s returned error on call %s, "
+ "but provided no additional details on reasons of failure", module, function);
+ return false;
+ }
+
+ gds__log("Trace plugin %s returned error on call %s.\n\tError details: %s",
+ module, function, errorStr);
+ return false;
+}
+
+
+TraceManager::TraceManager(ITraceDatabaseConnection* conn, const char* in_filename) :
+ filename(in_filename),
+ trace_needs(0),
+ new_needs(0),
+ connection(conn),
+ trace_sessions(*getDefaultMemoryPool()),
+ changeNumber(0)
+{
+}
+
+TraceManager::TraceManager(const char* in_filename, MemoryPool& pool) :
+ filename(in_filename),
+ trace_needs(0),
+ new_needs(0),
+ connection(NULL),
+ trace_sessions(pool),
+ changeNumber(0)
+{ }
+
+TraceManager::~TraceManager()
+{
+}
+
+void TraceManager::initServerTrace()
+{
+ // ensure storage is initialized
+
+ // In Classic mode this is the first getStorage call, so it always creates the storage
+ // but it may not reread the config
+ getStorage(); // Open storage
+
+ load_plugins();
+ changeNumber = 0;
+}
+
+void TraceManager::load_plugins()
+{
+ // Initialize all trace needs to false
+ trace_needs = 0;
+
+ if (init_factories)
+ return;
+
+ Firebird::WriteLockGuard guard(init_factories_lock, FB_FUNCTION);
+ if (init_factories)
+ return;
+
+ factories = FB_NEW_POOL(*getDefaultMemoryPool()) TraceManager::Factories(*getDefaultMemoryPool());
+ for (GetPlugins traceItr(IPluginManager::TYPE_TRACE); traceItr.hasData(); traceItr.next())
+ {
+ FactoryInfo info;
+ info.factory = traceItr.plugin();
+ info.factory->addRef();
+ string name(traceItr.name());
+ name.copyTo(info.name, sizeof(info.name));
+ factories->add(info);
+ }
+
+ init_factories = true;
+}
+
+void TraceManager::shutdown()
+{
+ if (init_factories)
+ {
+ Firebird::WriteLockGuard guard(init_factories_lock, FB_FUNCTION);
+
+ if (init_factories)
+ {
+ init_factories = false;
+ delete factories;
+ factories = NULL;
+ }
+ }
+
+ getStorage()->shutdown();
+}
+
+ITraceLogWriter* TraceManager::createSessionLogWriter(const TraceSession& session)
+{
+ return FB_NEW TraceLogWriterImpl(session);
+}
+
+void TraceManager::reload_sessions_lists(HalfStaticArray& newSessions)
+{
+ MemoryPool& pool = *getDefaultMemoryPool();
+ SortedArray > liveSessions(pool);
+
+ { // scope
+ Jrd::ConfigStorage* storage = getStorage();
+
+ Jrd::StorageGuard guard(storage);
+ storage->restart();
+
+ TraceSession session(pool);
+ while (storage->getNextSession(session, Jrd::ConfigStorage::FLAGS))
+ {
+ if ((session.ses_flags & trs_active) && !(session.ses_flags & trs_log_full))
+ {
+ FB_SIZE_T pos;
+ if (trace_sessions.find(session.ses_id, pos))
+ liveSessions.add(session.ses_id);
+ else
+ {
+ storage->getSession(session, Jrd::ConfigStorage::ALL);
+ newSessions.add(FB_NEW_POOL(pool) TraceSession(pool, session));
+ }
+ }
+ }
+
+ changeNumber = storage->getChangeNumber();
+ }
+
+ // remove sessions not present in storage
+ FB_SIZE_T i = 0;
+ while (i < trace_sessions.getCount())
+ {
+ FB_SIZE_T pos;
+ if (liveSessions.find(trace_sessions[i].ses_id, pos)) {
+ i++;
+ }
+ else
+ {
+ trace_sessions[i].plugin->release();
+ trace_sessions.remove(i);
+ }
+ }
+}
+
+void TraceManager::update_sessions()
+{
+ MemoryPool& pool = *getDefaultMemoryPool();
+ HalfStaticArray newSessions(pool);
+
+ reload_sessions_lists(newSessions);
+
+ // add new sessions
+ new_needs = trace_needs;
+ trace_needs = 0;
+ while (newSessions.hasData())
+ {
+ // Preventing memory leaks in case of an exception
+ Firebird::AutoPtr s(newSessions.pop());
+ update_session(*s.get());
+ }
+
+ // nothing to trace, clear needs
+ if (trace_sessions.getCount() == 0)
+ {
+ trace_needs = 0;
+ }
+ else
+ {
+ trace_needs = new_needs;
+ }
+}
+
+void TraceManager::update_session(const TraceSession& session)
+{
+ // if this session is already known, nothing to do
+ FB_SIZE_T pos;
+ if (trace_sessions.find(session.ses_id, pos)) {
+ return;
+ }
+
+ Firebird::ReadLockGuard guard(init_factories_lock, FB_FUNCTION);
+ if (!factories)
+ return;
+
+ for (FactoryInfo* info = factories->begin(); info != factories->end(); ++info)
+ {
+ Firebird::LocalStatus localStatus;
+ Firebird::CheckStatusWrapper status(&localStatus);
+
+ ServerTraceInitInfoImpl attachInfo(session, connection, filename);
+ ITracePlugin* plugin = info->factory->trace_create(&status, &attachInfo);
+
+ if (plugin)
+ {
+ plugin->addRef();
+ SessionInfo sesInfo;
+ sesInfo.plugin = plugin;
+ sesInfo.factory_info = info;
+ sesInfo.ses_id = session.ses_id;
+ trace_sessions.add(sesInfo);
+
+ new_needs |= info->factory->trace_needs();
+ }
+ else if (status.getState() & IStatus::STATE_ERRORS)
+ {
+ string header;
+ header.printf("Trace plugin %s returned error on call trace_create.", info->name);
+ iscLogStatus(header.c_str(), &status);
+ }
+ }
+}
+
+void TraceManager::event_attach(Firebird::ITraceDatabaseConnection* connection, bool create_db,
+ ntrace_result_t att_result)
+{
+ EXECUTE_HOOKS(trace_attach,
+ (connection, create_db, att_result));
+
+ trace_needs &= ~(FB_CONST64(1) << ITraceFactory::TRACE_EVENT_ATTACH);
+}
+
+void TraceManager::event_detach(ITraceDatabaseConnection* connection, bool drop_db)
+{
+ EXECUTE_HOOKS(trace_detach, (connection, drop_db));
+
+ trace_needs &= ~(FB_CONST64(1) << ITraceFactory::TRACE_EVENT_DETACH);
+}
diff --git a/src/supplement/trace/TraceManager.h b/src/supplement/trace/TraceManager.h
new file mode 100644
index 0000000000..fddab6554a
--- /dev/null
+++ b/src/supplement/trace/TraceManager.h
@@ -0,0 +1,177 @@
+/*
+ * PROGRAM: Server Access Methods
+ * MODULE: TraceManager.h
+ * DESCRIPTION: Trace API manager
+ *
+ * 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
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ *
+ * 2008 Khorsun Vladyslav
+ */
+
+#ifndef TRACEMANAGER_H
+#define TRACEMANAGER_H
+
+#include "../../jrd/ntrace.h"
+#include "../../common/classes/array.h"
+#include "../../common/classes/fb_string.h"
+#include "../../common/classes/init.h"
+#include "../../common/classes/rwlock.h"
+#include "../../common/classes/ImplementHelper.h"
+#include "../../jrd/trace/TraceConfigStorage.h"
+#include "../../jrd/trace/TraceSession.h"
+
+class TraceManager
+{
+public:
+ /* Initializes plugins. */
+ explicit TraceManager(Firebird::ITraceDatabaseConnection* conn, const char* in_filename);
+ explicit TraceManager(const char* in_filename, MemoryPool& pool);
+ void initServerTrace();
+
+ /* Finalize plugins. Called when database is closed by the engine */
+ ~TraceManager();
+
+ static Jrd::ConfigStorage* getStorage()
+ { return storageInstance->getStorage(); }
+
+ static size_t pluginsCount()
+ { return factories->getCount(); }
+
+ void event_attach(Firebird::ITraceDatabaseConnection* connection, bool create_db,
+ ntrace_result_t att_result);
+
+ void event_detach(Firebird::ITraceDatabaseConnection* connection, bool drop_db);
+
+ typedef ntrace_mask_t NotificationNeeds;
+
+ inline bool needs(unsigned e)
+ {
+ if (!init_factories)
+ return false;
+
+ if (changeNumber != getStorage()->getChangeNumber())
+ update_sessions();
+
+ return trace_needs & (FB_CONST64(1) << e);
+ }
+
+ static void shutdown();
+ static Firebird::ITraceLogWriter* createSessionLogWriter(const Firebird::TraceSession& session);
+
+
+#define EXECUTE_HOOKS(METHOD, PARAMS) \
+ FB_SIZE_T i = 0; \
+ while (i < trace_sessions.getCount()) \
+ { \
+ SessionInfo* plug_info = &trace_sessions[i]; \
+ if (check_result(plug_info->plugin, plug_info->factory_info->name, #METHOD, \
+ plug_info->plugin->METHOD PARAMS)) \
+ { \
+ i++; /* Move to next plugin */ \
+ } \
+ else { \
+ trace_sessions.remove(i); /* Remove broken plugin from the list */ \
+ } \
+ }
+
+protected:
+ void reload_sessions_lists(Firebird::HalfStaticArray& newSessions);
+
+private:
+ Firebird::ITraceDatabaseConnection* connection;
+
+protected:
+ const char* filename;
+ NotificationNeeds trace_needs, new_needs;
+
+ // This structure should be POD-like to be stored in Array
+ struct FactoryInfo
+ {
+ FactoryInfo() : factory(NULL)
+ {
+ memset(name, 0, sizeof(name));
+ }
+
+ Firebird::ITraceFactory* factory;
+ char name[MAXPATHLEN];
+ };
+
+ class Factories : public Firebird::Array
+ {
+ public:
+ explicit Factories(Firebird::MemoryPool& p)
+ : Firebird::Array(p)
+ { }
+
+ ~Factories()
+ {
+ Firebird::PluginManagerInterfacePtr pi;
+
+ for (unsigned int i = 0; i < getCount(); ++i)
+ pi->releasePlugin(getElement(i).factory);
+ }
+ };
+
+
+ static Factories* factories;
+ static Firebird::GlobalPtr init_factories_lock;
+ static volatile bool init_factories;
+
+ struct SessionInfo
+ {
+ FactoryInfo* factory_info;
+ Firebird::ITracePlugin* plugin;
+ ULONG ses_id;
+
+ static ULONG generate(const SessionInfo& item)
+ { return item.ses_id; }
+ };
+
+ class Sessions : public Firebird::SortedArray, ULONG, SessionInfo>
+ {
+ public:
+ explicit Sessions(MemoryPool& p)
+ : Firebird::SortedArray, ULONG, SessionInfo>(p)
+ { }
+
+ ~Sessions()
+ {
+ for (unsigned int i = 0; i < getCount(); ++i)
+ {
+ getElement(i).plugin->release();
+ }
+ }
+ };
+
+ Sessions trace_sessions;
+
+ void load_plugins();
+ void update_sessions();
+ void update_session(const Firebird::TraceSession& session);
+
+ bool check_result(Firebird::ITracePlugin* plugin, const char* module, const char* function, bool result);
+
+ static Firebird::GlobalPtr storageInstance;
+
+ ULONG changeNumber;
+};
+
+#endif // !TRACEMANAGER_H