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