| 1 | /****************************************************************************** |
| 2 | * Copyright (c) 2000-2016 Ericsson Telecom AB |
| 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
| 5 | * which accompanies this distribution, and is available at |
| 6 | * http://www.eclipse.org/legal/epl-v10.html |
| 7 | * |
| 8 | * Contributors: |
| 9 | * Balasko, Jeno |
| 10 | * Beres, Szabolcs |
| 11 | * Kovacs, Ferenc |
| 12 | * Raduly, Csaba |
| 13 | * Szabados, Kristof |
| 14 | * Zalanyi, Balazs Andor |
| 15 | * Pandi, Krisztian |
| 16 | * |
| 17 | ******************************************************************************/ |
| 18 | #ifndef LOGGER_PLUGIN_MANAGER_HH |
| 19 | #define LOGGER_PLUGIN_MANAGER_HH |
| 20 | |
| 21 | #include "Types.h" |
| 22 | #include "Logger.hh" |
| 23 | #include "LoggerPlugin.hh" |
| 24 | #include "TitanLoggerApi.hh" |
| 25 | // The above includes TTCN3.hh, which pulls in everything in the runtime |
| 26 | #include "LoggingParam.hh" |
| 27 | |
| 28 | struct Logging_Bits; |
| 29 | struct component_id_t; |
| 30 | struct disk_full_action_t; |
| 31 | |
| 32 | #ifdef __GNUC__ |
| 33 | #define MUST_CHECK __attribute__((__warn_unused_result__)) |
| 34 | #else |
| 35 | #define MUST_CHECK |
| 36 | #endif |
| 37 | |
| 38 | namespace LoggerAPI |
| 39 | { |
| 40 | class TitanLogEvent; |
| 41 | } |
| 42 | |
| 43 | |
| 44 | class RingBuffer |
| 45 | { |
| 46 | TitanLoggerApi::TitanLogEvent* buffer; |
| 47 | unsigned int head; |
| 48 | unsigned int tail; |
| 49 | unsigned int size; |
| 50 | |
| 51 | public: |
| 52 | explicit RingBuffer() : buffer(NULL), head(0), tail(0), |
| 53 | size(TTCN_Logger::get_emergency_logging()) {} |
| 54 | ~RingBuffer(); |
| 55 | |
| 56 | bool get(TitanLoggerApi::TitanLogEvent& data) MUST_CHECK; |
| 57 | void put(TitanLoggerApi::TitanLogEvent data); |
| 58 | void clear(); |
| 59 | unsigned int get_size() const { return size; } |
| 60 | void set_size(unsigned int new_size); |
| 61 | bool isFull() const { return (head + 1) % (size + 1) == tail; } |
| 62 | bool isEmpty() const {return head == tail; } |
| 63 | }; |
| 64 | |
| 65 | class LoggerPluginManager |
| 66 | { |
| 67 | friend class ILoggerPlugin; |
| 68 | |
| 69 | public: |
| 70 | void ring_buffer_dump(bool do_close_file); |
| 71 | |
| 72 | // Sends a single log event to all logger plugins. |
| 73 | void internal_log_to_all(const TitanLoggerApi::TitanLogEvent& event, |
| 74 | bool log_buffered, bool separate_file, bool use_emergency_mask); |
| 75 | // If an event appears before any logger is configured we have to pre-buffer it. |
| 76 | void internal_prebuff_logevent(const TitanLoggerApi::TitanLogEvent& event); |
| 77 | // When the loggers get configured we have to log everything we have buffered so far |
| 78 | void internal_log_prebuff_logevent(); |
| 79 | public: |
| 80 | explicit LoggerPluginManager(); |
| 81 | ~LoggerPluginManager(); |
| 82 | |
| 83 | void register_plugin(const component_id_t comp, char *identifier, char *filename); |
| 84 | void load_plugins(component component_reference, const char *component_name); |
| 85 | void unload_plugins(); |
| 86 | void reset(); |
| 87 | |
| 88 | bool add_parameter(const logging_setting_t& logging_param); |
| 89 | void set_parameters(component component_reference, const char *component_name); |
| 90 | |
| 91 | bool plugins_ready() const; |
| 92 | |
| 93 | /// Backward compatibility functions to handle top level configuration file |
| 94 | /// parameters. All logger plug-ins will receive these settings, but they |
| 95 | /// can simply ignore them. |
| 96 | bool set_file_mask(component_id_t const& comp, const Logging_Bits& new_file_mask); |
| 97 | bool set_console_mask(component_id_t const& comp, |
| 98 | const Logging_Bits& new_console_mask); |
| 99 | void set_file_name(const char *new_filename_skeleton, bool from_config); |
| 100 | void set_append_file(bool new_append_file); |
| 101 | /// Return true if the given configuration file parameter was set multiple |
| 102 | /// times. (The return value is used by the configuration file parser.) |
| 103 | bool set_file_size(component_id_t const& comp, int p_size); |
| 104 | bool set_file_number(component_id_t const& cmpt, int p_number); |
| 105 | bool set_disk_full_action(component_id_t const& comp, |
| 106 | TTCN_Logger::disk_full_action_t p_disk_full_action); |
| 107 | void open_file(); |
| 108 | void close_file(); |
| 109 | void fill_common_fields(TitanLoggerApi::TitanLogEvent& event, |
| 110 | const TTCN_Logger::Severity& severity); |
| 111 | void append_event_str(const char *str); |
| 112 | |
| 113 | /// returns a copy of the current event string |
| 114 | char* get_current_event_str(); |
| 115 | |
| 116 | /// Do the actual call to the plug-ins with EVENT. Flush the buffers if |
| 117 | /// necessary. It is called at the end of each log_* function. The |
| 118 | /// complete event handling is part of LoggerPluginManager. |
| 119 | void log(const TitanLoggerApi::TitanLogEvent& event); |
| 120 | void log_va_list(TTCN_Logger::Severity msg_severity, const char *fmt_str, |
| 121 | va_list p_var); |
| 122 | void buffer_event(const TitanLoggerApi::TitanLogEvent& event); |
| 123 | void begin_event(TTCN_Logger::Severity msg_severity, bool log2str); |
| 124 | void end_event(); |
| 125 | CHARSTRING end_event_log2str(); |
| 126 | void finish_event(); |
| 127 | void log_event_str(const char *str_ptr); |
| 128 | void log_char(char c); |
| 129 | void log_event_va_list(const char *fmt_str, va_list p_var); |
| 130 | void log_unhandled_event(TTCN_Logger::Severity severity, |
| 131 | const char *message_ptr, size_t message_len); |
| 132 | void log_log_options(const char *message_ptr, size_t message_len); |
| 133 | |
| 134 | /** @name New, one-per-event log functions. |
| 135 | * @{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 136 | void log_timer_read(const char *timer_name, double start_val); |
| 137 | void log_timer_start(const char *timer_name, double start_val); |
| 138 | void log_timer_guard(double start_val); |
| 139 | void log_timer_stop(const char *timer_name, double stop_val); |
| 140 | void log_timer_timeout(const char *timer_name, double timeout_val); |
| 141 | void log_timer_any_timeout(); |
| 142 | void log_timer_unqualified(const char *message); |
| 143 | |
| 144 | void log_testcase_started (const qualified_name& testcase_name); |
| 145 | void log_testcase_finished(const qualified_name& testcase_name, |
| 146 | verdicttype verdict, const char *reason); |
| 147 | |
| 148 | void log_controlpart_start_stop(const char *module_name, int finished); |
| 149 | void log_controlpart_errors(unsigned int error_count); |
| 150 | |
| 151 | void log_setverdict(verdicttype new_verdict, verdicttype old_verdict, |
| 152 | verdicttype local_verdict, const char *old_reason = NULL, const char *new_reason = NULL); |
| 153 | void log_getverdict(verdicttype verdict); |
| 154 | void log_final_verdict(bool is_ptc, verdicttype ptc_verdict, |
| 155 | verdicttype local_verdict, verdicttype new_verdict, |
| 156 | const char *verdict_reason = NULL, int notification = -1, |
| 157 | int ptc_compref = UNBOUND_COMPREF, const char *ptc_name = NULL); |
| 158 | |
| 159 | void log_verdict_statistics(size_t none_count, double none_percent, |
| 160 | size_t pass_count, double pass_percent, |
| 161 | size_t inconc_count, double inconc_percent, |
| 162 | size_t fail_count, double fail_percent, |
| 163 | size_t error_count, double error_percent); |
| 164 | |
| 165 | void log_defaultop_activate (const char *name, int id); |
| 166 | void log_defaultop_deactivate(const char *name, int id); |
| 167 | void log_defaultop_exit (const char *name, int id, int x); |
| 168 | |
| 169 | /// EXECUTOR_RUNTIME, fixed strings only (no params) |
| 170 | void log_executor_runtime(TitanLoggerApi::ExecutorRuntime_reason reason); |
| 171 | // EXECUTOR_RUNTIME with parameters |
| 172 | void log_HC_start(const char *host); |
| 173 | void log_fd_limits(int fd_limit, long fd_set_size); |
| 174 | void log_not_overloaded(int pid); |
| 175 | void log_testcase_exec(const char *tc, const char *module); |
| 176 | void log_module_init(const char *module, bool finish); |
| 177 | void log_mtc_created(long pid); |
| 178 | /// EXECUTOR_CONFIGDATA |
| 179 | void log_configdata(int reason, const char *str); |
| 180 | |
| 181 | void log_executor_component(int reason); // and some more |
| 182 | |
| 183 | void log_executor_misc(int reason, const char *name, const char *address, |
| 184 | int port); |
| 185 | |
| 186 | void log_extcommand(TTCN_Logger::extcommand_t action, const char *cmd); |
| 187 | |
| 188 | void log_matching_done(TitanLoggerApi::MatchingDoneType_reason reason, |
| 189 | const char *type, int ptc, const char *return_type); |
| 190 | |
| 191 | void log_matching_problem(int reason, int operation, |
| 192 | boolean check, boolean anyport, const char *port_name); |
| 193 | |
| 194 | void log_matching_success(int port_type, const char *port_name, int compref, |
| 195 | const CHARSTRING& info); |
| 196 | void log_matching_failure(int port_type, const char *port_name, int compref, |
| 197 | int reason, const CHARSTRING& info); |
| 198 | |
| 199 | void log_matching_timeout(const char *timer_name); |
| 200 | |
| 201 | void log_random(int action, double v, unsigned long u); |
| 202 | |
| 203 | void log_portconnmap(int operation, int src_compref, const char *src_port, |
| 204 | int dst_compref, const char *dst_port); |
| 205 | |
| 206 | void log_par_ptc(int reason, const char *module, const char *name, int compref, |
| 207 | const char *compname, const char *tc_loc, int alive_pid, int status); |
| 208 | |
| 209 | void log_port_queue(int operation, const char *port_name, int compref, int id, |
| 210 | const CHARSTRING& address, const CHARSTRING& param); |
| 211 | |
| 212 | void log_port_state(int operation, const char *port_name); |
| 213 | |
| 214 | void log_procport_send(const char *portname, int operation, |
| 215 | int compref, const CHARSTRING& system, const CHARSTRING& param); |
| 216 | void log_procport_recv(const char *portname, int operation, int compref, |
| 217 | boolean check, const CHARSTRING& param, int id); |
| 218 | void log_msgport_send(const char *portname, int compref, |
| 219 | const CHARSTRING& param); |
| 220 | void log_msgport_recv(const char *portname, int operation, int compref, |
| 221 | const CHARSTRING& system, const CHARSTRING& param, int id); |
| 222 | |
| 223 | void log_dualport_map(boolean incoming, const char *target_type, |
| 224 | const CHARSTRING& value, int id); |
| 225 | void log_dualport_discard(boolean incoming, const char *target_type, |
| 226 | const char *port_name, boolean unhandled); |
| 227 | |
| 228 | void log_port_misc(int reason, const char *port_name, int remote_component, |
| 229 | const char *remote_port, const char *ip_address, int tcp_port, int new_size); |
| 230 | |
| 231 | /** @} * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
| 232 | LoggerPlugin *find_plugin(const char *name); |
| 233 | |
| 234 | void clear_param_list(); |
| 235 | void clear_plugin_list(); |
| 236 | |
| 237 | private: |
| 238 | explicit LoggerPluginManager(const LoggerPluginManager&); |
| 239 | LoggerPluginManager& operator=(const LoggerPluginManager&); |
| 240 | |
| 241 | void apply_parameter(const logging_setting_t& logparam); |
| 242 | void send_parameter_to_plugin(LoggerPlugin* plugin, const logging_setting_t& logparam); |
| 243 | |
| 244 | void load_plugin(const char *identifier, const char *filename); |
| 245 | |
| 246 | enum event_destination_t |
| 247 | { |
| 248 | ED_NONE, // To be discarded. |
| 249 | ED_FILE, // Event goes to log file or console, it's a historic name. |
| 250 | ED_STRING // Event goes to CHARSTRING. |
| 251 | }; |
| 252 | |
| 253 | private: |
| 254 | /// Circular buffer for emergency logging |
| 255 | RingBuffer ring_buffer; |
| 256 | |
| 257 | /// Number of loaded plug-ins. Should be at least 1. |
| 258 | size_t n_plugins_; |
| 259 | |
| 260 | /// List of active (dynamic/static) logger plug-ins. |
| 261 | LoggerPlugin **plugins_; |
| 262 | |
| 263 | // This is for the fast events. |
| 264 | struct LogEntry |
| 265 | { |
| 266 | TitanLoggerApi::TitanLogEvent event_; |
| 267 | LogEntry *next_entry_; |
| 268 | } *entry_list_; |
| 269 | |
| 270 | // This is for the active events (~ stack). |
| 271 | struct ActiveEvent |
| 272 | { |
| 273 | /// Space for a TitanLogEvent aligned as a long int. |
| 274 | long event_[(sizeof(TitanLoggerApi::TitanLogEvent) - 1 + sizeof(long)) |
| 275 | / sizeof(long)]; |
| 276 | |
| 277 | char *event_str_; // Speed up event string handling. |
| 278 | size_t event_str_len_; ///< Actual length of the string. |
| 279 | size_t event_str_size_; ///< Size of the allocated memory. |
| 280 | event_destination_t event_destination_; // Used only be active events. |
| 281 | ActiveEvent *outer_event_; |
| 282 | // For better space efficiency, all the pieces are kept concatenated as always, |
| 283 | // but we remember offsets into the concatenated string. |
| 284 | size_t num_pieces_; |
| 285 | size_t *pieces_; // the end of each piece |
| 286 | // Only (num_pieces_-1) elements are allocated, so the last accessible |
| 287 | // element is at num_pieces_-2. The end of the last piece is event_str_len_ |
| 288 | |
| 289 | /// True if the event is for log2str, in which case @p event_ is blank. |
| 290 | bool fake_; |
| 291 | |
| 292 | /** Constructor |
| 293 | * |
| 294 | * @param fake_event true if the event is for log2str, in which case |
| 295 | * @p event_ is not initialized. |
| 296 | * @param dest event destination (logfile, string or none) |
| 297 | */ |
| 298 | ActiveEvent(bool fake_event, event_destination_t dest); |
| 299 | ~ActiveEvent(); |
| 300 | TitanLoggerApi::TitanLogEvent& get_event() |
| 301 | { |
| 302 | return *reinterpret_cast<TitanLoggerApi::TitanLogEvent*>((void*)&event_); |
| 303 | } |
| 304 | } *current_event_; |
| 305 | |
| 306 | logging_setting_t* logparams_head; |
| 307 | logging_setting_t* logparams_tail; |
| 308 | |
| 309 | logging_plugin_t* logplugins_head; |
| 310 | logging_plugin_t* logplugins_tail; |
| 311 | }; |
| 312 | |
| 313 | #endif // LOGGER_PLUGIN_MANAGER_HH |