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