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

Merge remote-tracking branch 'reddb/trace_faild_attaches_7580' into trace-failed-attach

This commit is contained in:
Dmitry Yemanov 2024-03-04 21:01:41 +03:00
commit 1ab2ad8af5
31 changed files with 956 additions and 420 deletions

View File

@ -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)

View File

@ -172,9 +172,10 @@
<ClCompile Include="..\..\..\src\jrd\trace\TraceCmdLine.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceConfigStorage.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceLog.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceManager.cpp" />
<ClCompile Include="..\..\..\src\supplement\trace\JrdTraceManager.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceObjects.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceService.cpp" />
<ClCompile Include="..\..\..\src\supplement\trace\TraceManager.cpp" />
<ClCompile Include="..\..\..\src\jrd\UserManagement.cpp" />
<ClCompile Include="..\..\..\src\jrd\validation.cpp" />
<ClCompile Include="..\..\..\src\jrd\vio.cpp" />
@ -358,7 +359,7 @@
<ClInclude Include="..\..\..\src\jrd\trace\TraceDSQLHelpers.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceJrdHelpers.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceLog.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceManager.h" />
<ClInclude Include="..\..\..\src\supplement\trace\JrdTraceManager.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceObjects.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceService.h" />
<ClInclude Include="..\..\..\src\jrd\trace\TraceSession.h" />

View File

@ -198,7 +198,7 @@
<ClCompile Include="..\..\..\src\jrd\trace\TraceLog.cpp">
<Filter>JRD files\Trace</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\trace\TraceManager.cpp">
<ClCompile Include="..\..\..\src\supplement\trace\JrdTraceManager.cpp">
<Filter>JRD files\Trace</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\trace\TraceObjects.cpp">
@ -207,6 +207,9 @@
<ClCompile Include="..\..\..\src\jrd\trace\TraceService.cpp">
<Filter>JRD files\Trace</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\supplement\trace\TraceManager.cpp">
<Filter>JRD files\Trace</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\VirtualTable.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -656,7 +659,7 @@
<ClInclude Include="..\..\..\src\jrd\trace\TraceLog.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\trace\TraceManager.h">
<ClInclude Include="..\..\..\src\supplement\trace\JrdTraceManager.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\trace\TraceObjects.h">

View File

@ -205,6 +205,9 @@
<ClCompile Include="..\..\..\src\remote\server\ReplServer.cpp" />
<ClCompile Include="..\..\..\src\jrd\replication\Config.cpp" />
<ClCompile Include="..\..\..\src\jrd\replication\Utils.cpp" />
<ClCompile Include="..\..\..\src\supplement\trace\TraceManager.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceConfigStorage.cpp" />
<ClCompile Include="..\..\..\src\jrd\trace\TraceLog.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\src\remote\server\os\win32\caution.ico" />

View File

@ -34,6 +34,15 @@
<ClCompile Include="..\..\..\src\remote\server\os\win32\srvr_w32.cpp">
<Filter>Remote server</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\supplement\trace\TraceManager.cpp">
<Filter>Remote server</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\trace\TraceConfigStorage.cpp">
<Filter>Remote server</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\trace\TraceLog.cpp">
<Filter>Remote server</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\auth\SecureRemotePassword\server\SrpServer.cpp">
<Filter>AUTH files</Filter>
</ClCompile>

View File

@ -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());

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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()),

View File

@ -92,7 +92,7 @@ namespace Jrd
class jrd_fld;
class dsql_dbb;
class PreparedStatement;
class TraceManager;
class JrdTraceManager;
template <typename T> 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;

View File

@ -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"

View File

@ -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"

View File

@ -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))

View File

@ -129,7 +129,7 @@ class Parameter;
class jrd_fld;
class dsql_dbb;
class PreparedStatement;
class TraceManager;
class JrdTraceManager;
class MessageNode;

View File

@ -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"

View File

@ -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))
{

View File

@ -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<type_svc>
@ -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:

View File

@ -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);

View File

@ -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 <unistd.h>

View File

@ -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;

View File

@ -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;

View File

