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