Commit | Line | Data |
---|---|---|
d44e3c4f | 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 | * Baranyi, Botond | |
11 | * Beres, Szabolcs | |
12 | * Delic, Adam | |
13 | * Forstner, Matyas | |
14 | * Kovacs, Ferenc | |
15 | * Raduly, Csaba | |
16 | * Szabados, Kristof | |
17 | * Szabo, Janos Zoltan – initial implementation | |
18 | * Zalanyi, Balazs Andor | |
19 | * Pandi, Krisztian | |
20 | * | |
21 | ******************************************************************************/ | |
970ed795 EL |
22 | #ifndef LOGGER_HH |
23 | #define LOGGER_HH | |
24 | ||
25 | #include <stdio.h> | |
26 | #include <stdlib.h> | |
27 | #include <stdarg.h> | |
28 | #include <sys/time.h> | |
29 | ||
30 | #include "Types.h" | |
31 | ||
32 | struct log_mask_info; | |
33 | struct Logging_Bits; | |
34 | class LoggerPlugin; | |
35 | class LoggerPluginManager; | |
36 | class CHARSTRING; | |
37 | struct logging_setting_t; | |
38 | ||
39 | /** @brief Logger class | |
40 | ||
41 | Acts as a namespace. No instance data or methods. | |
42 | ||
43 | */ | |
44 | class TTCN_Logger | |
45 | { | |
46 | friend class LoggerPlugin; | |
47 | friend class LoggerPluginManager; | |
48 | public: | |
49 | static LoggerPluginManager *plugins_; | |
50 | // TODO: This should be plug-in specific, but the configuration file parsers | |
51 | // are using this type... | |
52 | enum disk_full_action_type_t { DISKFULL_ERROR, DISKFULL_STOP, | |
53 | DISKFULL_RETRY, DISKFULL_DELETE }; | |
54 | struct disk_full_action_t { | |
55 | disk_full_action_type_t type; | |
56 | size_t retry_interval; | |
57 | }; | |
58 | enum timestamp_format_t { TIMESTAMP_TIME, TIMESTAMP_DATETIME, | |
59 | TIMESTAMP_SECONDS }; | |
60 | enum source_info_format_t { SINFO_NONE, SINFO_SINGLE, SINFO_STACK }; | |
61 | enum log_event_types_t { LOGEVENTTYPES_NO, LOGEVENTTYPES_YES, | |
62 | LOGEVENTTYPES_SUBCATEGORIES }; | |
63 | ||
64 | enum emergency_logging_behaviour_t { BUFFER_ALL, BUFFER_MASKED }; | |
65 | ||
66 | enum matching_verbosity_t { VERBOSITY_COMPACT, VERBOSITY_FULL }; | |
67 | enum extcommand_t { EXTCOMMAND_START, EXTCOMMAND_SUCCESS }; | |
68 | ||
69 | /** Values and templates can be logged in the following formats */ | |
70 | enum data_log_format_t { LF_LEGACY, LF_TTCN }; | |
71 | ||
72 | /** @brief Titan logging severities | |
73 | ||
74 | @note The values are not bit masks. Expressions like | |
75 | @code LOG_ALL | TTCN_DEBUG @endcode will not work correctly. | |
76 | ||
77 | @note This enum must start at 0 and have no gaps until | |
78 | NUMBER_OF_LOGSEVERITIES. | |
79 | */ | |
80 | enum Severity | |
81 | { | |
82 | NOTHING_TO_LOG = 0, // for compatibility | |
83 | ||
84 | ACTION_UNQUALIFIED, | |
85 | ||
86 | DEFAULTOP_ACTIVATE, | |
87 | DEFAULTOP_DEACTIVATE, | |
88 | DEFAULTOP_EXIT, | |
89 | DEFAULTOP_UNQUALIFIED, //5 | |
90 | ||
91 | ERROR_UNQUALIFIED, | |
92 | ||
93 | EXECUTOR_RUNTIME, | |
94 | EXECUTOR_CONFIGDATA, | |
95 | EXECUTOR_EXTCOMMAND, | |
96 | EXECUTOR_COMPONENT, //10 | |
97 | EXECUTOR_LOGOPTIONS, | |
98 | EXECUTOR_UNQUALIFIED, | |
99 | ||
100 | FUNCTION_RND, | |
101 | FUNCTION_UNQUALIFIED, | |
102 | ||
103 | PARALLEL_PTC, //15 | |
104 | PARALLEL_PORTCONN, | |
105 | PARALLEL_PORTMAP, | |
106 | PARALLEL_UNQUALIFIED, | |
107 | ||
108 | TESTCASE_START, | |
109 | TESTCASE_FINISH, //20 | |
110 | TESTCASE_UNQUALIFIED, | |
111 | ||
112 | PORTEVENT_PQUEUE, | |
113 | PORTEVENT_MQUEUE, | |
114 | PORTEVENT_STATE, | |
115 | PORTEVENT_PMIN, //25 | |
116 | PORTEVENT_PMOUT, | |
117 | PORTEVENT_PCIN, | |
118 | PORTEVENT_PCOUT, | |
119 | PORTEVENT_MMRECV, | |
120 | PORTEVENT_MMSEND, //30 | |
121 | PORTEVENT_MCRECV, | |
122 | PORTEVENT_MCSEND, | |
123 | PORTEVENT_DUALRECV, | |
124 | PORTEVENT_DUALSEND, | |
125 | PORTEVENT_UNQUALIFIED, //35 | |
126 | ||
127 | STATISTICS_VERDICT, | |
128 | STATISTICS_UNQUALIFIED, | |
129 | ||
130 | TIMEROP_READ, | |
131 | TIMEROP_START, | |
132 | TIMEROP_GUARD, //40 | |
133 | TIMEROP_STOP, | |
134 | TIMEROP_TIMEOUT, | |
135 | TIMEROP_UNQUALIFIED, | |
136 | ||
137 | USER_UNQUALIFIED, | |
138 | ||
139 | VERDICTOP_GETVERDICT, //45 | |
140 | VERDICTOP_SETVERDICT, | |
141 | VERDICTOP_FINAL, | |
142 | VERDICTOP_UNQUALIFIED, | |
143 | ||
144 | WARNING_UNQUALIFIED, | |
145 | ||
146 | // MATCHING and DEBUG should be at the end (not included in LOG_ALL) | |
147 | MATCHING_DONE, //50 | |
148 | MATCHING_TIMEOUT, | |
149 | MATCHING_PCSUCCESS, | |
150 | MATCHING_PCUNSUCC, | |
151 | MATCHING_PMSUCCESS, | |
152 | MATCHING_PMUNSUCC, //55 | |
153 | MATCHING_MCSUCCESS, | |
154 | MATCHING_MCUNSUCC, | |
155 | MATCHING_MMSUCCESS, | |
156 | MATCHING_MMUNSUCC, | |
157 | MATCHING_PROBLEM, //60 | |
158 | MATCHING_UNQUALIFIED, | |
159 | ||
160 | DEBUG_ENCDEC, | |
161 | DEBUG_TESTPORT, | |
3f84031e | 162 | DEBUG_USER, |
163 | DEBUG_FRAMEWORK, | |
164 | DEBUG_UNQUALIFIED, //66 | |
970ed795 EL |
165 | |
166 | NUMBER_OF_LOGSEVERITIES, // must follow the last individual severity | |
167 | LOG_ALL_IMPORTANT | |
168 | }; | |
169 | /// Number of main severities (plus one, because it includes LOG_NOTHING). | |
170 | static const size_t number_of_categories = 16; | |
171 | /// Main severity names. | |
172 | static const char* severity_category_names[number_of_categories]; | |
173 | /// Sub-category suffixes. | |
174 | static const char* severity_subcategory_names[NUMBER_OF_LOGSEVERITIES]; | |
175 | static const TTCN_Logger::Severity sev_categories[number_of_categories]; | |
176 | ||
177 | static const unsigned int major_version = 2; | |
178 | static const unsigned int minor_version = 2; | |
179 | ||
180 | // buffer used by the log match algorithms to buffer the output | |
181 | static char* logmatch_buffer; | |
182 | // length of the logmatch buffer | |
183 | static size_t logmatch_buffer_len; | |
184 | // the size of the log match buffer (memory allocated for it) | |
185 | static size_t logmatch_buffer_size; | |
186 | // true if the logmatch buffer was already printed in the actual log event. | |
187 | static boolean logmatch_printed; | |
188 | ||
189 | // length of the emergencylogging buffer | |
190 | static size_t emergency_logging; | |
191 | static void set_emergency_logging(size_t size); | |
192 | static size_t get_emergency_logging(); | |
193 | ||
194 | static emergency_logging_behaviour_t emergency_logging_behaviour; | |
195 | static void set_emergency_logging_behaviour(emergency_logging_behaviour_t behaviour); | |
196 | static emergency_logging_behaviour_t get_emergency_logging_behaviour(); | |
d44e3c4f | 197 | |
198 | static boolean emergency_logging_for_fail_verdict; | |
199 | static void set_emergency_logging_for_fail_verdict(boolean b); | |
200 | static boolean get_emergency_logging_for_fail_verdict(); | |
970ed795 EL |
201 | |
202 | /** @brief returns the actual length of the logmatch buffer | |
203 | This way it can be stored for later, when the buffer needs to be reverted. | |
204 | @return the length | |
205 | */ | |
206 | static size_t get_logmatch_buffer_len(); | |
207 | ||
208 | /** @brief sets the length of the logmatch buffer | |
209 | Is used to effectively revert the buffer to a previous state. | |
210 | @param new_size the new length to be set. | |
211 | */ | |
212 | static void set_logmatch_buffer_len(size_t new_size); | |
213 | ||
214 | /** @brief prints the contents of the logmatch buffer to the current event | |
215 | Writes contents of the logmatch buffer into the actual event, prefixed with | |
216 | a ',' if needed. | |
217 | */ | |
218 | static void print_logmatch_buffer(); | |
219 | ||
220 | /** @brief Format a string into the current logmatch buffer. | |
221 | @param fmt_str printf-style format string | |
222 | @callgraph | |
223 | */ | |
224 | static void log_logmatch_info(const char *fmt_str, ...) | |
225 | __attribute__ ((__format__ (__printf__, 1, 2))); | |
226 | ||
227 | struct log_mask_struct; // Forward declaration. | |
228 | private: | |
229 | static log_mask_struct console_log_mask; | |
230 | static log_mask_struct file_log_mask; | |
231 | static log_mask_struct emergency_log_mask; | |
232 | ||
233 | ||
234 | static matching_verbosity_t matching_verbosity; | |
235 | ||
236 | static timestamp_format_t timestamp_format; | |
237 | ||
238 | static source_info_format_t source_info_format; | |
239 | ||
240 | static log_event_types_t log_event_types; | |
241 | ||
242 | static struct timeval start_time; | |
243 | ||
244 | static char *executable_name; | |
245 | ||
246 | static boolean log_entity_name; | |
247 | ||
248 | static data_log_format_t data_log_format; | |
249 | ||
250 | /// Always return the single instance of the LoggerPluginManager. | |
251 | static LoggerPluginManager *get_logger_plugin_manager(); | |
252 | /// Returns the actual global logger options. The returned string must be | |
253 | /// freed by the caller. | |
254 | static char *get_logger_settings_str(); | |
255 | ||
256 | public: | |
257 | /** @brief Initialize the logger. | |
258 | ||
259 | @pre initialize_logger has not been called previously | |
260 | */ | |
261 | static void initialize_logger(); | |
262 | ||
263 | /// Frees any resources held by the logger. | |
264 | static void terminate_logger(); | |
265 | ||
266 | static bool is_logger_up(); | |
267 | ||
268 | /** @brief Initializes the logger configuration. | |
269 | ||
270 | \li sets the logfilename template | |
271 | \li sets \c file_mask to LOG_ALL | |
272 | \li sets \c console_mask to TTCN_ERROR | TTCN_WARNING | TTCN_ACTION | TTCN_TESTCASE | TTCN_STATISTICS | |
273 | \li sets \c timestamp_format = TIMESTAMP_TIME; | |
274 | \li sets \c source_info_format = SINFO_NONE; | |
275 | \li sets \c log_event_types = LOGEVENTTYPES_NO; | |
276 | \li sets \c append_file = FALSE; | |
277 | \li sets \c log_entity_name = FALSE; | |
278 | ||
279 | @pre initialize_logger() has been called. | |
280 | ||
281 | */ | |
282 | static void reset_configuration(); | |
283 | ||
284 | /** @name Setting internal members | |
285 | @{ | |
286 | */ | |
287 | /** @brief Sets executable_name. | |
288 | ||
289 | \p argv_0 is stripped of its extension and path (if any) and the result is | |
290 | assigned to \c executable_name. | |
291 | ||
292 | @param argv_0 string containing the name of the program ( \c argv[0] ) | |
293 | */ | |
294 | static void set_executable_name(const char *argv_0); | |
295 | static inline char *get_executable_name() { return executable_name; } | |
296 | ||
297 | static data_log_format_t get_log_format() { return data_log_format; } | |
298 | static void set_log_format(data_log_format_t p_data_log_format) { data_log_format = p_data_log_format; } | |
299 | ||
300 | static bool add_parameter(const logging_setting_t& logging_param); | |
301 | static void set_plugin_parameters(component component_reference, const char* component_name); | |
302 | static void load_plugins(component component_reference, const char* component_name); | |
303 | ||
304 | /** @brief Set the log filename skeleton. | |
305 | ||
306 | @param new_filename_skeleton this string is copied to \c filename_skeleton | |
307 | @param from_config TRUE if set from config file value | |
308 | */ | |
309 | static void set_file_name(const char *new_filename_skeleton, | |
310 | boolean from_config = TRUE); | |
311 | ||
312 | /// Sets start_time by calling \c gettimeofday() | |
313 | static void set_start_time(); | |
314 | ||
315 | /** @brief Set the logging mask to a log file. | |
316 | ||
317 | The mask is simply stored internally. | |
318 | @see set_component() | |
319 | ||
320 | @param cmpt a component_id_t identifying the component. | |
321 | @param new_file_mask a \c LoggingBits containing the categories | |
322 | to be logged to a file. | |
323 | */ | |
324 | static void set_file_mask(component_id_t const& cmpt, | |
325 | const Logging_Bits& new_file_mask); | |
326 | ||
327 | /** @brief Set the logging mask to the console. | |
328 | ||
329 | The mask is simply stored internally. | |
330 | @see set_component() | |
331 | ||
332 | @param cmpt a component_id_t identifying the component. | |
333 | @param new_console_mask a \c LoggingBits containing the categories to be | |
334 | logged to the console. | |
335 | */ | |
336 | static void set_console_mask(component_id_t const& cmpt, | |
337 | const Logging_Bits& new_console_mask); | |
338 | ||
339 | /** @brief Set the logging mask to the console. | |
340 | ||
341 | The mask is simply stored internally. | |
342 | @see set_component() | |
343 | ||
344 | @param cmpt a component_id_t identifying the component. | |
345 | @param new_logging_mask | |
346 | */ | |
347 | static void set_emergency_logging_mask(component_id_t const& cmpt, | |
348 | const Logging_Bits& new_logging_mask); | |
349 | ||
350 | ||
351 | static Logging_Bits const& get_file_mask(); | |
352 | ||
353 | static Logging_Bits const& get_console_mask(); | |
354 | ||
355 | static Logging_Bits const& get_emergency_logging_mask(); | |
356 | ||
357 | static void set_timestamp_format(timestamp_format_t new_timestamp_format); | |
358 | static inline timestamp_format_t get_timestamp_format() | |
359 | { return timestamp_format; } | |
360 | static void set_source_info_format(source_info_format_t new_source_info_format); | |
361 | static inline source_info_format_t get_source_info_format() | |
362 | { return source_info_format; } | |
363 | static void set_log_event_types(log_event_types_t new_log_event_types); | |
364 | static inline log_event_types_t get_log_event_types() | |
365 | { return log_event_types; } | |
366 | static void set_append_file(boolean new_append_file); | |
367 | static void set_log_entity_name(boolean new_log_entity_name); | |
368 | /** @} */ | |
369 | ||
370 | static CHARSTRING get_timestamp_str(timestamp_format_t p_timestamp_format); | |
371 | static CHARSTRING get_source_info_str(source_info_format_t p_source_info_format); | |
372 | static boolean get_log_entity_name() { return log_entity_name; } | |
373 | static char *mputstr_severity(char *str, const TTCN_Logger::Severity& sev); | |
374 | static char *mputstr_timestamp(char *str, | |
375 | timestamp_format_t p_timestamp_format, | |
376 | const struct timeval *tv); | |
377 | // Register a logger plug-in into the LoggerPluginManager from the | |
378 | // configuration file. | |
379 | static void register_plugin(const component_id_t comp, char *identifier, char *filename); | |
380 | ||
381 | static bool set_file_size(component_id_t const& comp, int p_size); | |
382 | static bool set_file_number(component_id_t const& comp, int p_number); | |
383 | static bool set_disk_full_action(component_id_t const& comp, | |
384 | disk_full_action_t p_disk_full_action); | |
385 | ||
386 | /** @brief Whether a message with the given severity should be logged to the | |
387 | log file. | |
388 | ||
389 | Checks the actual logging bits selected by set_component() | |
390 | ||
391 | @param sev logging severity | |
392 | @return \c true if it should be logged, \c false otherwise | |
393 | */ | |
394 | static boolean should_log_to_file(Severity sev); | |
395 | ||
396 | /// Like should_log_to_file() but for logging to the console. | |
397 | static boolean should_log_to_console(Severity sev); | |
398 | ||
399 | /// Like should_log_to_file() but for logging to the emergency. | |
400 | static boolean should_log_to_emergency(Severity sev); | |
401 | ||
402 | /** @brief Get the log event mask. | |
403 | ||
404 | @deprecated Please use TTCN_Logger::should_log_to_file() or | |
405 | TTCN_Logger::should_log_to_console() instead. | |
406 | */ | |
407 | static unsigned int get_mask(); | |
408 | ||
409 | static matching_verbosity_t get_matching_verbosity(); | |
410 | static void set_matching_verbosity(matching_verbosity_t v); | |
411 | ||
412 | /** @brief Handle logging of the logger's configuration settings. | |
413 | ||
414 | This function is called from Single_main.cc and Runtime.cc immediately | |
415 | after the "Host controller/Executor/Component started" message. | |
416 | However, in some cases (e.g. in the HC) the logger's settings aren't known yet | |
417 | so the content of the log message cannot be determined. | |
418 | In this situation, an empty log message is stored until the configuration | |
419 | is received, then the stored message is updated before writing. | |
420 | This method performs all three of these operations. | |
421 | ||
422 | @param opening true if called from TTCN_Logger::open_file() while writing | |
423 | the buffered messages, false otherwise. | |
424 | */ | |
425 | static void write_logger_settings(bool opening = false); | |
426 | ||
427 | /** @brief Opens the log file. | |
428 | ||
429 | Opens the file with the name returned by get_filename(). If append_file | |
430 | is true, new events are written to the end of an existing log file. | |
431 | Otherwise, the log file is truncated. | |
432 | If there are buffered events, they are written to the file. | |
433 | */ | |
434 | static void open_file(); | |
435 | static void close_file(); | |
436 | /** @brief dump all events from ring buffer to log file | |
437 | @param do_close_file if true, close the files afterwards | |
438 | */ | |
439 | static void ring_buffer_dump(bool do_close_file); | |
440 | ||
441 | /** @brief Should this event be logged? | |
442 | ||
443 | @return \c true if the the event with severity specified by | |
444 | \p event_severity should be logged to either the console or the log file, | |
445 | \c false otherwise. | |
446 | ||
447 | If the logger was not configured yet, it returns true. Otherwise, it | |
448 | masks \p event_severity with console_mask and, if the log file is opened, | |
449 | file_mask. | |
450 | */ | |
451 | static boolean log_this_event(Severity event_severity); | |
452 | ||
453 | /** @brief Format and log a message. | |
454 | ||
455 | Calls log_va_list. | |
456 | ||
457 | @param msg_severity severity | |
458 | @param fmt_str printf-style format string | |
459 | @callgraph | |
460 | */ | |
461 | static void log(Severity msg_severity, const char *fmt_str, ...) | |
462 | __attribute__ ((__format__ (__printf__, 2, 3) /*, deprecated (one day) */ )); | |
463 | ||
464 | /** @brief Sends the current event string as an error message to the MC. | |
465 | */ | |
466 | static void send_event_as_error(); | |
467 | ||
468 | static void fatal_error(const char *err_msg, ...) | |
469 | __attribute__ ((__format__ (__printf__, 1, 2), | |
470 | __noreturn__)); | |
471 | ||
472 | /** @brief Log a string without formatting. | |
473 | ||
474 | Description: | |
475 | ||
476 | @param msg_severity severity | |
477 | @param str_ptr the string | |
478 | @callgraph | |
479 | */ | |
480 | static void log_str(Severity msg_severity, const char *str_ptr ); | |
481 | ||
482 | /** @brief Format and log a list of arguments. | |
483 | ||
484 | Description: | |
485 | ||
486 | @param msg_severity severity | |
487 | @param fmt_str printf-style format string | |
488 | @param p_var variable arguments | |
489 | @callgraph | |
490 | */ | |
491 | static void log_va_list(Severity msg_severity, const char *fmt_str, | |
492 | va_list p_var); | |
493 | ||
494 | /** @brief Begin an event | |
495 | ||
496 | Events are held on a stack; the new event becomes the current event. | |
497 | ||
498 | If the logger is not yet initialized, this function does nothing. | |
499 | ||
500 | @param msg_severity severity | |
501 | @callgraph | |
502 | */ | |
503 | static void begin_event(Severity msg_severity, boolean log2str = FALSE); | |
504 | ||
505 | /** begin an event that logs to CHARSTRING */ | |
506 | static void begin_event_log2str() { begin_event(USER_UNQUALIFIED, TRUE); } | |
507 | ||
508 | /** @brief End event | |
509 | ||
510 | @pre current_event != NULL | |
511 | ||
512 | This is when the event is actually logged. | |
513 | ||
514 | @callgraph | |
515 | */ | |
516 | static void end_event(); | |
517 | ||
518 | static CHARSTRING end_event_log2str(); | |
519 | ||
520 | /** @brief Finish event. | |
521 | ||
522 | @pre current_event != NULL | |
523 | ||
524 | @callgraph | |
525 | */ | |
526 | static void finish_event(); | |
527 | ||
528 | /** @brief Format a string into the current event. | |
529 | ||
530 | @pre current_event != NULL | |
531 | ||
532 | @param fmt_str printf-style format string | |
533 | @callgraph | |
534 | */ | |
535 | static void log_event(const char *fmt_str, ...) | |
536 | __attribute__ ((__format__ (__printf__, 1, 2))); | |
537 | ||
538 | /** @brief Log event str | |
539 | ||
540 | Stores a string in the current log event without formatting. | |
541 | ||
542 | @pre current_event != NULL | |
543 | ||
544 | @param str_ptr the message | |
545 | @callgraph | |
546 | */ | |
547 | static void log_event_str(const char *str_ptr); | |
548 | ||
549 | /** @brief Format a list of arguments into the current event. | |
550 | ||
551 | @pre current_event != NULL | |
552 | ||
553 | Increases the current event's buffer as needed. | |
554 | ||
555 | @param fmt_str printf-style format string | |
556 | @param p_var variable arguments | |
557 | @callgraph | |
558 | */ | |
559 | static void log_event_va_list(const char *fmt_str, va_list p_var); | |
560 | ||
561 | // Log an unbound/uninitialized/enum value according to the current format setting | |
562 | static void log_event_unbound(); | |
563 | static void log_event_uninitialized(); | |
564 | static void log_event_enum(const char* enum_name_str, int enum_value); | |
565 | ||
566 | /** @brief Log one character into the current event. | |
567 | ||
568 | @pre current_event != NULL | |
569 | ||
570 | Appends the character \c c to the buffer of the current event. | |
571 | ||
572 | @param c the character | |
573 | @callgraph | |
574 | */ | |
575 | static void log_char(char c); | |
576 | ||
577 | /// Return \c true if \c c is a printable character, \c false otherwise. | |
578 | static boolean is_printable(unsigned char c); | |
579 | ||
580 | /** @brief Log a char. | |
581 | ||
582 | Description: | |
583 | ||
584 | @param c the character | |
585 | @callgraph | |
586 | */ | |
587 | static void log_char_escaped(unsigned char c); | |
588 | ||
589 | /** @brief Log a char into expstring_t buffer. | |
590 | ||
591 | Description: | |
592 | ||
593 | @param c the character | |
594 | @param p_buffer expstring_t buffer | |
595 | @callgraph | |
596 | */ | |
597 | static void log_char_escaped(unsigned char c, char*& p_buffer); | |
598 | ||
599 | /** @brief Log hex. | |
600 | ||
601 | Description: | |
602 | ||
603 | @param nibble | |
604 | @callgraph | |
605 | */ | |
606 | static void log_hex(unsigned char nibble); | |
607 | ||
608 | /** @brief Log an octet. | |
609 | ||
610 | Description: | |
611 | ||
612 | @param octet | |
613 | @callgraph | |
614 | */ | |
615 | static void log_octet(unsigned char octet); | |
616 | ||
617 | /** @brief Synonymous to log_char. | |
618 | ||
619 | Description: | |
620 | ||
621 | @param c | |
622 | @callgraph | |
623 | */ | |
624 | static inline void log_event(char c) { log_char(c); } | |
625 | ||
626 | /** @brief Log the OS error based on the current errno. | |
627 | Description: | |
628 | @callgraph | |
629 | */ | |
630 | static void OS_error(); | |
631 | ||
632 | // To preserve the semantic meaning of the log messages... | |
633 | /** @name New, one-per-event log functions | |
634 | * @{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
635 | static void log_timer_read(const char *timer_name, double start_val); | |
636 | static void log_timer_start(const char *timer_name, double start_val); | |
637 | static void log_timer_guard(double start_val); | |
638 | static void log_timer_stop(const char *timer_name, double stop_val); | |
639 | static void log_timer_timeout(const char *timer_name, double timeout_val); | |
640 | static void log_timer_any_timeout(); | |
641 | static void log_timer_unqualified(const char *message); | |
642 | ||
643 | static void log_setverdict(verdicttype new_verdict, verdicttype old_verdict, | |
644 | verdicttype local_verdict, const char *old_reason = NULL, const char *new_reason = NULL); | |
645 | static void log_getverdict(verdicttype verdict); | |
646 | // Handle all VERDICTOP_FINAL events. ptc_verdict/new_verdict are used only | |
647 | // for detailed PTC statistics, in all other cases they're the same. | |
648 | // - is_ptc: true if we're setting the final verdict for a PTC, false for MTC | |
649 | // - ptc_verdict: final verdict of the PTC | |
650 | // - local_verdict: the local verdict until now | |
651 | // - new_verdict: new verdict after PTC is finished | |
652 | // - verdict_reason: final verdict reason for PTC/MTC if applicable | |
653 | // - notification: enumeration value for the two fixed notification messages | |
654 | // - ptc_compref: only for detailed PTC statistics | |
655 | // - ptc_name: only for detailed PTC statistics | |
656 | static void log_final_verdict(bool is_ptc, verdicttype ptc_verdict, | |
657 | verdicttype local_verdict, verdicttype new_verdict, | |
658 | const char *verdict_reason = NULL, int notification = -1, | |
659 | int ptc_compref = UNBOUND_COMPREF, const char *ptc_name = NULL); | |
660 | ||
661 | static void log_testcase_started (const qualified_name& testcase_name); | |
662 | static void log_testcase_finished(const qualified_name& testcase_name, | |
663 | verdicttype verdict, | |
664 | const char *reason); | |
665 | static void log_controlpart_start_stop(const char *module_name, int finished); | |
666 | static void log_controlpart_errors(unsigned int error_count); | |
667 | ||
668 | static void log_verdict_statistics(size_t none_count, double none_percent, | |
669 | size_t pass_count, double pass_percent, | |
670 | size_t inconc_count, double inconc_percent, | |
671 | size_t fail_count, double fail_percent, | |
672 | size_t error_count, double error_percent); | |
673 | ||
674 | static void log_defaultop_activate (const char *name, int id); | |
675 | static void log_defaultop_deactivate(const char *name, int id); | |
676 | static void log_defaultop_exit (const char *name, int id, int x); | |
677 | ||
678 | /// EXECUTOR_RUNTIME, fixed strings only (no params) | |
679 | static void log_executor_runtime(int reason); | |
680 | /// EXECUTOR_RUNTIME, messages with parameters | |
681 | static void log_HC_start(const char *host); | |
682 | static void log_fd_limits(int fd_limit, long fd_set_size); | |
683 | static void log_testcase_exec(const char *module, const char *tc); | |
684 | static void log_module_init(const char *module, bool finish = false); | |
685 | static void log_mtc_created(long pid); | |
686 | ||
687 | /// EXECUTOR_CONFIGDATA | |
688 | /// @param str module name, config file or NULL | |
689 | static void log_configdata(int reason, const char *str = NULL); | |
690 | ||
691 | static void log_executor_component(int reason); | |
692 | ||
693 | static void log_executor_misc(int reason, const char *name, const char *address, | |
694 | int port); | |
695 | ||
696 | static void log_extcommand(extcommand_t action, const char *cmd); | |
697 | //static void log_extcommand_success(const char *cmd); | |
698 | ||
699 | static void log_matching_done(const char *type, int ptc, | |
700 | const char *return_type, int reason); | |
701 | ||
702 | static void log_matching_problem(int reason, int operation, | |
703 | boolean check, boolean anyport, const char *port_name = NULL); | |
704 | ||
705 | static void log_matching_success(int port_type, const char *port_name, int compref, | |
706 | const CHARSTRING& info); | |
707 | static void log_matching_failure(int port_type, const char *port_name, int compref, | |
708 | int reason, const CHARSTRING& info); | |
709 | ||
710 | static void log_matching_timeout(const char *timer_name); | |
711 | ||
712 | static void log_portconnmap(int operation, int src_compref, const char *src_port, | |
713 | int dst_compref, const char *dst_port); | |
714 | ||
715 | static void log_par_ptc(int reason, | |
716 | const char *module = NULL, const char *name = NULL, int compref = 0, | |
717 | const char *compname = NULL, const char *tc_loc = NULL, | |
718 | int alive_pid = 0, int status = 0); | |
719 | ||
720 | static void log_port_queue(int operation, const char *port_name, int compref, | |
721 | int id, const CHARSTRING& address, const CHARSTRING& param); | |
722 | ||
723 | static void log_port_state(int operation, const char *port_name); | |
724 | ||
725 | static void log_procport_send(const char *portname, int operation, int compref, | |
726 | const CHARSTRING& system, const CHARSTRING& param); | |
727 | static void log_procport_recv(const char *portname, int operation, int compref, | |
728 | boolean check, const CHARSTRING& param, int id); | |
729 | static void log_msgport_send(const char *portname, int compref, | |
730 | const CHARSTRING& param); | |
731 | static void log_msgport_recv(const char *portname, int operation, int compref, | |
732 | const CHARSTRING& system, const CHARSTRING& param, int id); | |
733 | ||
734 | static void log_dualport_map(boolean incoming, const char *target_type, | |
735 | const CHARSTRING& value, int id); | |
736 | static void log_dualport_discard(boolean incoming, const char *target_type, | |
737 | const char *port_name, boolean unhaldled); | |
738 | ||
739 | static void log_port_misc(int reason, const char *port_name, | |
740 | int remote_component = NULL_COMPREF, const char *remote_port = NULL, | |
741 | const char *ip_address = NULL, int tcp_port = -1, int new_size = 0); | |
742 | ||
743 | static void log_random(int action, double v, unsigned long u); | |
744 | ||
745 | static void clear_parameters(); | |
746 | /** @} TODO: More * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | |
747 | }; | |
748 | ||
749 | /** @name #defines for backward-compatibility. | |
750 | These #defines (TTCN_ERROR, TTCN_WARNING, ... TTCN_DEBUG) | |
751 | are source-compatible (but \b not binary compatible) with the original #defines | |
752 | ||
753 | @note The values are not bit masks. Expressions like | |
754 | @code LOG_ALL | TTCN_DEBUG @endcode will not work correctly. | |
755 | ||
756 | @{ | |
757 | */ | |
758 | #define TTCN_ERROR TTCN_Logger::ERROR_UNQUALIFIED | |
759 | #define TTCN_WARNING TTCN_Logger::WARNING_UNQUALIFIED | |
760 | #define TTCN_PORTEVENT TTCN_Logger::PORTEVENT_UNQUALIFIED | |
761 | #define TTCN_TIMEROP TTCN_Logger::TIMEROP_UNQUALIFIED | |
762 | #define TTCN_VERDICTOP TTCN_Logger::VERDICTOP_UNQUALIFIED | |
763 | #define TTCN_DEFAULTOP TTCN_Logger::DEFAULTOP_UNQUALIFIED | |
764 | #define TTCN_ACTION TTCN_Logger::ACTION_UNQUALIFIED | |
765 | #define TTCN_TESTCASE TTCN_Logger::TESTCASE_UNQUALIFIED | |
766 | #define TTCN_FUNCTION TTCN_Logger::FUNCTION_UNQUALIFIED | |
767 | #define TTCN_USER TTCN_Logger::USER_UNQUALIFIED | |
768 | #define TTCN_STATISTICS TTCN_Logger::STATISTICS_UNQUALIFIED | |
769 | #define TTCN_PARALLEL TTCN_Logger::PARALLEL_UNQUALIFIED | |
770 | #define TTCN_EXECUTOR TTCN_Logger::EXECUTOR_UNQUALIFIED | |
771 | #define TTCN_MATCHING TTCN_Logger::MATCHING_UNQUALIFIED | |
772 | #define TTCN_DEBUG TTCN_Logger::DEBUG_UNQUALIFIED | |
773 | #define LOG_NOTHING TTCN_Logger::NOTHING_TO_LOG | |
774 | #define LOG_ALL TTCN_Logger::LOG_ALL_IMPORTANT | |
775 | /** @} */ | |
776 | ||
777 | extern TTCN_Logger TTCN_logger; | |
778 | ||
779 | class TTCN_Location { | |
780 | public: | |
781 | enum entity_type_t { LOCATION_UNKNOWN, LOCATION_CONTROLPART, | |
782 | LOCATION_TESTCASE, LOCATION_ALTSTEP, LOCATION_FUNCTION, | |
783 | LOCATION_EXTERNALFUNCTION, LOCATION_TEMPLATE }; | |
784 | protected: | |
785 | const char *file_name; | |
786 | unsigned int line_number; | |
787 | entity_type_t entity_type; | |
788 | const char *entity_name; | |
789 | TTCN_Location *inner_location, *outer_location; | |
790 | static TTCN_Location *innermost_location, *outermost_location; | |
791 | friend class LoggerPluginManager; | |
792 | public: | |
793 | /** @brief Create a TTCN_Location object. | |
794 | ||
795 | Objects of this class are created by code generated by the TTCN-3 compiler. | |
796 | ||
797 | @param par_file_name source file of the call site | |
798 | @param par_line_number line number of the call site | |
799 | @param par_entity_type controlpart/testcase/altstep/function/...etc | |
800 | @param par_entity_name entity name of the caller | |
801 | ||
802 | @note The constructor copies the par_file_name and par_entity_name | |
803 | pointers but not the strings. The caller must ensure that the strings | |
804 | don't go out of scope before the TTCN_Location object. | |
805 | */ | |
806 | TTCN_Location(const char *par_file_name, unsigned int par_line_number, | |
807 | entity_type_t par_entity_type = LOCATION_UNKNOWN, | |
808 | const char *par_entity_name = NULL); | |
809 | virtual ~TTCN_Location(); | |
810 | ||
811 | virtual void update_lineno(unsigned int new_lineno); | |
812 | ||
813 | /** @brief Write the current location information to a string. | |
814 | * | |
815 | * @param print_outers \c true to print all the callers | |
816 | * (in the style of SourceInfo = Stack) | |
817 | * @param print_innermost \c true to print the current (innermost) location | |
818 | * @param print_entity_name \c true to print the type | |
819 | * (control part/test case/altstep/function/template) and name | |
820 | * of the current location. | |
821 | * @note print_innermost is always TRUE (there is never a call with FALSE) | |
822 | * | |
823 | * @return an expstring_t. The caller is responsible for calling Free() | |
824 | **/ | |
825 | static char *print_location(boolean print_outers, boolean print_innermost, | |
826 | boolean print_entity_name); | |
827 | /** @brief Remove location information from a string. | |
828 | * | |
829 | * @param [in,out] par_str the string to modify. | |
830 | * @pre par_str was allocated by Malloc, or is NULL. | |
831 | * It may be an expstring_t. | |
832 | * | |
833 | * The function copies characters from \p par_str to a temporary string, | |
834 | * except characters between parentheses. Then it calls | |
835 | * \c Free(par_str) and replaces \p par_str with the temporary. | |
836 | * | |
837 | **/ | |
838 | static void strip_entity_name(char*& par_str); | |
f08ff9ca BB |
839 | |
840 | /** @brief Return the innermost location's line number | |
841 | **/ | |
842 | static unsigned int get_line_number(); | |
970ed795 EL |
843 | protected: |
844 | char *append_contents(char *par_str, boolean print_entity_name) const; | |
845 | }; | |
846 | ||
847 | class TTCN_Location_Statistics: public TTCN_Location | |
848 | { | |
849 | public: | |
850 | TTCN_Location_Statistics(const char *par_file_name, unsigned int par_line_number, | |
851 | entity_type_t par_entity_type = LOCATION_UNKNOWN, | |
852 | const char *par_entity_name = NULL); | |
853 | ~TTCN_Location_Statistics(); | |
854 | void update_lineno(unsigned int new_lineno); | |
855 | static void init_file_lines(const char *file_name, const int line_nos[], size_t line_nos_len); | |
856 | static void init_file_functions(const char *file_name, const char *function_names[], size_t function_names_len); | |
857 | }; | |
858 | ||
859 | /// Restores the original log format when running out of scope: use as local variable | |
860 | class Logger_Format_Scope { | |
861 | private: | |
862 | TTCN_Logger::data_log_format_t orig_log_format; | |
863 | public: | |
864 | Logger_Format_Scope(TTCN_Logger::data_log_format_t p_log_format) { orig_log_format=TTCN_Logger::get_log_format(); TTCN_Logger::set_log_format(p_log_format); } | |
865 | ~Logger_Format_Scope() { TTCN_Logger::set_log_format(orig_log_format); } | |
866 | }; | |
867 | ||
868 | #endif |