clang specific define in Runtime.cc
[deliverable/titan.core.git] / core / LoggerPluginManager.cc
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 * Kovacs, Ferenc
13 * Raduly, Csaba
14 * Szabados, Kristof
15 * Zalanyi, Balazs Andor
16 * Pandi, Krisztian
17 *
18 ******************************************************************************/
19 #include "LoggerPluginManager.hh"
20 #include "LoggerPlugin.hh"
21 #include "TitanLoggerApi.hh"
22 #include "Runtime.hh"
23 #include "Logger.hh"
24 #include "ILoggerPlugin.hh"
25
26 #include "../common/dbgnew.hh"
27 #include "../core/Error.hh"
28 #include "../common/static_check.h"
29
30 #include <assert.h>
31 #include <string.h>
32
33
34 #ifdef WIN32
35 // On Cygwin/MinGW it's called DLL.
36 #define SO_EXTENSION "dll"
37 #else
38 #define SO_EXTENSION "so"
39 #endif
40
41 namespace API = TitanLoggerApi;
42
43 extern "C" cb_create_plugin create_legacy_logger;
44
45 RingBuffer::~RingBuffer()
46 {
47 if (buffer != NULL) {
48 delete[] buffer;
49 }
50 }
51
52 bool RingBuffer::get(TitanLoggerApi::TitanLogEvent& data)
53 {
54 if(tail == head)
55 return false;
56
57 data = buffer[tail];
58 tail = (tail +1) % (size + 1);
59
60 return true;
61 }
62
63 void RingBuffer::put(TitanLoggerApi::TitanLogEvent data)
64 {
65 buffer[head] = data;
66 head = (head + 1) % (size + 1);
67
68 if (head == tail) {
69 tail = (tail +1 ) % (size + 1);
70 }
71 }
72
73 void RingBuffer::set_size(unsigned int new_size)
74 {
75 if (buffer != NULL) return;
76
77 size = new_size;
78 buffer = new TitanLoggerApi::TitanLogEvent[size + 1];
79 }
80
81 void RingBuffer::clear()
82 {
83 head = tail = 0;
84 }
85
86 LoggerPluginManager::LoggerPluginManager()
87 : n_plugins_(1), plugins_(new LoggerPlugin*[1]), entry_list_(NULL),
88 current_event_(NULL), logparams_head(NULL), logparams_tail(NULL),
89 logplugins_head(NULL), logplugins_tail(NULL)
90 {
91 this->plugins_[0] = new LoggerPlugin(&create_legacy_logger);
92 this->plugins_[0]->load();
93 }
94
95 LoggerPluginManager::~LoggerPluginManager()
96 {
97 // It can happen that there're some unlogged events still in the buffer. E.g.
98 // an exception is thrown and no `end_event()' etc. is called.
99 while (this->entry_list_ != NULL) {
100 LogEntry *next_entry = this->entry_list_->next_entry_;
101 for (size_t i = 0; i < this->n_plugins_; ++i) {
102 if (this->plugins_[i]->is_configured()) {
103 this->plugins_[i]->log(this->entry_list_->event_, true, false, false);
104 }
105 }
106 delete this->entry_list_;
107 this->entry_list_ = next_entry;
108 }
109 this->entry_list_ = NULL;
110
111 for (size_t i = 0; i < this->n_plugins_; ++i) {
112 delete this->plugins_[i];
113 }
114 delete [] this->plugins_;
115 this->plugins_ = NULL;
116 this->n_plugins_ = 0;
117
118 if (this->current_event_ != NULL) {
119 fputs("Some logging events in the buffer were not finished properly in "
120 "the plug-in manager.\n", stderr);
121 while (this->current_event_) {
122 ActiveEvent *outer_event = this->current_event_->outer_event_;
123 Free(this->current_event_->event_str_);
124 delete this->current_event_;
125 this->current_event_ = outer_event;
126 }
127 this->current_event_ = NULL;
128 }
129 }
130
131 void LoggerPluginManager::ring_buffer_dump(bool do_close_file)
132 {
133 // in case of buffer all, flush the content of the ring buffer
134 if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_ALL) {
135 TitanLoggerApi::TitanLogEvent ring_event;
136 // get all the events from the ring: buffer
137 while (!ring_buffer.isEmpty()) {
138 if (ring_buffer.get(ring_event)) {
139 internal_log_to_all(ring_event, true, false, false); // buffer all: DO NOT log in separate file
140 }
141 }
142 }
143
144 if (do_close_file) {
145 for (size_t i = 0; i < this->n_plugins_; ++i) {
146 plugins_[i]->close_file();
147 }
148 }
149
150 ring_buffer.clear();
151 }
152
153 void LoggerPluginManager::register_plugin(const component_id_t comp,
154 char *identifier, char *filename)
155 {
156 logging_plugin_t *newplugin = new logging_plugin_t;
157 newplugin->component.id_selector = comp.id_selector;
158 switch (newplugin->component.id_selector) {
159 case COMPONENT_ID_NAME: newplugin->component.id_name = mcopystr(comp.id_name); break;
160 case COMPONENT_ID_COMPREF: newplugin->component.id_compref = comp.id_compref; break;
161 default: newplugin->component.id_name = NULL; break;
162 }
163 newplugin->identifier = identifier;
164 newplugin->filename = filename;
165 newplugin->next = NULL;
166 if (logplugins_head == NULL) logplugins_head = newplugin;
167 if (logplugins_tail != NULL) logplugins_tail->next = newplugin;
168 logplugins_tail = newplugin;
169 }
170
171 void LoggerPluginManager::load_plugins(component component_reference,
172 const char *component_name)
173 {
174 if (logplugins_head == NULL) {
175 // The LoggerPlugins option was not used in the configuration file.
176 // The LegacyLogger plug-in is already active; nothing to do.
177 return;
178 }
179
180 for (logging_plugin_t *p = logplugins_head; p != NULL; p = p->next) {
181 switch (p->component.id_selector) {
182 case COMPONENT_ID_NAME:
183 if (component_name != NULL &&
184 !strcmp(p->component.id_name, component_name))
185 load_plugin(p->identifier, p->filename);
186 break;
187 case COMPONENT_ID_COMPREF:
188 if (p->component.id_compref == component_reference)
189 load_plugin(p->identifier, p->filename);
190 break;
191 case COMPONENT_ID_ALL:
192 load_plugin(p->identifier, p->filename);
193 break;
194 default:
195 break;
196 }
197 }
198 }
199
200 void LoggerPluginManager::load_plugin(const char *identifier,
201 const char *filename)
202 {
203 bool is_legacylogger =
204 !strncasecmp(identifier, "LegacyLogger", 12) ? true : false;
205 static bool legacylogger_needed = false;
206 if (!legacylogger_needed && is_legacylogger) legacylogger_needed = true;
207 // LegacyLogger was listed explicitly. Otherwise, it's disabled. It is
208 // always loaded as the first element of the list.
209 this->plugins_[0]->set_configured(legacylogger_needed);
210
211 if (is_legacylogger) {
212 if (filename != NULL)
213 TTCN_warning("The `LegacyLogger' plug-in should not have a path");
214 return; // It's already in the list.
215 }
216
217 char *pluginname = (filename != NULL && strlen(filename) > 0) ?
218 mcopystr(filename) : mputprintf(NULL, "%s.%s", identifier, SO_EXTENSION);
219 size_t pluginname_length = strlen(pluginname);
220 for (size_t i = 0; i < this->n_plugins_; ++i) {
221 // Our only static plug-in doesn't have a name, skip it. If we have a
222 // name, we have a dynamic plug-in.
223 if (!this->plugins_[i]->filename_)
224 continue;
225 if (!strncmp(pluginname, this->plugins_[i]->filename_,
226 pluginname_length)) {
227 TTCN_warning("A plug-in from the same path `%s' is already active, "
228 "skipping plug-in", pluginname);
229 Free(pluginname);
230 return;
231 }
232 }
233
234 this->plugins_ = (LoggerPlugin **)Realloc(this->plugins_,
235 ++this->n_plugins_ * sizeof(LoggerPlugin *));
236 this->plugins_[this->n_plugins_ - 1] = new LoggerPlugin(pluginname);
237 // Doesn't matter if load fails...
238 Free(pluginname);
239 this->plugins_[this->n_plugins_ - 1]->load();
240 }
241
242 extern bool operator==(const component_id_t& left, const component_id_t& right);
243
244 bool LoggerPluginManager::add_parameter(const logging_setting_t& logging_param)
245 {
246 bool duplication_warning = false;
247
248 for (logging_setting_t *par = logparams_head; par != NULL; par = par->nextparam) {
249 bool for_all_components = logging_param.component.id_selector == COMPONENT_ID_ALL || par->component.id_selector == COMPONENT_ID_ALL;
250 bool for_all_plugins = logging_param.plugin_id == NULL || par->plugin_id == NULL ||
251 !strcmp(logging_param.plugin_id, "*") || !strcmp(par->plugin_id, "*");
252 bool component_overlaps = for_all_components || logging_param.component == par->component;
253 bool plugin_overlaps = for_all_plugins || !strcmp(logging_param.plugin_id, par->plugin_id);
254 bool parameter_overlaps = logging_param.logparam.log_param_selection == par->logparam.log_param_selection;
255 if (parameter_overlaps && logging_param.logparam.log_param_selection == LP_PLUGIN_SPECIFIC)
256 parameter_overlaps = strcmp(logging_param.logparam.param_name, par->logparam.param_name) == 0;
257 duplication_warning = component_overlaps && plugin_overlaps && parameter_overlaps;
258 if (duplication_warning)
259 break;
260 }
261
262 logging_setting_t *newparam = new logging_setting_t(logging_param);
263 newparam->nextparam = NULL;
264 if (logparams_head == NULL) logparams_head = newparam;
265 if (logparams_tail != NULL) logparams_tail->nextparam = newparam;
266 logparams_tail = newparam;
267
268 return duplication_warning;
269 }
270
271 void LoggerPluginManager::set_parameters(component component_reference,
272 const char *component_name)
273 {
274 if (logparams_head == NULL) return;
275 for (logging_setting_t *par = logparams_head; par != NULL; par = par->nextparam)
276 switch (par->component.id_selector) {
277 case COMPONENT_ID_NAME:
278 if (component_name != NULL &&
279 !strcmp(par->component.id_name, component_name)) {
280 apply_parameter(*par);
281 }
282 break;
283 case COMPONENT_ID_COMPREF:
284 if (par->component.id_compref == component_reference)
285 apply_parameter(*par);
286 break;
287 case COMPONENT_ID_ALL:
288 apply_parameter(*par);
289 break;
290 default:
291 break;
292 }
293 }
294
295 void LoggerPluginManager::apply_parameter(const logging_setting_t& logparam)
296 {
297 if (logparam.plugin_id && !(strlen(logparam.plugin_id) == 1 && !strncmp(logparam.plugin_id, "*", 1))) {
298 // The parameter refers to a specific plug-in. If the plug-in is not
299 // found the execution will stop.
300 LoggerPlugin *plugin = find_plugin(logparam.plugin_id);
301 if (plugin != NULL) {
302 send_parameter_to_plugin(plugin, logparam);
303 } else {
304 TTCN_Logger::fatal_error("Logger plug-in with name `%s' was not found.", logparam.plugin_id);
305 }
306 } else {
307 // The parameter refers to all plug-ins.
308 for (size_t i = 0; i < this->n_plugins_; i++) {
309 send_parameter_to_plugin(this->plugins_[i], logparam);
310 }
311 }
312 }
313
314 void LoggerPluginManager::send_parameter_to_plugin(LoggerPlugin *plugin,
315 const logging_setting_t& logparam)
316 {
317 switch (logparam.logparam.log_param_selection) {
318 case LP_FILEMASK:
319 TTCN_Logger::set_file_mask(logparam.component,
320 logparam.logparam.logoptions_val);
321 break;
322 case LP_CONSOLEMASK:
323 TTCN_Logger::set_console_mask(logparam.component,
324 logparam.logparam.logoptions_val);
325 break;
326 case LP_LOGFILESIZE:
327 plugin->set_file_size(logparam.logparam.int_val);
328 break;
329 case LP_LOGFILENUMBER:
330 plugin->set_file_number(logparam.logparam.int_val);
331 break;
332 case LP_DISKFULLACTION:
333 plugin->set_disk_full_action(logparam.logparam.disk_full_action_value);
334 break;
335 case LP_LOGFILE:
336 plugin->set_file_name(logparam.logparam.str_val, true);
337 break;
338 case LP_TIMESTAMPFORMAT:
339 TTCN_Logger::set_timestamp_format(logparam.logparam.timestamp_value);
340 break;
341 case LP_SOURCEINFOFORMAT:
342 TTCN_Logger::set_source_info_format(logparam.logparam.source_info_value);
343 break;
344 case LP_APPENDFILE:
345 plugin->set_append_file(logparam.logparam.bool_val);
346 break;
347 case LP_LOGEVENTTYPES:
348 TTCN_Logger::set_log_event_types(logparam.logparam.log_event_types_value);
349 break;
350 case LP_LOGENTITYNAME:
351 TTCN_Logger::set_log_entity_name(logparam.logparam.bool_val);
352 break;
353 case LP_MATCHINGHINTS:
354 TTCN_Logger::set_matching_verbosity(logparam.logparam.matching_verbosity_value);
355 break;
356 case LP_PLUGIN_SPECIFIC:
357 plugin->set_parameter(logparam.logparam.param_name, logparam.logparam.str_val);
358 break;
359 case LP_EMERGENCY:
360 TTCN_Logger::set_emergency_logging(logparam.logparam.emergency_logging);
361 ring_buffer.set_size(TTCN_Logger::get_emergency_logging());
362 break;
363 case LP_EMERGENCYBEHAVIOR:
364 TTCN_Logger::set_emergency_logging_behaviour(logparam.logparam.emergency_logging_behaviour_value);
365 break;
366 case LP_EMERGENCYMASK:
367 TTCN_Logger::set_emergency_logging_mask(logparam.component,
368 logparam.logparam.logoptions_val);
369 break;
370 case LP_EMERGENCYFORFAIL:
371 TTCN_Logger::set_emergency_logging_for_fail_verdict(logparam.logparam.bool_val);
372 break;
373 default:
374 break;
375 }
376 }
377
378 void LoggerPluginManager::clear_param_list()
379 {
380 for (logging_setting_t *par = logparams_head; par != NULL;) {
381 Free(par->plugin_id);
382 switch (par->logparam.log_param_selection) {
383 case LP_PLUGIN_SPECIFIC:
384 Free(par->logparam.param_name);
385 // no break
386 case LP_LOGFILE:
387 Free(par->logparam.str_val);
388 break;
389 default:
390 break;
391 }
392 if (par->component.id_selector == COMPONENT_ID_NAME)
393 Free(par->component.id_name);
394 logging_setting_t *tmp = par;
395 par = par->nextparam;
396 delete tmp;
397 }
398 logparams_head = logparams_tail = NULL;
399 }
400
401 void LoggerPluginManager::clear_plugin_list()
402 {
403 for (logging_plugin_t *plugin = logplugins_head; plugin != NULL;) {
404 if (plugin->component.id_selector == COMPONENT_ID_NAME)
405 Free(plugin->component.id_name);
406 Free(plugin->identifier);
407 Free(plugin->filename);
408 logging_plugin_t *tmp = plugin;
409 plugin = plugin->next;
410 delete tmp;
411 }
412 logplugins_head = logplugins_tail = NULL;
413 }
414
415 void LoggerPluginManager::set_file_name(const char *new_filename_skeleton,
416 bool from_config)
417 {
418 for (size_t i = 0; i < this->n_plugins_; ++i)
419 this->plugins_[i]->set_file_name(new_filename_skeleton, from_config);
420 }
421
422 void LoggerPluginManager::reset()
423 {
424 for (size_t i = 0; i < this->n_plugins_; ++i)
425 this->plugins_[i]->reset();
426 }
427
428 void LoggerPluginManager::set_append_file(bool new_append_file)
429 {
430 for (size_t i = 0; i < this->n_plugins_; ++i)
431 this->plugins_[i]->set_append_file(new_append_file);
432 }
433
434 bool LoggerPluginManager::set_file_size(component_id_t const& /*comp*/, int p_size)
435 {
436 bool ret_val = false;
437 for (size_t i = 0; i < this->n_plugins_; ++i)
438 if (this->plugins_[i]->set_file_size(p_size))
439 ret_val = true;
440 return ret_val;
441 }
442
443 bool LoggerPluginManager::set_file_number(component_id_t const& /*comp*/, int p_number)
444 {
445 bool ret_val = false;
446 for (size_t i = 0; i < this->n_plugins_; ++i)
447 if (this->plugins_[i]->set_file_number(p_number))
448 ret_val = true;
449 return ret_val;
450 }
451
452 bool LoggerPluginManager::set_disk_full_action(component_id_t const& /*comp*/,
453 TTCN_Logger::disk_full_action_t p_disk_full_action)
454 {
455 bool ret_val = false;
456 for (size_t i = 0; i < this->n_plugins_; ++i)
457 if (this->plugins_[i]->set_disk_full_action(p_disk_full_action))
458 ret_val = true;
459 return ret_val;
460 }
461
462 void LoggerPluginManager::open_file()
463 {
464 static bool is_first = true;
465 bool free_entry_list = false;
466 assert(this->n_plugins_ > 0);
467 // In case of `EXECUTOR_LOGOPTIONS' write updated
468 // `write_logger_settings(true)'. Try to log the buffered events, they not
469 // necessarily be logged otherwise.
470 for (size_t i = 0; i < this->n_plugins_; ++i) {
471 this->plugins_[i]->open_file(is_first);
472 if (this->plugins_[i]->is_configured()) {
473 free_entry_list = true;
474 LogEntry *entry = this->entry_list_, *next_entry = NULL;
475 while (entry != NULL) {
476 next_entry = entry->next_entry_;
477 if ((TTCN_Logger::Severity)(int)entry->event_.severity() ==
478 TTCN_Logger::EXECUTOR_LOGOPTIONS) {
479 char *new_log_message = TTCN_Logger::get_logger_settings_str();
480 entry->event_.logEvent().choice().executorEvent().choice().logOptions() =
481 CHARSTRING(mstrlen(new_log_message), new_log_message);
482 Free(new_log_message);
483 }
484 this->plugins_[i]->log(entry->event_, true, false, false);
485 entry = next_entry;
486 }
487 }
488 }
489 if (free_entry_list) {
490 while (this->entry_list_ != NULL) {
491 LogEntry *next_entry = this->entry_list_->next_entry_;
492 delete this->entry_list_;
493 this->entry_list_ = next_entry;
494 }
495 this->entry_list_ = NULL;
496 }
497 is_first = false;
498 }
499
500 void LoggerPluginManager::close_file()
501 {
502
503 while (this->current_event_ != NULL)
504 finish_event();
505
506 ring_buffer_dump(true);
507 }
508
509 void LoggerPluginManager::unload_plugins()
510 {
511 for (size_t i = 0; i < n_plugins_; ++i)
512 plugins_[i]->unload();
513 }
514
515 void LoggerPluginManager::fill_common_fields(API::TitanLogEvent& event,
516 const TTCN_Logger::Severity& severity)
517 {
518 // Check at compile time that entity type can be directly assigned.
519 ENSURE_EQUAL(API::LocationInfo_ent__type::unknown , TTCN_Location::LOCATION_UNKNOWN);
520 ENSURE_EQUAL(API::LocationInfo_ent__type::controlpart, TTCN_Location::LOCATION_CONTROLPART);
521 ENSURE_EQUAL(API::LocationInfo_ent__type::testcase__ , TTCN_Location::LOCATION_TESTCASE);
522 ENSURE_EQUAL(API::LocationInfo_ent__type::altstep__ , TTCN_Location::LOCATION_ALTSTEP);
523 ENSURE_EQUAL(API::LocationInfo_ent__type::function__ , TTCN_Location::LOCATION_FUNCTION);
524 ENSURE_EQUAL(API::LocationInfo_ent__type::external__function, TTCN_Location::LOCATION_EXTERNALFUNCTION);
525 ENSURE_EQUAL(API::LocationInfo_ent__type::template__ , TTCN_Location::LOCATION_TEMPLATE);
526
527 // The detailed timestamp is used by the plug-ins. Don't stringify in this
528 // stage. E.g. DISKFULL_RETRY uses these for comparison. TODO: Severity
529 // should be an optional field, since the type of the event (in the XSD) is
530 // always clear. It's now used to handle unhandled events.
531 struct timeval tv;
532 if (gettimeofday(&tv, NULL) < 0)
533 TTCN_Logger::fatal_error("The gettimeofday() system call failed.");
534 event.timestamp() = API::TimestampType(tv.tv_sec, tv.tv_usec);
535 TTCN_Logger::source_info_format_t source_info_format =
536 TTCN_Logger::get_source_info_format();
537 API::TitanLogEvent_sourceInfo__list& srcinfo = event.sourceInfo__list();
538 srcinfo = NULL_VALUE; // Make sure it's bound.
539 if (source_info_format != TTCN_Logger::SINFO_NONE) {
540 if (TTCN_Location::innermost_location != NULL) {
541 size_t num_locations = 0;
542 for (TTCN_Location *iter = TTCN_Location::outermost_location; iter != NULL; iter = iter->inner_location) {
543 API::LocationInfo& loc = srcinfo[num_locations++];
544 loc.filename() = iter->file_name;
545 loc.line() = iter->line_number;
546 loc.ent__type() = iter->entity_type;
547 loc.ent__name() = iter->entity_name;
548 }
549 }
550 }
551 event.severity() = severity;
552 }
553
554 void LoggerPluginManager::internal_prebuff_logevent(const TitanLoggerApi::TitanLogEvent& event)
555 {
556 LogEntry *new_entry = new LogEntry;
557 new_entry->event_ = event;
558 new_entry->next_entry_ = NULL;
559 if (!this->entry_list_) {
560 this->entry_list_ = new_entry;
561 } else {
562 LogEntry *current_entry = this->entry_list_;
563 for (; current_entry; current_entry = current_entry->next_entry_)
564 if (!current_entry->next_entry_) break;
565 current_entry->next_entry_ = new_entry;
566 }
567 }
568
569 void LoggerPluginManager::internal_log_prebuff_logevent()
570 {
571 LogEntry *entry = this->entry_list_, *next_entry = NULL;
572 while (entry != NULL) {
573 next_entry = entry->next_entry_;
574 if ((TTCN_Logger::Severity)(int)entry->event_.severity() ==
575 TTCN_Logger::EXECUTOR_LOGOPTIONS) {
576 char *new_log_message = TTCN_Logger::get_logger_settings_str();
577 entry->event_.logEvent().choice().executorEvent().choice().logOptions() =
578 CHARSTRING(mstrlen(new_log_message), new_log_message);
579 Free(new_log_message);
580 }
581 internal_log_to_all(entry->event_, true, false, false);
582 delete entry;
583 entry = next_entry;
584 }
585
586 this->entry_list_ = NULL;
587 }
588
589 void LoggerPluginManager::internal_log_to_all(const TitanLoggerApi::TitanLogEvent& event,
590 bool log_buffered, bool separate_file, bool use_emergency_mask)
591 {
592 for (size_t i = 0; i < this->n_plugins_; ++i) {
593 if (this->plugins_[i]->is_configured()) {
594 this->plugins_[i]->log(event, log_buffered, separate_file, use_emergency_mask);
595 }
596 }
597 }
598
599 bool LoggerPluginManager::plugins_ready() const
600 {
601 for (size_t i = 0; i < this->n_plugins_; ++i) {
602 if (this->plugins_[i]->is_configured()) {
603 return true;
604 }
605 }
606 return false;
607 }
608
609 void LoggerPluginManager::log(const API::TitanLogEvent& event)
610 {
611 if (!plugins_ready()) {
612 // buffer quick events
613 internal_prebuff_logevent(event);
614 return;
615 }
616
617 // Init phase, log prebuffered events first if any.
618 internal_log_prebuff_logevent();
619
620 if (TTCN_Logger::get_emergency_logging() == 0) {
621 // If emergency buffering is not needed log the event
622 internal_log_to_all(event, false, false, false);
623 return;
624 }
625
626 // Log the buffered events first, if any. In the current scheme,
627 // open_file() has already flushed this buffer at this time.
628 // Send the event to the plugin if it is necessary.
629 // ring_buffer content fill up
630 if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_MASKED) {
631 //ToDo: do it nicer
632 //if(TTCN_Logger::log_this_event((TTCN_Logger::Severity)(int)event.severity())){
633 internal_log_to_all(event, true, false, false);
634 if (!TTCN_Logger::should_log_to_file((TTCN_Logger::Severity)(int)event.severity()) &&
635 TTCN_Logger::should_log_to_emergency((TTCN_Logger::Severity)(int)event.severity())) {
636 ring_buffer.put(event);
637 }
638 } else if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_ALL) {
639 if (ring_buffer.isFull()) {
640 TitanLoggerApi::TitanLogEvent ring_event;
641 // the ring buffer is full, get the the oldest event
642 // check does the user want this to be logged
643 if (ring_buffer.get(ring_event)) {
644 internal_log_to_all(ring_event, true, false, false);
645 } else {
646 // it is not wanted by the user, throw it away
647 }
648 }
649 ring_buffer.put(event);
650 }
651 // ERROR or setverdict(fail), flush the ring buffer content
652 if ((TTCN_Logger::Severity)(int)event.severity() == TTCN_Logger::ERROR_UNQUALIFIED ||
653 (TTCN_Logger::get_emergency_logging_for_fail_verdict() &&
654 (TTCN_Logger::Severity)(int)event.severity() == TTCN_Logger::VERDICTOP_SETVERDICT &&
655 event.logEvent().choice().verdictOp().choice().setVerdict().newVerdict() == API::Verdict::v3fail)) {
656 TitanLoggerApi::TitanLogEvent ring_event;
657 // get all the events from the ring: buffer
658 while (!ring_buffer.isEmpty()) {
659 if (ring_buffer.get(ring_event)) {
660 if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_MASKED) {
661 internal_log_to_all(ring_event, true, true, false); // log in separate file
662 } else if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_ALL) {
663 internal_log_to_all(ring_event, true, false, true); // DO NOT log in separate file
664 }
665 }
666 }
667
668 ring_buffer.clear();
669 }
670 }
671
672 // Start of externally callable log functions
673 void LoggerPluginManager::log_unhandled_event(TTCN_Logger::Severity severity,
674 const char *message_ptr,
675 size_t message_len)
676 {
677 if (!TTCN_Logger::log_this_event(severity) && (TTCN_Logger::get_emergency_logging()<=0)) return;
678 API::TitanLogEvent event;
679 fill_common_fields(event, severity);
680
681 event.logEvent().choice().unhandledEvent() = CHARSTRING(message_len, message_ptr);
682 log(event);
683 }
684
685 void LoggerPluginManager::log_log_options(const char *message_ptr,
686 size_t message_len)
687 {
688 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_LOGOPTIONS) && (TTCN_Logger::get_emergency_logging()<=0))
689 return;
690 API::TitanLogEvent event;
691 fill_common_fields(event, TTCN_Logger::EXECUTOR_LOGOPTIONS);
692
693 event.logEvent().choice().executorEvent().choice().logOptions() =
694 CHARSTRING(message_len, message_ptr);
695 log(event);
696 }
697
698 void LoggerPluginManager::log_timer_read(const char *timer_name,
699 double start_val)
700 {
701 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_READ) && (TTCN_Logger::get_emergency_logging()<=0))
702 return;
703 API::TitanLogEvent event;
704 fill_common_fields(event, TTCN_Logger::TIMEROP_READ);
705
706 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().readTimer();
707 timer.name() = timer_name;
708 timer.value__() = start_val;
709 log(event);
710 }
711
712 void LoggerPluginManager::log_timer_start(const char *timer_name,
713 double start_val)
714 {
715 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_START) && (TTCN_Logger::get_emergency_logging()<=0))
716 return;
717 API::TitanLogEvent event;
718 fill_common_fields(event, TTCN_Logger::TIMEROP_START);
719
720 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().startTimer();
721 timer.name() = timer_name;
722 timer.value__() = start_val;
723 log(event);
724 }
725
726 void LoggerPluginManager::log_timer_guard(double start_val)
727 {
728 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_GUARD) && (TTCN_Logger::get_emergency_logging()<=0))
729 return;
730 API::TitanLogEvent event;
731 fill_common_fields(event, TTCN_Logger::TIMEROP_GUARD);
732
733 API::TimerGuardType& timer = event.logEvent().choice().timerEvent().choice().guardTimer();
734 timer.value__() = start_val;
735 log(event);
736 }
737
738 void LoggerPluginManager::log_timer_stop(const char *timer_name,
739 double stop_val)
740 {
741 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_STOP) && (TTCN_Logger::get_emergency_logging()<=0))
742 return;
743 API::TitanLogEvent event;
744 fill_common_fields(event, TTCN_Logger::TIMEROP_STOP);
745
746 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().stopTimer();
747 timer.name() = timer_name;
748 timer.value__() = stop_val;
749 log(event);
750 }
751
752 void LoggerPluginManager::log_timer_timeout(const char *timer_name,
753 double timeout_val)
754 {
755 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_TIMEOUT) && (TTCN_Logger::get_emergency_logging()<=0))
756 return;
757 API::TitanLogEvent event;
758 fill_common_fields(event, TTCN_Logger::TIMEROP_TIMEOUT);
759
760 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().timeoutTimer();
761 timer.name() = timer_name;
762 timer.value__() = timeout_val;
763 log(event);
764 }
765
766 void LoggerPluginManager::log_timer_any_timeout()
767 {
768 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_TIMEOUT) && (TTCN_Logger::get_emergency_logging()<=0))
769 return;
770 API::TitanLogEvent event;
771 fill_common_fields(event, TTCN_Logger::TIMEROP_TIMEOUT);
772
773 // Make `ALT_timeoutAnyTimer' selected in the union. No data fields here.
774 event.logEvent().choice().timerEvent().choice().timeoutAnyTimer() = NULL_VALUE;
775 log(event);
776 }
777
778 void LoggerPluginManager::log_timer_unqualified(const char *message)
779 {
780 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
781 return;
782 API::TitanLogEvent event;
783 fill_common_fields(event, TTCN_Logger::TIMEROP_UNQUALIFIED);
784
785 event.logEvent().choice().timerEvent().choice().unqualifiedTimer() = message;
786 log(event);
787 }
788
789 void LoggerPluginManager::log_testcase_started(const qualified_name& testcase_name)
790 {
791 if (!TTCN_Logger::log_this_event(TTCN_Logger::TESTCASE_START) && (TTCN_Logger::get_emergency_logging()<=0))
792 return;
793 API::TitanLogEvent event;
794 fill_common_fields(event, TTCN_Logger::TESTCASE_START);
795
796 API::QualifiedName& qname = event.logEvent().choice().testcaseOp().choice().testcaseStarted();
797 qname.module__name () = testcase_name.module_name;
798 qname.testcase__name() = testcase_name.definition_name;
799 log(event);
800 }
801
802 void LoggerPluginManager::log_testcase_finished(const qualified_name& testcase_name,
803 verdicttype verdict,
804 const char *reason)
805 {
806 if (!TTCN_Logger::log_this_event(TTCN_Logger::TESTCASE_FINISH) && (TTCN_Logger::get_emergency_logging()<=0))
807 return;
808 API::TitanLogEvent event;
809 fill_common_fields(event, TTCN_Logger::TESTCASE_FINISH);
810
811 API::TestcaseType& testcase = event.logEvent().choice().testcaseOp().choice().testcaseFinished();
812 API::QualifiedName& qname = testcase.name();
813 qname.module__name () = testcase_name.module_name;
814 qname.testcase__name() = testcase_name.definition_name;
815 testcase.verdict() = verdict;
816 testcase.reason() = reason;
817 // FIXME: our caller had a CHARSTRING but gave us a C string. Now we have to measure it again :(
818 log(event);
819 }
820
821 void LoggerPluginManager::log_controlpart_start_stop(const char *module_name, int finished)
822 {
823 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
824 return;
825 API::TitanLogEvent event;
826 fill_common_fields(event, TTCN_Logger::STATISTICS_UNQUALIFIED);
827
828 API::StatisticsType& stats = event.logEvent().choice().statistics();
829 if (finished) stats.choice().controlpartFinish() = module_name;
830 else stats.choice().controlpartStart() = module_name;
831 log(event);
832 }
833
834 void LoggerPluginManager::log_controlpart_errors(unsigned int error_count)
835 {
836 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
837 return;
838 API::TitanLogEvent event;
839 fill_common_fields(event, TTCN_Logger::STATISTICS_UNQUALIFIED);
840
841 event.logEvent().choice().statistics().choice().controlpartErrors() = error_count;
842 log(event);
843 }
844
845 void LoggerPluginManager::log_setverdict(verdicttype new_verdict, verdicttype old_verdict,
846 verdicttype local_verdict, const char *old_reason, const char *new_reason)
847 {
848 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_SETVERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
849 return;
850 API::TitanLogEvent event;
851 fill_common_fields(event, TTCN_Logger::VERDICTOP_SETVERDICT);
852 API::SetVerdictType& set = event.logEvent().choice().verdictOp().choice().setVerdict();
853 set.newVerdict() = new_verdict;
854 set.oldVerdict() = old_verdict;
855 set.localVerdict() = local_verdict;
856 if (old_reason != NULL) set.oldReason() = old_reason;
857 else set.oldReason() = OMIT_VALUE;
858 if (new_reason != NULL) set.newReason() = new_reason;
859 else set.newReason() = OMIT_VALUE;
860 log(event);
861 }
862
863 void LoggerPluginManager::log_getverdict(verdicttype verdict)
864 {
865 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_GETVERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
866 return;
867 API::TitanLogEvent event;
868 fill_common_fields(event, TTCN_Logger::VERDICTOP_GETVERDICT);
869 event.logEvent().choice().verdictOp().choice().getVerdict() = verdict;
870 log(event);
871 }
872
873 void LoggerPluginManager::log_final_verdict(bool is_ptc,
874 verdicttype ptc_verdict, verdicttype local_verdict, verdicttype new_verdict,
875 const char *verdict__reason, int notification, int ptc_compref,
876 const char *ptc_name)
877 {
878 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_FINAL) && (TTCN_Logger::get_emergency_logging()<=0))
879 return;
880 API::TitanLogEvent event;
881 fill_common_fields(event, TTCN_Logger::VERDICTOP_FINAL);
882 API::FinalVerdictType& final = event.logEvent().choice().verdictOp().choice().finalVerdict();
883 if (notification >= 0) {
884 final.choice().notification() = notification;
885 } else {
886 final.choice().info().is__ptc() = is_ptc;
887 final.choice().info().ptc__verdict() = ptc_verdict;
888 final.choice().info().local__verdict() = local_verdict;
889 final.choice().info().new__verdict() = new_verdict;
890 final.choice().info().ptc__compref() = ptc_compref;
891 if (verdict__reason != NULL)
892 final.choice().info().verdict__reason() = verdict__reason;
893 else final.choice().info().verdict__reason() = OMIT_VALUE;
894 if (ptc_name != NULL)
895 final.choice().info().ptc__name() = ptc_name;
896 else final.choice().info().ptc__name() = OMIT_VALUE;
897 }
898 log(event);
899 }
900
901 void LoggerPluginManager::log_verdict_statistics(size_t none_count, double none_percent,
902 size_t pass_count, double pass_percent,
903 size_t inconc_count, double inconc_percent,
904 size_t fail_count, double fail_percent,
905 size_t error_count, double error_percent)
906 {
907 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_VERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
908 return;
909 API::TitanLogEvent event;
910 fill_common_fields(event, TTCN_Logger::STATISTICS_VERDICT);
911
912 API::StatisticsType& statistics = event.logEvent().choice().statistics();
913 statistics.choice().verdictStatistics().none__() = none_count;
914 statistics.choice().verdictStatistics().nonePercent() = none_percent;
915 statistics.choice().verdictStatistics().pass__() = pass_count;
916 statistics.choice().verdictStatistics().passPercent() = pass_percent;
917 statistics.choice().verdictStatistics().inconc__() = inconc_count;
918 statistics.choice().verdictStatistics().inconcPercent() = inconc_percent;
919 statistics.choice().verdictStatistics().fail__() = fail_count;
920 statistics.choice().verdictStatistics().failPercent() = fail_percent;
921 statistics.choice().verdictStatistics().error__() = error_count;
922 statistics.choice().verdictStatistics().errorPercent() = error_percent;
923 log(event);
924 }
925
926 void LoggerPluginManager::log_defaultop_activate(const char *name, int id)
927 {
928 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_ACTIVATE) && (TTCN_Logger::get_emergency_logging()<=0))
929 return;
930 API::TitanLogEvent event;
931 fill_common_fields(event, TTCN_Logger::DEFAULTOP_ACTIVATE);
932
933 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopActivate();
934 defaultop.name() = name;
935 defaultop.id() = id;
936 defaultop.end() = API::DefaultEnd::UNKNOWN_VALUE; // don't care
937 log(event);
938 }
939
940 void LoggerPluginManager::log_defaultop_deactivate(const char *name, int id)
941 {
942 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_DEACTIVATE) && (TTCN_Logger::get_emergency_logging()<=0))
943 return;
944 API::TitanLogEvent event;
945 fill_common_fields(event, TTCN_Logger::DEFAULTOP_DEACTIVATE);
946
947 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopDeactivate();
948 defaultop.name() = name;
949 defaultop.id() = id;
950 defaultop.end() = API::DefaultEnd::UNKNOWN_VALUE; // don't care
951 log(event); // whoa, deja vu!
952 }
953
954 void LoggerPluginManager::log_defaultop_exit(const char *name, int id, int x)
955 {
956 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_EXIT) && (TTCN_Logger::get_emergency_logging()<=0))
957 return;
958 API::TitanLogEvent event;
959 fill_common_fields(event, TTCN_Logger::DEFAULTOP_EXIT);
960
961 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopExit();
962 defaultop.name() = name;
963 defaultop.id() = id;
964 defaultop.end() = x;
965 log(event);
966 }
967
968 void LoggerPluginManager::log_executor_runtime(API::ExecutorRuntime_reason reason)
969 {
970 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
971 return;
972 API::TitanLogEvent event;
973 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
974
975 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
976 exec.reason() = reason;
977 exec.module__name() = OMIT_VALUE;
978 exec.testcase__name() = OMIT_VALUE;
979 exec.pid() = OMIT_VALUE;
980 exec.fd__setsize() = OMIT_VALUE;
981 log(event);
982 }
983
984 void LoggerPluginManager::log_HC_start(const char *host)
985 {
986 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
987 return;
988 API::TitanLogEvent event;
989 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
990
991 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
992 exec.reason() = API::ExecutorRuntime_reason::host__controller__started;
993 exec.module__name() = host; // "reuse" charstring member
994 exec.testcase__name() = OMIT_VALUE;
995 exec.pid() = OMIT_VALUE;
996 exec.fd__setsize() = OMIT_VALUE;
997 log(event);
998 }
999
1000 void LoggerPluginManager::log_fd_limits(int fd_limit, long fd_set_size)
1001 {
1002 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1003 return;
1004 API::TitanLogEvent event;
1005 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1006
1007 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1008 exec.reason() = API::ExecutorRuntime_reason::fd__limits;
1009 exec.module__name() = OMIT_VALUE;
1010 exec.testcase__name() = OMIT_VALUE;
1011 exec.pid() = fd_limit;
1012 exec.fd__setsize() = fd_set_size;
1013 log(event);
1014 }
1015
1016 void LoggerPluginManager::log_not_overloaded(int pid)
1017 {
1018 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1019 return;
1020 API::TitanLogEvent event;
1021 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1022
1023 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1024 exec.reason() = API::ExecutorRuntime_reason::overloaded__no__more;
1025 exec.module__name() = OMIT_VALUE;
1026 exec.testcase__name() = OMIT_VALUE;
1027 exec.pid() = pid;
1028 exec.fd__setsize() = OMIT_VALUE;
1029 log(event);
1030 }
1031
1032 void LoggerPluginManager::log_testcase_exec(const char *tc, const char *module)
1033 {
1034 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1035 return;
1036 API::TitanLogEvent event;
1037 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1038
1039 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1040 exec.reason() = API::ExecutorRuntime_reason::executing__testcase__in__module;
1041 exec.module__name() = module;
1042 exec.testcase__name() = tc;
1043 exec.pid() = OMIT_VALUE;
1044 exec.fd__setsize() = OMIT_VALUE;
1045 log(event);
1046 }
1047
1048 void LoggerPluginManager::log_module_init(const char *module, bool finish)
1049 {
1050 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1051 return;
1052 API::TitanLogEvent event;
1053 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1054
1055 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1056 exec.reason() = finish
1057 ? API::ExecutorRuntime_reason::initialization__of__module__finished
1058 : API::ExecutorRuntime_reason::initializing__module;
1059 exec.module__name() = module;
1060 exec.testcase__name() = OMIT_VALUE;
1061 exec.pid() = OMIT_VALUE;
1062 exec.fd__setsize() = OMIT_VALUE;
1063 log(event);
1064 }
1065
1066 void LoggerPluginManager::log_mtc_created(long pid)
1067 {
1068 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1069 return;
1070 API::TitanLogEvent event;
1071 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1072
1073 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1074 exec.reason() = API::ExecutorRuntime_reason::mtc__created;
1075 exec.module__name() = OMIT_VALUE;
1076 exec.testcase__name() = OMIT_VALUE;
1077 exec.pid() = pid;
1078 exec.fd__setsize() = OMIT_VALUE;
1079 log(event);
1080 }
1081
1082 void LoggerPluginManager::log_configdata(int reason, const char *str)
1083 {
1084 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_CONFIGDATA) && (TTCN_Logger::get_emergency_logging()<=0))
1085 return;
1086 API::TitanLogEvent event;
1087 fill_common_fields(event, TTCN_Logger::EXECUTOR_CONFIGDATA);
1088
1089 API::ExecutorConfigdata& cfg = event.logEvent().choice().executorEvent().choice().executorConfigdata();
1090 cfg.reason() = reason;
1091 if (str != NULL) cfg.param__() = str;
1092 else cfg.param__() = OMIT_VALUE;
1093 log(event);
1094 }
1095
1096 void LoggerPluginManager::log_executor_component(int reason)
1097 {
1098 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_COMPONENT) && (TTCN_Logger::get_emergency_logging()<=0))
1099 return;
1100 API::TitanLogEvent event;
1101 fill_common_fields(event, TTCN_Logger::EXECUTOR_COMPONENT);
1102
1103 API::ExecutorComponent& ec = event.logEvent().choice().executorEvent().choice().executorComponent();
1104 ec.reason() = reason;
1105 ec.compref() = OMIT_VALUE;
1106 log(event);
1107 }
1108
1109 void LoggerPluginManager::log_executor_misc(int reason, const char *name,
1110 const char *address, int port)
1111 {
1112 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
1113 return;
1114 API::TitanLogEvent event;
1115 fill_common_fields(event, TTCN_Logger::EXECUTOR_UNQUALIFIED);
1116
1117 API::ExecutorUnqualified& ex = event.logEvent().choice().executorEvent().choice().executorMisc();
1118 ex.reason() = reason;
1119 ex.name() = name;
1120 ex.addr() = address;
1121 ex.port__() = port;
1122
1123 log(event);
1124 }
1125
1126 void LoggerPluginManager::log_extcommand(TTCN_Logger::extcommand_t action,
1127 const char *cmd)
1128 {
1129 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_EXTCOMMAND) && (TTCN_Logger::get_emergency_logging()<=0))
1130 return;
1131 API::TitanLogEvent event;
1132 fill_common_fields(event, TTCN_Logger::EXECUTOR_EXTCOMMAND);
1133
1134 CHARSTRING& str = (action == TTCN_Logger::EXTCOMMAND_START)
1135 ? event.logEvent().choice().executorEvent().choice().extcommandStart()
1136 : event.logEvent().choice().executorEvent().choice().extcommandSuccess();
1137
1138 str = cmd;
1139 log(event);
1140 }
1141
1142 void LoggerPluginManager::log_matching_done(API::MatchingDoneType_reason reason,
1143 const char *type, int ptc, const char *return_type)
1144 {
1145 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_DONE) && (TTCN_Logger::get_emergency_logging()<=0))
1146 return;
1147 API::TitanLogEvent event;
1148 fill_common_fields(event, TTCN_Logger::MATCHING_DONE);
1149
1150 API::MatchingDoneType& mp = event.logEvent().choice().matchingEvent().choice().matchingDone();
1151 mp.reason() = reason;
1152 mp.type__() = type;
1153 mp.ptc() = ptc;
1154 mp.return__type() = return_type;
1155 log(event);
1156 }
1157
1158 void LoggerPluginManager::log_matching_problem(int reason, int operation,
1159 boolean check, boolean anyport, const char *port_name)
1160 {
1161 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_PROBLEM) && (TTCN_Logger::get_emergency_logging()<=0))
1162 return;
1163 API::TitanLogEvent event;
1164 fill_common_fields(event, TTCN_Logger::MATCHING_PROBLEM);
1165
1166 API::MatchingProblemType& mp = event.logEvent().choice().matchingEvent().choice().matchingProblem();
1167 mp.reason() = reason;
1168 mp.any__port() = anyport;
1169 mp.check__() = check;
1170 mp.operation() = operation;
1171 mp.port__name()= port_name;
1172 log(event);
1173 }
1174
1175 void LoggerPluginManager::log_matching_success(int port_type, const char *port_name,
1176 int compref, const CHARSTRING& info)
1177 {
1178 TTCN_Logger::Severity sev;
1179 if (compref == SYSTEM_COMPREF) {
1180 sev = (port_type == API::PortType::message__)
1181 ? TTCN_Logger::MATCHING_MMSUCCESS : TTCN_Logger::MATCHING_PMSUCCESS;
1182 }
1183 else {
1184 sev = (port_type == API::PortType::message__)
1185 ? TTCN_Logger::MATCHING_MCSUCCESS : TTCN_Logger::MATCHING_PCSUCCESS;
1186 }
1187 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1188 return;
1189 API::TitanLogEvent event;
1190 fill_common_fields(event, sev);
1191
1192 API::MatchingSuccessType& ms = event.logEvent().choice().matchingEvent().choice().matchingSuccess();
1193 ms.port__type() = port_type;
1194 ms.port__name() = port_name;
1195 ms.info() = info;
1196 log(event);
1197 }
1198
1199 void LoggerPluginManager::log_matching_failure(int port_type, const char *port_name,
1200 int compref, int reason, const CHARSTRING& info)
1201 {
1202 TTCN_Logger::Severity sev;
1203 if (compref == SYSTEM_COMPREF) {
1204 sev = (port_type == API::PortType::message__)
1205 ? TTCN_Logger::MATCHING_MMUNSUCC : TTCN_Logger::MATCHING_PMUNSUCC;
1206 }
1207 else {
1208 sev = (port_type == API::PortType::message__)
1209 ? TTCN_Logger::MATCHING_MCUNSUCC : TTCN_Logger::MATCHING_PCUNSUCC;
1210 }
1211 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1212 return;
1213 API::TitanLogEvent event;
1214 fill_common_fields(event, sev);
1215
1216 API::MatchingFailureType& mf = event.logEvent().choice().matchingEvent().choice().matchingFailure();
1217 mf.port__type() = port_type;
1218 mf.port__name() = port_name;
1219 mf.reason() = reason;
1220
1221 if (compref == SYSTEM_COMPREF) {
1222 mf.choice().system__();
1223 }
1224 else mf.choice().compref() = compref;
1225
1226 mf.info() = info;
1227
1228 log(event);
1229 }
1230
1231 void LoggerPluginManager::log_matching_timeout(const char *timer_name)
1232 {
1233 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_PROBLEM) && (TTCN_Logger::get_emergency_logging()<=0))
1234 return;
1235 API::TitanLogEvent event;
1236 fill_common_fields(event, TTCN_Logger::MATCHING_PROBLEM);
1237
1238 API::MatchingTimeout& mt = event.logEvent().choice().matchingEvent().choice().matchingTimeout();
1239 if (timer_name) mt.timer__name() = timer_name;
1240 else mt.timer__name() = OMIT_VALUE;
1241 log(event);
1242 }
1243
1244 void LoggerPluginManager::log_random(int action, double v, unsigned long u)
1245 {
1246 if (!TTCN_Logger::log_this_event(TTCN_Logger::FUNCTION_RND) && (TTCN_Logger::get_emergency_logging()<=0))
1247 return;
1248 API::TitanLogEvent event;
1249 fill_common_fields(event, TTCN_Logger::FUNCTION_RND);
1250
1251 API::FunctionEvent_choice_random &r = event.logEvent().choice().functionEvent().choice().random();
1252 r.operation()= action;
1253 r.retval() = v;
1254 r.intseed() = u;
1255 log(event);
1256 }
1257
1258 /** Pretend that the control part is executed by a separate component.
1259 *
1260 * In TITAN, the control part is executed on the MTC.
1261 * This does not match the standard, which states:
1262 * "The MTC shall be created by the system automatically at the start
1263 * of each test case execution"; so the MTC is not supposed to exist
1264 * in a control part. For the purpose of logging, we pretend that in the
1265 * control part the current component is not the MTC but another "artificial"
1266 * component "control", similar to "null", "system", or "all".
1267 *
1268 * @param compref
1269 * @return the input value, but substitute CONTROLPART_COMPREF for MTC_COMPREF
1270 * if inside a controlpart.
1271 */
1272 inline int adjust_compref(int compref)
1273 {
1274 if (compref == MTC_COMPREF) {
1275 switch (TTCN_Runtime::get_state()) {
1276 case TTCN_Runtime::MTC_CONTROLPART:
1277 case TTCN_Runtime::SINGLE_CONTROLPART:
1278 compref = CONTROL_COMPREF;
1279 break;
1280 default:
1281 break;
1282 }
1283 }
1284
1285 return compref;
1286 }
1287
1288 void LoggerPluginManager::log_portconnmap(int operation, int src_compref,
1289 const char *src_port, int dst_compref, const char *dst_port)
1290 {
1291 TTCN_Logger::Severity event_severity;
1292 switch (operation) {
1293 case API::ParPort_operation::connect__:
1294 case API::ParPort_operation::disconnect__:
1295 event_severity = TTCN_Logger::PARALLEL_PORTCONN;
1296 break;
1297 case API::ParPort_operation::map__:
1298 case API::ParPort_operation::unmap__:
1299 event_severity = TTCN_Logger::PARALLEL_PORTMAP;
1300 break;
1301 default:
1302 TTCN_error("Invalid operation");
1303 }
1304
1305 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1306 return;
1307 API::TitanLogEvent event;
1308 fill_common_fields(event, event_severity);
1309
1310 API::ParPort & pp = event.logEvent().choice().parallelEvent().choice().parallelPort();
1311 pp.operation() = operation;
1312 pp.srcCompref() = adjust_compref(src_compref);
1313 pp.srcPort() = src_port;
1314 pp.dstCompref() = adjust_compref(dst_compref);
1315 pp.dstPort() = dst_port;
1316 log(event);
1317 }
1318
1319 void LoggerPluginManager::log_par_ptc(int reason,
1320 const char *module, const char *name, int compref,
1321 const char *compname, const char *tc_loc, int alive_pid, int status)
1322 {
1323 TTCN_Logger::Severity sev =
1324 (alive_pid && reason == API::ParallelPTC_reason::function__finished)
1325 ? TTCN_Logger::PARALLEL_UNQUALIFIED : TTCN_Logger::PARALLEL_PTC;
1326 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1327 return;
1328 API::TitanLogEvent event;
1329 fill_common_fields(event, sev);
1330
1331 API::ParallelPTC& ptc = event.logEvent().choice().parallelEvent().choice().parallelPTC();
1332 ptc.reason() = reason;
1333 ptc.module__() = module;
1334 ptc.name() = name;
1335 ptc.compref() = compref;
1336 ptc.tc__loc() = tc_loc;
1337 ptc.compname() = compname;
1338 ptc.alive__pid() = alive_pid;
1339 ptc.status() = status;
1340 log(event);
1341 }
1342
1343 void LoggerPluginManager::log_port_queue(int operation, const char *port_name,
1344 int compref, int id, const CHARSTRING& address, const CHARSTRING& param)
1345 {
1346 TTCN_Logger::Severity sev;
1347 switch (operation) {
1348 case API::Port__Queue_operation::enqueue__msg:
1349 case API::Port__Queue_operation::extract__msg:
1350 sev = TTCN_Logger::PORTEVENT_MQUEUE;
1351 break;
1352 case API::Port__Queue_operation::enqueue__call:
1353 case API::Port__Queue_operation::enqueue__exception:
1354 case API::Port__Queue_operation::enqueue__reply:
1355 case API::Port__Queue_operation::extract__op:
1356 sev = TTCN_Logger::PORTEVENT_PQUEUE;
1357 break;
1358 default:
1359 TTCN_error("Invalid operation");
1360 }
1361
1362 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0)) return;
1363 API::TitanLogEvent event;
1364 fill_common_fields(event, sev);
1365
1366 API::Port__Queue& pq = event.logEvent().choice().portEvent().choice().portQueue();
1367 pq.operation() = operation;
1368 pq.port__name() = port_name;
1369 pq.compref() = adjust_compref(compref);
1370 pq.msgid() = id;
1371 pq.address__() = address;
1372 pq.param__() = param;
1373 log(event);
1374 }
1375
1376 void LoggerPluginManager::log_port_state(int operation, const char *port_name)
1377 {
1378 if (!TTCN_Logger::log_this_event(TTCN_Logger::PORTEVENT_STATE)) return;
1379 API::TitanLogEvent event;
1380 fill_common_fields(event, TTCN_Logger::PORTEVENT_STATE);
1381
1382 API::Port__State& ps = event.logEvent().choice().portEvent().choice().portState();
1383 ps.operation() = operation;
1384 ps.port__name() = port_name;
1385 log(event);
1386 }
1387
1388 void LoggerPluginManager::log_procport_send(const char *portname, int operation,
1389 int compref, const CHARSTRING& system, const CHARSTRING& param)
1390 {
1391 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1392 ? TTCN_Logger::PORTEVENT_PMOUT : TTCN_Logger::PORTEVENT_PCOUT;
1393 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1394 return;
1395 API::TitanLogEvent event;
1396 fill_common_fields(event, event_severity);
1397
1398 API::Proc__port__out& pt = event.logEvent().choice().portEvent().choice().procPortSend();
1399 pt.port__name() = portname;
1400 pt.operation() = operation;
1401 pt.compref() = compref;
1402 if (compref == SYSTEM_COMPREF) { // it's mapped
1403 pt.sys__name() = system;
1404 }
1405 pt.parameter() = param;
1406
1407 log(event);
1408 }
1409
1410 void LoggerPluginManager::log_procport_recv(const char *portname, int operation,
1411 int compref, boolean check, const CHARSTRING& param, int id)
1412 {
1413 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1414 ? TTCN_Logger::PORTEVENT_PMIN : TTCN_Logger::PORTEVENT_PCIN;
1415 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1416 return;
1417 API::TitanLogEvent event;
1418 fill_common_fields(event, event_severity);
1419
1420 API::Proc__port__in& pt = event.logEvent().choice().portEvent().choice().procPortRecv();
1421 pt.port__name() = portname;
1422 pt.operation() = operation;
1423 pt.compref() = compref;
1424 pt.check__() = check;
1425 pt.parameter() = param;
1426 pt.msgid() = id;
1427
1428 log(event);
1429 }
1430
1431 void LoggerPluginManager::log_msgport_send(const char *portname, int compref,
1432 const CHARSTRING& param)
1433 {
1434 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1435 ? TTCN_Logger::PORTEVENT_MMSEND : TTCN_Logger::PORTEVENT_MCSEND;
1436 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0)) return;
1437 API::TitanLogEvent event;
1438 fill_common_fields(event, event_severity);
1439
1440 API::Msg__port__send& ms = event.logEvent().choice().portEvent().choice().msgPortSend();
1441 ms.port__name() = portname;
1442 ms.compref() = compref;
1443 ms.parameter() = param;
1444
1445 log(event);
1446 }
1447
1448 void LoggerPluginManager::log_msgport_recv(const char *portname, int operation,
1449 int compref, const CHARSTRING& system, const CHARSTRING& param, int id)
1450 {
1451 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1452 ? TTCN_Logger::PORTEVENT_MMRECV : TTCN_Logger::PORTEVENT_MCRECV;
1453 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1454 return;
1455 API::TitanLogEvent event;
1456 fill_common_fields(event, event_severity);
1457
1458 API::Msg__port__recv& ms = event.logEvent().choice().portEvent().choice().msgPortRecv();
1459 ms.port__name() = portname;
1460 ms.compref() = compref;
1461 if (compref == SYSTEM_COMPREF) { // it's mapped
1462 ms.sys__name() = system;
1463 }
1464 ms.operation() = operation;
1465 ms.msgid() = id;
1466 ms.parameter() = param;
1467
1468 log(event);
1469 }
1470
1471 void LoggerPluginManager::log_dualport_map(boolean incoming, const char *target_type,
1472 const CHARSTRING& value, int id)
1473 {
1474 TTCN_Logger::Severity event_severity = incoming
1475 ? TTCN_Logger::PORTEVENT_DUALRECV : TTCN_Logger::PORTEVENT_DUALSEND;
1476 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1477 return;
1478 API::TitanLogEvent event;
1479 fill_common_fields(event, event_severity);
1480
1481 API::Dualface__mapped& dual = event.logEvent().choice().portEvent().choice().dualMapped();
1482 dual.incoming() = incoming;
1483 dual.target__type() = target_type;
1484 dual.value__() = value;
1485 dual.msgid() = id;
1486
1487 log(event);
1488 }
1489
1490 void LoggerPluginManager::log_dualport_discard(boolean incoming, const char *target_type,
1491 const char *port_name, boolean unhandled)
1492 {
1493 TTCN_Logger::Severity event_severity = incoming
1494 ? TTCN_Logger::PORTEVENT_DUALRECV : TTCN_Logger::PORTEVENT_DUALSEND;
1495 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1496 return;
1497 API::TitanLogEvent event;
1498 fill_common_fields(event, event_severity);
1499
1500 API::Dualface__discard& dualop = event.logEvent().choice().portEvent().choice().dualDiscard();
1501 dualop.incoming() = incoming;
1502 dualop.target__type() = target_type;
1503 dualop.port__name() = port_name;
1504 dualop.unhandled() = unhandled;
1505
1506 log(event);
1507 }
1508
1509 void LoggerPluginManager::log_port_misc(int reason, const char *port_name,
1510 int remote_component, const char *remote_port, const char *ip_address,
1511 int tcp_port, int new_size)
1512 {
1513 if (!TTCN_Logger::log_this_event(TTCN_Logger::PORTEVENT_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
1514 return;
1515 API::TitanLogEvent event;
1516 fill_common_fields(event, TTCN_Logger::PORTEVENT_UNQUALIFIED);
1517
1518 API::Port__Misc& portmisc = event.logEvent().choice().portEvent().choice().portMisc();
1519 portmisc.reason() = reason;
1520 portmisc.port__name() = port_name;
1521 portmisc.remote__component() = remote_component;
1522 portmisc.remote__port() = remote_port;
1523 portmisc.ip__address() = ip_address;
1524 portmisc.tcp__port() = tcp_port;
1525 portmisc.new__size() = new_size;
1526
1527 log(event);
1528 }
1529
1530
1531 // End of externally callable functions
1532
1533 /// Construct an event string, one by one. Event construction is not
1534 /// supported for all event types. E.g. those event types with fixed format
1535 /// like TIMEROP_* events have nothing to do with this at all.
1536 void LoggerPluginManager::append_event_str(const char *str)
1537 {
1538 if (!this->current_event_) return;
1539 ActiveEvent& curr = *this->current_event_;
1540 const size_t str_len = strlen(str);
1541 if (!str_len) return; // don't bother with empty string
1542
1543 if (curr.event_str_ != NULL) { // event_str_ already allocated
1544 if (!curr.fake_) {
1545 // pieces_ may be NULL, in which case Realloc calls Malloc
1546 curr.pieces_ = (size_t*)Realloc(curr.pieces_, sizeof(size_t) * curr.num_pieces_);
1547 // Remember the current end
1548 curr.pieces_[curr.num_pieces_++-1] = curr.event_str_len_;
1549 }
1550 // Don't bother remembering the pieces for a log2str event
1551
1552 if ( curr.event_str_len_ + str_len > curr.event_str_size_) {
1553 for (; curr.event_str_len_ + str_len > curr.event_str_size_;
1554 curr.event_str_size_ *= 2) ; // double until it fits
1555 curr.event_str_ = (char *)Realloc(curr.event_str_, curr.event_str_size_);
1556 memset(curr.event_str_ + curr.event_str_len_, '\0',
1557 curr.event_str_size_ - curr.event_str_len_);
1558 }
1559 memcpy(curr.event_str_ + curr.event_str_len_, str, str_len);
1560 curr.event_str_len_ += str_len;
1561 } else { // the first piece
1562 curr.event_str_len_ = str_len;
1563 curr.event_str_size_ = str_len * 2; // must be strictly bigger than str_len
1564 curr.event_str_ = (char *)Malloc(curr.event_str_size_);
1565 memcpy(curr.event_str_, str, str_len);
1566 memset(curr.event_str_ + str_len, '\0',
1567 curr.event_str_size_ - str_len);
1568 curr.num_pieces_++;
1569 // Do not allocate memory for the first piece; it ends at event_str_len_
1570 }
1571 }
1572
1573 char* LoggerPluginManager::get_current_event_str()
1574 {
1575 if (!this->current_event_) return 0;
1576 size_t str_len = current_event_->event_str_len_ + 1;
1577 char* result = (char*)Malloc(str_len);
1578 memcpy(result, current_event_->event_str_, str_len - 1);
1579 result[str_len - 1] = '\0';
1580 return result;
1581 }
1582
1583 void LoggerPluginManager::begin_event(TTCN_Logger::Severity msg_severity,
1584 bool log2str)
1585 {
1586 event_destination_t event_dest;
1587 if (log2str) event_dest = ED_STRING;
1588 else event_dest =
1589 TTCN_Logger::log_this_event(msg_severity) ? ED_FILE : ED_NONE;
1590 // We are in the middle of another event, allocate a new entry for this
1591 // event. The other active events are available through outer events.
1592 // We're not (re)using the `outermost_event' buffer.
1593 ActiveEvent *new_event = new ActiveEvent(log2str, event_dest);
1594 if (!log2str) fill_common_fields(new_event->get_event(), msg_severity);
1595 new_event->outer_event_ = this->current_event_;
1596 this->current_event_ = new_event;
1597 }
1598
1599 void LoggerPluginManager::end_event()
1600 {
1601 if (this->current_event_ == NULL) {
1602 // Invalid usage.
1603 const char *message = "TTCN_Logger::end_event(): not in event.";
1604 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1605 return;
1606 }
1607
1608 ActiveEvent& curr = *this->current_event_;
1609 switch (curr.event_destination_) {
1610 case ED_NONE:
1611 break;
1612 case ED_FILE:
1613 switch ((TTCN_Logger::Severity)(int)curr.get_event().severity()) {
1614 case TTCN_Logger::DEBUG_ENCDEC:
1615 case TTCN_Logger::DEBUG_TESTPORT:
1616 case TTCN_Logger::DEBUG_UNQUALIFIED:
1617 curr.get_event().logEvent().choice().debugLog().text() =
1618 CHARSTRING(curr.event_str_len_, curr.event_str_);
1619 curr.get_event().logEvent().choice().debugLog().category() = 0; // not yet used
1620 break;
1621
1622 case TTCN_Logger::ERROR_UNQUALIFIED:
1623 curr.get_event().logEvent().choice().errorLog().text() =
1624 CHARSTRING(curr.event_str_len_, curr.event_str_);
1625 curr.get_event().logEvent().choice().errorLog().category() = 0; // not yet used
1626 break;
1627
1628 case TTCN_Logger::ACTION_UNQUALIFIED:
1629 // fall through
1630 case TTCN_Logger::USER_UNQUALIFIED: {
1631 // Select the list for either userLog or action; treatment is the same.
1632 API::Strings_str__list& slist = (curr.get_event().severity() == TTCN_Logger::USER_UNQUALIFIED)
1633 ? curr.get_event().logEvent().choice().userLog().str__list()
1634 : curr.get_event().logEvent().choice().actionEvent().str__list();
1635 if (curr.num_pieces_ > 0) {
1636 // First piece. If num_pieces_==1, pieces_ is not allocated, use the full length.
1637 size_t len0 = curr.num_pieces_ > 1 ? curr.pieces_[0] : curr.event_str_len_;
1638 slist[0] = CHARSTRING(len0, curr.event_str_);
1639 // Subsequent pieces from pieces_[i-1] to pieces_[i] (exclusive)
1640 for (size_t i = 1; i < curr.num_pieces_ - 1; ++i) {
1641 slist[i] = CHARSTRING(
1642 curr.pieces_[i] - curr.pieces_[i - 1],
1643 curr.event_str_ + curr.pieces_[i - 1]);
1644 }
1645 // Last piece (if it's not the same as the first)
1646 if (curr.num_pieces_ > 1) { // i == num_pieces_-1
1647 slist[curr.num_pieces_ - 1]= CHARSTRING(
1648 curr.event_str_len_ - curr.pieces_[curr.num_pieces_-2],
1649 curr.event_str_ + curr.pieces_[curr.num_pieces_-2]);
1650 }
1651 }
1652 else slist = NULL_VALUE; // make sure it's bound but empty
1653 break; }
1654
1655 case TTCN_Logger::WARNING_UNQUALIFIED:
1656 curr.get_event().logEvent().choice().warningLog().text() =
1657 CHARSTRING(curr.event_str_len_, curr.event_str_);
1658 curr.get_event().logEvent().choice().warningLog().category() = 0; // not yet used
1659 break;
1660
1661 default:
1662 curr.get_event().logEvent().choice().unhandledEvent() =
1663 CHARSTRING(curr.event_str_len_, curr.event_str_);
1664 break;
1665 } // switch(severity)
1666 log(curr.get_event());
1667 break;
1668 case ED_STRING:
1669 TTCN_Logger::fatal_error("TTCN_Logger::end_event(): event with string "
1670 "destination was found, missing call of "
1671 "TTCN_Logger::end_event_log2str().");
1672 default:
1673 TTCN_Logger::fatal_error("TTCN_Logger::end_event(): invalid event "
1674 "destination.");
1675 } // switch(event_destination)
1676
1677 // Remove the current (already logged) event from the list of pending
1678 // events and select a higher level event on the stack. We're not
1679 // following the old implementation regarding the `outermost_event' stuff.
1680 ActiveEvent *outer_event = curr.outer_event_;
1681 Free(curr.event_str_);
1682 Free(curr.pieces_);
1683 delete this->current_event_;
1684 this->current_event_ = outer_event;
1685 }
1686
1687 CHARSTRING LoggerPluginManager::end_event_log2str()
1688 {
1689 if (this->current_event_ == NULL) {
1690 // Invalid usage.
1691 const char *message = "TTCN_Logger::end_event_log2str(): not in event.";
1692 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1693 return CHARSTRING(); // unbound!
1694 }
1695
1696 ActiveEvent& curr = *this->current_event_;
1697 CHARSTRING ret_val(curr.event_str_len_, curr.event_str_);
1698
1699 ActiveEvent *outer_event = curr.outer_event_;
1700 Free(curr.event_str_);
1701 Free(curr.pieces_);
1702 delete this->current_event_;
1703 // Otherwise, we don't save the current event to be `outermost_event',
1704 // like the previous implementation. An initialized `outermost_event' is
1705 // not the sign of an initialized logger. NULL or not, assign.
1706 this->current_event_ = outer_event;
1707 return ret_val;
1708 }
1709
1710 void LoggerPluginManager::finish_event()
1711 {
1712 // Drop events which have string destination in case of log2str()
1713 // operations. There is no try-catch block to delete the event. Avoid
1714 // data/log file corruption if there's an exception inside a log2str(),
1715 // which is inside a log().
1716 while (this->current_event_ != NULL &&
1717 this->current_event_->event_destination_ == ED_STRING)
1718 (void)end_event_log2str();
1719
1720 if (this->current_event_ != NULL) {
1721 log_event_str("<unfinished>");
1722 end_event();
1723 }
1724 }
1725
1726 // Simply append the contents STR_PTR to the end of the current event.
1727 // Everything is a string here.
1728 void LoggerPluginManager::log_event_str(const char *str_ptr)
1729 {
1730 if (this->current_event_ != NULL) {
1731 if (this->current_event_->event_destination_ == ED_NONE) return;
1732 if (str_ptr == NULL) str_ptr = "<NULL pointer>";
1733 append_event_str(str_ptr);
1734 } else {
1735 // Invalid usage.
1736 const char *message = "TTCN_Logger::log_event_str(): not in event.";
1737 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1738 }
1739 }
1740
1741 void LoggerPluginManager::log_char(char c)
1742 {
1743 if (this->current_event_ != NULL) {
1744 if (this->current_event_->event_destination_ == ED_NONE || c == '\0') return;
1745 const char c_str[2] = { c, 0 };
1746 append_event_str(c_str);
1747 } else {
1748 // Invalid usage.
1749 const char *message = "TTCN_Logger::log_char(): not in event.";
1750 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1751 }
1752 }
1753
1754 void LoggerPluginManager::log_event_va_list(const char *fmt_str,
1755 va_list p_var)
1756 {
1757 if (this->current_event_ != NULL) {
1758 if (this->current_event_->event_destination_ == ED_NONE) return;
1759 if (fmt_str == NULL) fmt_str = "<NULL format string>";
1760 char *message = mprintf_va_list(fmt_str, p_var);
1761 append_event_str(message);
1762 Free(message);
1763 } else {
1764 // Invalid usage.
1765 const char *message = "TTCN_Logger::log_event(): not in event.";
1766 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1767 }
1768 }
1769
1770 void LoggerPluginManager::log_va_list(TTCN_Logger::Severity msg_severity,
1771 const char *fmt_str, va_list p_var)
1772 {
1773 if (!TTCN_Logger::log_this_event(msg_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1774 return;
1775 if (fmt_str == NULL) fmt_str = "<NULL format string>";
1776 // Allocate a temporary buffer for this event.
1777 char *message_buf = mprintf_va_list(fmt_str, p_var);
1778 log_unhandled_event(msg_severity, message_buf, mstrlen(message_buf));
1779 Free(message_buf);
1780 }
1781
1782
1783 LoggerPlugin *LoggerPluginManager::find_plugin(const char *name)
1784 {
1785 assert(name != NULL);
1786 for (size_t i = 0; i < this->n_plugins_; i++) {
1787 const char *plugin_name = this->plugins_[i]->ref_->plugin_name();
1788 // TODO: If the name is not set in the plug-in, a warning should be
1789 // reported instead.
1790 if (plugin_name != NULL && !strcmp(name, plugin_name)) {
1791 return this->plugins_[i];
1792 }
1793 }
1794 return NULL;
1795 }
1796
1797 #ifdef MEMORY_DEBUG
1798 // new has been redefined in dbgnew.hh, undo it
1799 #undef new
1800 #endif
1801
1802 inline void * operator new (size_t, void * p) throw() { return p ; }
1803
1804 LoggerPluginManager::ActiveEvent::ActiveEvent(bool fake_event, event_destination_t dest)
1805 : event_()
1806 , event_str_(NULL)
1807 , event_str_len_(0)
1808 , event_str_size_(0)
1809 , event_destination_(dest)
1810 , outer_event_(NULL)
1811 , num_pieces_(0)
1812 , pieces_(NULL)
1813 , fake_(fake_event)
1814 {
1815 if (!fake_event) {
1816 new (event_) TitanLoggerApi::TitanLogEvent(); // placement new
1817 }
1818 }
1819
1820 LoggerPluginManager::ActiveEvent::~ActiveEvent()
1821 {
1822 if (!fake_) {
1823 get_event().~TitanLogEvent(); // explicit destructor call
1824 }
1825 }
This page took 0.070325 seconds and 5 git commands to generate.