@ -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<ITraceLogWriterImpl<TraceLogWriterImpl, CheckStatusWrapper> >
{
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)
{

View File

@ -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)

View File

@ -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"

View File

@ -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 <process.h>
#define getpid _getpid
#endif
using namespace Firebird;
@ -431,6 +438,151 @@ public:
}
};
// For Trace
class TraceFailedAuthImpl :
public Firebird::AutoIface<Firebird::ITraceDatabaseConnectionImpl<TraceFailedAuthImpl, Firebird::CheckStatusWrapper> >
{
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<FailedLogins> usernameFailedLogins;
GlobalPtr<FailedLogins> 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<ClumpletWriter> 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<const Config> 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;
}

View File

@ -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<StorageInstance, InstanceControl::PRIORITY_DELETE_FIRST> TraceManager::storageInstance;
TraceManager::Factories* TraceManager::factories = NULL;
GlobalPtr<RWLock> 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<ITraceFactory> 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<ULONG, InlineStorage<ULONG, 64> > liveSessions(pool);
HalfStaticArray<TraceSession*, 64> 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,28 +403,28 @@ 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)
{
@ -582,7 +433,7 @@ void TraceManager::event_blr_compile(ITraceDatabaseConnection* connection,
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,

View File

@ -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 <time.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"
#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<FactoryInfo>
{
public:
explicit Factories(Firebird::MemoryPool& p)
: Firebird::Array<FactoryInfo>(p)
{ }
~Factories()
{
Firebird::PluginManagerInterfacePtr pi;
for (unsigned int i = 0; i < getCount(); ++i)
pi->releasePlugin(getElement(i).factory);
}
};
static Factories* factories;
static Firebird::GlobalPtr<Firebird::RWLock> 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<SessionInfo, Firebird::EmptyStorage<SessionInfo>, ULONG, SessionInfo>
{
public:
explicit Sessions(MemoryPool& p)
: Firebird::SortedArray<SessionInfo, Firebird::EmptyStorage<SessionInfo>, 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, Firebird::InstanceControl::PRIORITY_DELETE_FIRST> storageInstance;
ULONG changeNumber;
bool active, failedAttach;
};

View File

@ -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 <nickolay@broadviewsoftware.com>
* 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 <process.h>
#endif
using namespace Firebird;
class TraceLogWriterImpl final :
public RefCntIface<ITraceLogWriterImpl<TraceLogWriterImpl, CheckStatusWrapper> >
{
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<ITraceInitInfoImpl<ServerTraceInitInfoImpl, CheckStatusWrapper> >
{
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<Firebird::ITraceLogWriter> logWriter;
ITraceDatabaseConnection* connection;
};
GlobalPtr<Jrd::StorageInstance, InstanceControl::PRIORITY_DELETE_FIRST> TraceManager::storageInstance;
TraceManager::Factories* TraceManager::factories = NULL;
GlobalPtr<Firebird::RWLock> 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<ITraceFactory> 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<TraceSession*, 64>& newSessions)
{
MemoryPool& pool = *getDefaultMemoryPool();
SortedArray<ULONG, InlineStorage<ULONG, 64> > 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<TraceSession*, 64> 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<TraceSession> 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);
}

View File

@ -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 <nickolay@broadviewsoftware.com>
* 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<Firebird::TraceSession*, 64>& 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<FactoryInfo>
{
public:
explicit Factories(Firebird::MemoryPool& p)
: Firebird::Array<FactoryInfo>(p)
{ }
~Factories()
{
Firebird::PluginManagerInterfacePtr pi;
for (unsigned int i = 0; i < getCount(); ++i)
pi->releasePlugin(getElement(i).factory);
}
};
static Factories* factories;
static Firebird::GlobalPtr<Firebird::RWLock> 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<SessionInfo, Firebird::EmptyStorage<SessionInfo>, ULONG, SessionInfo>
{
public:
explicit Sessions(MemoryPool& p)
: Firebird::SortedArray<SessionInfo, Firebird::EmptyStorage<SessionInfo>, 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<Jrd::StorageInstance, Firebird::InstanceControl::PRIORITY_DELETE_FIRST> storageInstance;
ULONG changeNumber;
};
#endif // !TRACEMANAGER_H