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