Sync with 5.3.0
[deliverable/titan.core.git] / core / LoggerPluginManager.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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 if (TTCN_Logger::should_log_to_file((TTCN_Logger::Severity)(int)event.severity()) ||
620 TTCN_Logger::should_log_to_console((TTCN_Logger::Severity)(int)event.severity())) {
621 internal_log_to_all(event, true, false, false);
622 } else {
623 // check emergency logging mask
624 if (TTCN_Logger::should_log_to_emergency((TTCN_Logger::Severity)(int)event.severity()))
625 ring_buffer.put(event);
626 }
627 } else if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_ALL) {
628 if (ring_buffer.isFull()) {
629 TitanLoggerApi::TitanLogEvent ring_event;
630 // the ring buffer is full, get the the oldest event
631 // check does the user want this to be logged
632 if (ring_buffer.get(ring_event)) {
633 internal_log_to_all(ring_event, true, false, false);
634 } else {
635 // it is not wanted by the user, throw it away
636 }
637 }
638 ring_buffer.put(event);
639 }
640 // ERROR, flush the ring buffer content
641 if ((TTCN_Logger::Severity)(int)event.severity() == TTCN_Logger::ERROR_UNQUALIFIED) {
642 TitanLoggerApi::TitanLogEvent ring_event;
643 // get all the events from the ring: buffer
644 while (!ring_buffer.isEmpty()) {
645 if (ring_buffer.get(ring_event)) {
646 if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_MASKED) {
647 internal_log_to_all(ring_event, true, true, false); // log in separate file
648 } else if (TTCN_Logger::get_emergency_logging_behaviour() == TTCN_Logger::BUFFER_ALL) {
649 internal_log_to_all(ring_event, true, false, true); // DO NOT log in separate file
650 }
651 }
652 }
653
654 ring_buffer.clear();
655 }
656 }
657
658 // Start of externally callable log functions
659 void LoggerPluginManager::log_unhandled_event(TTCN_Logger::Severity severity,
660 const char *message_ptr,
661 size_t message_len)
662 {
663 if (!TTCN_Logger::log_this_event(severity) && (TTCN_Logger::get_emergency_logging()<=0)) return;
664 API::TitanLogEvent event;
665 fill_common_fields(event, severity);
666
667 event.logEvent().choice().unhandledEvent() = CHARSTRING(message_len, message_ptr);
668 log(event);
669 }
670
671 void LoggerPluginManager::log_log_options(const char *message_ptr,
672 size_t message_len)
673 {
674 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_LOGOPTIONS) && (TTCN_Logger::get_emergency_logging()<=0))
675 return;
676 API::TitanLogEvent event;
677 fill_common_fields(event, TTCN_Logger::EXECUTOR_LOGOPTIONS);
678
679 event.logEvent().choice().executorEvent().choice().logOptions() =
680 CHARSTRING(message_len, message_ptr);
681 log(event);
682 }
683
684 void LoggerPluginManager::log_timer_read(const char *timer_name,
685 double start_val)
686 {
687 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_READ) && (TTCN_Logger::get_emergency_logging()<=0))
688 return;
689 API::TitanLogEvent event;
690 fill_common_fields(event, TTCN_Logger::TIMEROP_READ);
691
692 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().readTimer();
693 timer.name() = timer_name;
694 timer.value__() = start_val;
695 log(event);
696 }
697
698 void LoggerPluginManager::log_timer_start(const char *timer_name,
699 double start_val)
700 {
701 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_START) && (TTCN_Logger::get_emergency_logging()<=0))
702 return;
703 API::TitanLogEvent event;
704 fill_common_fields(event, TTCN_Logger::TIMEROP_START);
705
706 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().startTimer();
707 timer.name() = timer_name;
708 timer.value__() = start_val;
709 log(event);
710 }
711
712 void LoggerPluginManager::log_timer_guard(double start_val)
713 {
714 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_GUARD) && (TTCN_Logger::get_emergency_logging()<=0))
715 return;
716 API::TitanLogEvent event;
717 fill_common_fields(event, TTCN_Logger::TIMEROP_GUARD);
718
719 API::TimerGuardType& timer = event.logEvent().choice().timerEvent().choice().guardTimer();
720 timer.value__() = start_val;
721 log(event);
722 }
723
724 void LoggerPluginManager::log_timer_stop(const char *timer_name,
725 double stop_val)
726 {
727 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_STOP) && (TTCN_Logger::get_emergency_logging()<=0))
728 return;
729 API::TitanLogEvent event;
730 fill_common_fields(event, TTCN_Logger::TIMEROP_STOP);
731
732 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().stopTimer();
733 timer.name() = timer_name;
734 timer.value__() = stop_val;
735 log(event);
736 }
737
738 void LoggerPluginManager::log_timer_timeout(const char *timer_name,
739 double timeout_val)
740 {
741 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_TIMEOUT) && (TTCN_Logger::get_emergency_logging()<=0))
742 return;
743 API::TitanLogEvent event;
744 fill_common_fields(event, TTCN_Logger::TIMEROP_TIMEOUT);
745
746 API::TimerType& timer = event.logEvent().choice().timerEvent().choice().timeoutTimer();
747 timer.name() = timer_name;
748 timer.value__() = timeout_val;
749 log(event);
750 }
751
752 void LoggerPluginManager::log_timer_any_timeout()
753 {
754 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_TIMEOUT) && (TTCN_Logger::get_emergency_logging()<=0))
755 return;
756 API::TitanLogEvent event;
757 fill_common_fields(event, TTCN_Logger::TIMEROP_TIMEOUT);
758
759 // Make `ALT_timeoutAnyTimer' selected in the union. No data fields here.
760 event.logEvent().choice().timerEvent().choice().timeoutAnyTimer() = NULL_VALUE;
761 log(event);
762 }
763
764 void LoggerPluginManager::log_timer_unqualified(const char *message)
765 {
766 if (!TTCN_Logger::log_this_event(TTCN_Logger::TIMEROP_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
767 return;
768 API::TitanLogEvent event;
769 fill_common_fields(event, TTCN_Logger::TIMEROP_UNQUALIFIED);
770
771 event.logEvent().choice().timerEvent().choice().unqualifiedTimer() = message;
772 log(event);
773 }
774
775 void LoggerPluginManager::log_testcase_started(const qualified_name& testcase_name)
776 {
777 if (!TTCN_Logger::log_this_event(TTCN_Logger::TESTCASE_START) && (TTCN_Logger::get_emergency_logging()<=0))
778 return;
779 API::TitanLogEvent event;
780 fill_common_fields(event, TTCN_Logger::TESTCASE_START);
781
782 API::QualifiedName& qname = event.logEvent().choice().testcaseOp().choice().testcaseStarted();
783 qname.module__name () = testcase_name.module_name;
784 qname.testcase__name() = testcase_name.definition_name;
785 log(event);
786 }
787
788 void LoggerPluginManager::log_testcase_finished(const qualified_name& testcase_name,
789 verdicttype verdict,
790 const char *reason)
791 {
792 if (!TTCN_Logger::log_this_event(TTCN_Logger::TESTCASE_FINISH) && (TTCN_Logger::get_emergency_logging()<=0))
793 return;
794 API::TitanLogEvent event;
795 fill_common_fields(event, TTCN_Logger::TESTCASE_FINISH);
796
797 API::TestcaseType& testcase = event.logEvent().choice().testcaseOp().choice().testcaseFinished();
798 API::QualifiedName& qname = testcase.name();
799 qname.module__name () = testcase_name.module_name;
800 qname.testcase__name() = testcase_name.definition_name;
801 testcase.verdict() = verdict;
802 testcase.reason() = reason;
803 // FIXME: our caller had a CHARSTRING but gave us a C string. Now we have to measure it again :(
804 log(event);
805 }
806
807 void LoggerPluginManager::log_controlpart_start_stop(const char *module_name, int finished)
808 {
809 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
810 return;
811 API::TitanLogEvent event;
812 fill_common_fields(event, TTCN_Logger::STATISTICS_UNQUALIFIED);
813
814 API::StatisticsType& stats = event.logEvent().choice().statistics();
815 if (finished) stats.choice().controlpartFinish() = module_name;
816 else stats.choice().controlpartStart() = module_name;
817 log(event);
818 }
819
820 void LoggerPluginManager::log_controlpart_errors(unsigned int error_count)
821 {
822 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
823 return;
824 API::TitanLogEvent event;
825 fill_common_fields(event, TTCN_Logger::STATISTICS_UNQUALIFIED);
826
827 event.logEvent().choice().statistics().choice().controlpartErrors() = error_count;
828 log(event);
829 }
830
831 void LoggerPluginManager::log_setverdict(verdicttype new_verdict, verdicttype old_verdict,
832 verdicttype local_verdict, const char *old_reason, const char *new_reason)
833 {
834 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_SETVERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
835 return;
836 API::TitanLogEvent event;
837 fill_common_fields(event, TTCN_Logger::VERDICTOP_SETVERDICT);
838 API::SetVerdictType& set = event.logEvent().choice().verdictOp().choice().setVerdict();
839 set.newVerdict() = new_verdict;
840 set.oldVerdict() = old_verdict;
841 set.localVerdict() = local_verdict;
842 if (old_reason != NULL) set.oldReason() = old_reason;
843 else set.oldReason() = OMIT_VALUE;
844 if (new_reason != NULL) set.newReason() = new_reason;
845 else set.newReason() = OMIT_VALUE;
846 log(event);
847 }
848
849 void LoggerPluginManager::log_getverdict(verdicttype verdict)
850 {
851 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_GETVERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
852 return;
853 API::TitanLogEvent event;
854 fill_common_fields(event, TTCN_Logger::VERDICTOP_GETVERDICT);
855 event.logEvent().choice().verdictOp().choice().getVerdict() = verdict;
856 log(event);
857 }
858
859 void LoggerPluginManager::log_final_verdict(bool is_ptc,
860 verdicttype ptc_verdict, verdicttype local_verdict, verdicttype new_verdict,
861 const char *verdict__reason, int notification, int ptc_compref,
862 const char *ptc_name)
863 {
864 if (!TTCN_Logger::log_this_event(TTCN_Logger::VERDICTOP_FINAL) && (TTCN_Logger::get_emergency_logging()<=0))
865 return;
866 API::TitanLogEvent event;
867 fill_common_fields(event, TTCN_Logger::VERDICTOP_FINAL);
868 API::FinalVerdictType& final = event.logEvent().choice().verdictOp().choice().finalVerdict();
869 if (notification >= 0) {
870 final.choice().notification() = notification;
871 } else {
872 final.choice().info().is__ptc() = is_ptc;
873 final.choice().info().ptc__verdict() = ptc_verdict;
874 final.choice().info().local__verdict() = local_verdict;
875 final.choice().info().new__verdict() = new_verdict;
876 final.choice().info().ptc__compref() = ptc_compref;
877 if (verdict__reason != NULL)
878 final.choice().info().verdict__reason() = verdict__reason;
879 else final.choice().info().verdict__reason() = OMIT_VALUE;
880 if (ptc_name != NULL)
881 final.choice().info().ptc__name() = ptc_name;
882 else final.choice().info().ptc__name() = OMIT_VALUE;
883 }
884 log(event);
885 }
886
887 void LoggerPluginManager::log_verdict_statistics(size_t none_count, double none_percent,
888 size_t pass_count, double pass_percent,
889 size_t inconc_count, double inconc_percent,
890 size_t fail_count, double fail_percent,
891 size_t error_count, double error_percent)
892 {
893 if (!TTCN_Logger::log_this_event(TTCN_Logger::STATISTICS_VERDICT) && (TTCN_Logger::get_emergency_logging()<=0))
894 return;
895 API::TitanLogEvent event;
896 fill_common_fields(event, TTCN_Logger::STATISTICS_VERDICT);
897
898 API::StatisticsType& statistics = event.logEvent().choice().statistics();
899 statistics.choice().verdictStatistics().none__() = none_count;
900 statistics.choice().verdictStatistics().nonePercent() = none_percent;
901 statistics.choice().verdictStatistics().pass__() = pass_count;
902 statistics.choice().verdictStatistics().passPercent() = pass_percent;
903 statistics.choice().verdictStatistics().inconc__() = inconc_count;
904 statistics.choice().verdictStatistics().inconcPercent() = inconc_percent;
905 statistics.choice().verdictStatistics().fail__() = fail_count;
906 statistics.choice().verdictStatistics().failPercent() = fail_percent;
907 statistics.choice().verdictStatistics().error__() = error_count;
908 statistics.choice().verdictStatistics().errorPercent() = error_percent;
909 log(event);
910 }
911
912 void LoggerPluginManager::log_defaultop_activate(const char *name, int id)
913 {
914 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_ACTIVATE) && (TTCN_Logger::get_emergency_logging()<=0))
915 return;
916 API::TitanLogEvent event;
917 fill_common_fields(event, TTCN_Logger::DEFAULTOP_ACTIVATE);
918
919 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopActivate();
920 defaultop.name() = name;
921 defaultop.id() = id;
922 defaultop.end() = API::DefaultEnd::UNKNOWN_VALUE; // don't care
923 log(event);
924 }
925
926 void LoggerPluginManager::log_defaultop_deactivate(const char *name, int id)
927 {
928 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_DEACTIVATE) && (TTCN_Logger::get_emergency_logging()<=0))
929 return;
930 API::TitanLogEvent event;
931 fill_common_fields(event, TTCN_Logger::DEFAULTOP_DEACTIVATE);
932
933 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopDeactivate();
934 defaultop.name() = name;
935 defaultop.id() = id;
936 defaultop.end() = API::DefaultEnd::UNKNOWN_VALUE; // don't care
937 log(event); // whoa, deja vu!
938 }
939
940 void LoggerPluginManager::log_defaultop_exit(const char *name, int id, int x)
941 {
942 if (!TTCN_Logger::log_this_event(TTCN_Logger::DEFAULTOP_EXIT) && (TTCN_Logger::get_emergency_logging()<=0))
943 return;
944 API::TitanLogEvent event;
945 fill_common_fields(event, TTCN_Logger::DEFAULTOP_EXIT);
946
947 API::DefaultOp& defaultop = event.logEvent().choice().defaultEvent().choice().defaultopExit();
948 defaultop.name() = name;
949 defaultop.id() = id;
950 defaultop.end() = x;
951 log(event);
952 }
953
954 void LoggerPluginManager::log_executor_runtime(API::ExecutorRuntime_reason reason)
955 {
956 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
957 return;
958 API::TitanLogEvent event;
959 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
960
961 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
962 exec.reason() = reason;
963 exec.module__name() = OMIT_VALUE;
964 exec.testcase__name() = OMIT_VALUE;
965 exec.pid() = OMIT_VALUE;
966 exec.fd__setsize() = OMIT_VALUE;
967 log(event);
968 }
969
970 void LoggerPluginManager::log_HC_start(const char *host)
971 {
972 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
973 return;
974 API::TitanLogEvent event;
975 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
976
977 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
978 exec.reason() = API::ExecutorRuntime_reason::host__controller__started;
979 exec.module__name() = host; // "reuse" charstring member
980 exec.testcase__name() = OMIT_VALUE;
981 exec.pid() = OMIT_VALUE;
982 exec.fd__setsize() = OMIT_VALUE;
983 log(event);
984 }
985
986 void LoggerPluginManager::log_fd_limits(int fd_limit, long fd_set_size)
987 {
988 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
989 return;
990 API::TitanLogEvent event;
991 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
992
993 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
994 exec.reason() = API::ExecutorRuntime_reason::fd__limits;
995 exec.module__name() = OMIT_VALUE;
996 exec.testcase__name() = OMIT_VALUE;
997 exec.pid() = fd_limit;
998 exec.fd__setsize() = fd_set_size;
999 log(event);
1000 }
1001
1002 void LoggerPluginManager::log_not_overloaded(int pid)
1003 {
1004 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1005 return;
1006 API::TitanLogEvent event;
1007 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1008
1009 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1010 exec.reason() = API::ExecutorRuntime_reason::overloaded__no__more;
1011 exec.module__name() = OMIT_VALUE;
1012 exec.testcase__name() = OMIT_VALUE;
1013 exec.pid() = pid;
1014 exec.fd__setsize() = OMIT_VALUE;
1015 log(event);
1016 }
1017
1018 void LoggerPluginManager::log_testcase_exec(const char *tc, const char *module)
1019 {
1020 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1021 return;
1022 API::TitanLogEvent event;
1023 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1024
1025 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1026 exec.reason() = API::ExecutorRuntime_reason::executing__testcase__in__module;
1027 exec.module__name() = module;
1028 exec.testcase__name() = tc;
1029 exec.pid() = OMIT_VALUE;
1030 exec.fd__setsize() = OMIT_VALUE;
1031 log(event);
1032 }
1033
1034 void LoggerPluginManager::log_module_init(const char *module, bool finish)
1035 {
1036 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1037 return;
1038 API::TitanLogEvent event;
1039 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1040
1041 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1042 exec.reason() = finish
1043 ? API::ExecutorRuntime_reason::initialization__of__module__finished
1044 : API::ExecutorRuntime_reason::initializing__module;
1045 exec.module__name() = module;
1046 exec.testcase__name() = OMIT_VALUE;
1047 exec.pid() = OMIT_VALUE;
1048 exec.fd__setsize() = OMIT_VALUE;
1049 log(event);
1050 }
1051
1052 void LoggerPluginManager::log_mtc_created(long pid)
1053 {
1054 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_RUNTIME) && (TTCN_Logger::get_emergency_logging()<=0))
1055 return;
1056 API::TitanLogEvent event;
1057 fill_common_fields(event, TTCN_Logger::EXECUTOR_RUNTIME);
1058
1059 API::ExecutorRuntime& exec = event.logEvent().choice().executorEvent().choice().executorRuntime();
1060 exec.reason() = API::ExecutorRuntime_reason::mtc__created;
1061 exec.module__name() = OMIT_VALUE;
1062 exec.testcase__name() = OMIT_VALUE;
1063 exec.pid() = pid;
1064 exec.fd__setsize() = OMIT_VALUE;
1065 log(event);
1066 }
1067
1068 void LoggerPluginManager::log_configdata(int reason, const char *str)
1069 {
1070 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_CONFIGDATA) && (TTCN_Logger::get_emergency_logging()<=0))
1071 return;
1072 API::TitanLogEvent event;
1073 fill_common_fields(event, TTCN_Logger::EXECUTOR_CONFIGDATA);
1074
1075 API::ExecutorConfigdata& cfg = event.logEvent().choice().executorEvent().choice().executorConfigdata();
1076 cfg.reason() = reason;
1077 if (str != NULL) cfg.param__() = str;
1078 else cfg.param__() = OMIT_VALUE;
1079 log(event);
1080 }
1081
1082 void LoggerPluginManager::log_executor_component(int reason)
1083 {
1084 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_COMPONENT) && (TTCN_Logger::get_emergency_logging()<=0))
1085 return;
1086 API::TitanLogEvent event;
1087 fill_common_fields(event, TTCN_Logger::EXECUTOR_COMPONENT);
1088
1089 API::ExecutorComponent& ec = event.logEvent().choice().executorEvent().choice().executorComponent();
1090 ec.reason() = reason;
1091 ec.compref() = OMIT_VALUE;
1092 log(event);
1093 }
1094
1095 void LoggerPluginManager::log_executor_misc(int reason, const char *name,
1096 const char *address, int port)
1097 {
1098 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
1099 return;
1100 API::TitanLogEvent event;
1101 fill_common_fields(event, TTCN_Logger::EXECUTOR_UNQUALIFIED);
1102
1103 API::ExecutorUnqualified& ex = event.logEvent().choice().executorEvent().choice().executorMisc();
1104 ex.reason() = reason;
1105 ex.name() = name;
1106 ex.addr() = address;
1107 ex.port__() = port;
1108
1109 log(event);
1110 }
1111
1112 void LoggerPluginManager::log_extcommand(TTCN_Logger::extcommand_t action,
1113 const char *cmd)
1114 {
1115 if (!TTCN_Logger::log_this_event(TTCN_Logger::EXECUTOR_EXTCOMMAND) && (TTCN_Logger::get_emergency_logging()<=0))
1116 return;
1117 API::TitanLogEvent event;
1118 fill_common_fields(event, TTCN_Logger::EXECUTOR_EXTCOMMAND);
1119
1120 CHARSTRING& str = (action == TTCN_Logger::EXTCOMMAND_START)
1121 ? event.logEvent().choice().executorEvent().choice().extcommandStart()
1122 : event.logEvent().choice().executorEvent().choice().extcommandSuccess();
1123
1124 str = cmd;
1125 log(event);
1126 }
1127
1128 void LoggerPluginManager::log_matching_done(API::MatchingDoneType_reason reason,
1129 const char *type, int ptc, const char *return_type)
1130 {
1131 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_DONE) && (TTCN_Logger::get_emergency_logging()<=0))
1132 return;
1133 API::TitanLogEvent event;
1134 fill_common_fields(event, TTCN_Logger::MATCHING_DONE);
1135
1136 API::MatchingDoneType& mp = event.logEvent().choice().matchingEvent().choice().matchingDone();
1137 mp.reason() = reason;
1138 mp.type__() = type;
1139 mp.ptc() = ptc;
1140 mp.return__type() = return_type;
1141 log(event);
1142 }
1143
1144 void LoggerPluginManager::log_matching_problem(int reason, int operation,
1145 boolean check, boolean anyport, const char *port_name)
1146 {
1147 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_PROBLEM) && (TTCN_Logger::get_emergency_logging()<=0))
1148 return;
1149 API::TitanLogEvent event;
1150 fill_common_fields(event, TTCN_Logger::MATCHING_PROBLEM);
1151
1152 API::MatchingProblemType& mp = event.logEvent().choice().matchingEvent().choice().matchingProblem();
1153 mp.reason() = reason;
1154 mp.any__port() = anyport;
1155 mp.check__() = check;
1156 mp.operation() = operation;
1157 mp.port__name()= port_name;
1158 log(event);
1159 }
1160
1161 void LoggerPluginManager::log_matching_success(int port_type, const char *port_name,
1162 int compref, const CHARSTRING& info)
1163 {
1164 TTCN_Logger::Severity sev;
1165 if (compref == SYSTEM_COMPREF) {
1166 sev = (port_type == API::PortType::message__)
1167 ? TTCN_Logger::MATCHING_MMSUCCESS : TTCN_Logger::MATCHING_PMSUCCESS;
1168 }
1169 else {
1170 sev = (port_type == API::PortType::message__)
1171 ? TTCN_Logger::MATCHING_MCSUCCESS : TTCN_Logger::MATCHING_PCSUCCESS;
1172 }
1173 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1174 return;
1175 API::TitanLogEvent event;
1176 fill_common_fields(event, sev);
1177
1178 API::MatchingSuccessType& ms = event.logEvent().choice().matchingEvent().choice().matchingSuccess();
1179 ms.port__type() = port_type;
1180 ms.port__name() = port_name;
1181 ms.info() = info;
1182 log(event);
1183 }
1184
1185 void LoggerPluginManager::log_matching_failure(int port_type, const char *port_name,
1186 int compref, int reason, const CHARSTRING& info)
1187 {
1188 TTCN_Logger::Severity sev;
1189 if (compref == SYSTEM_COMPREF) {
1190 sev = (port_type == API::PortType::message__)
1191 ? TTCN_Logger::MATCHING_MMUNSUCC : TTCN_Logger::MATCHING_PMUNSUCC;
1192 }
1193 else {
1194 sev = (port_type == API::PortType::message__)
1195 ? TTCN_Logger::MATCHING_MCUNSUCC : TTCN_Logger::MATCHING_PCUNSUCC;
1196 }
1197 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1198 return;
1199 API::TitanLogEvent event;
1200 fill_common_fields(event, sev);
1201
1202 API::MatchingFailureType& mf = event.logEvent().choice().matchingEvent().choice().matchingFailure();
1203 mf.port__type() = port_type;
1204 mf.port__name() = port_name;
1205 mf.reason() = reason;
1206
1207 if (compref == SYSTEM_COMPREF) {
1208 mf.choice().system__();
1209 }
1210 else mf.choice().compref() = compref;
1211
1212 mf.info() = info;
1213
1214 log(event);
1215 }
1216
1217 void LoggerPluginManager::log_matching_timeout(const char *timer_name)
1218 {
1219 if (!TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_PROBLEM) && (TTCN_Logger::get_emergency_logging()<=0))
1220 return;
1221 API::TitanLogEvent event;
1222 fill_common_fields(event, TTCN_Logger::MATCHING_PROBLEM);
1223
1224 API::MatchingTimeout& mt = event.logEvent().choice().matchingEvent().choice().matchingTimeout();
1225 if (timer_name) mt.timer__name() = timer_name;
1226 else mt.timer__name() = OMIT_VALUE;
1227 log(event);
1228 }
1229
1230 void LoggerPluginManager::log_random(int action, double v, unsigned long u)
1231 {
1232 if (!TTCN_Logger::log_this_event(TTCN_Logger::FUNCTION_RND) && (TTCN_Logger::get_emergency_logging()<=0))
1233 return;
1234 API::TitanLogEvent event;
1235 fill_common_fields(event, TTCN_Logger::FUNCTION_RND);
1236
1237 API::FunctionEvent_choice_random &r = event.logEvent().choice().functionEvent().choice().random();
1238 r.operation()= action;
1239 r.retval() = v;
1240 r.intseed() = u;
1241 log(event);
1242 }
1243
1244 /** Pretend that the control part is executed by a separate component.
1245 *
1246 * In TITAN, the control part is executed on the MTC.
1247 * This does not match the standard, which states:
1248 * "The MTC shall be created by the system automatically at the start
1249 * of each test case execution"; so the MTC is not supposed to exist
1250 * in a control part. For the purpose of logging, we pretend that in the
1251 * control part the current component is not the MTC but another "artificial"
1252 * component "control", similar to "null", "system", or "all".
1253 *
1254 * @param compref
1255 * @return the input value, but substitute CONTROLPART_COMPREF for MTC_COMPREF
1256 * if inside a controlpart.
1257 */
1258 inline int adjust_compref(int compref)
1259 {
1260 if (compref == MTC_COMPREF) {
1261 switch (TTCN_Runtime::get_state()) {
1262 case TTCN_Runtime::MTC_CONTROLPART:
1263 case TTCN_Runtime::SINGLE_CONTROLPART:
1264 compref = CONTROL_COMPREF;
1265 break;
1266 default:
1267 break;
1268 }
1269 }
1270
1271 return compref;
1272 }
1273
1274 void LoggerPluginManager::log_portconnmap(int operation, int src_compref,
1275 const char *src_port, int dst_compref, const char *dst_port)
1276 {
1277 TTCN_Logger::Severity event_severity;
1278 switch (operation) {
1279 case API::ParPort_operation::connect__:
1280 case API::ParPort_operation::disconnect__:
1281 event_severity = TTCN_Logger::PARALLEL_PORTCONN;
1282 break;
1283 case API::ParPort_operation::map__:
1284 case API::ParPort_operation::unmap__:
1285 event_severity = TTCN_Logger::PARALLEL_PORTMAP;
1286 break;
1287 default:
1288 TTCN_error("Invalid operation");
1289 }
1290
1291 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1292 return;
1293 API::TitanLogEvent event;
1294 fill_common_fields(event, event_severity);
1295
1296 API::ParPort & pp = event.logEvent().choice().parallelEvent().choice().parallelPort();
1297 pp.operation() = operation;
1298 pp.srcCompref() = adjust_compref(src_compref);
1299 pp.srcPort() = src_port;
1300 pp.dstCompref() = adjust_compref(dst_compref);
1301 pp.dstPort() = dst_port;
1302 log(event);
1303 }
1304
1305 void LoggerPluginManager::log_par_ptc(int reason,
1306 const char *module, const char *name, int compref,
1307 const char *compname, const char *tc_loc, int alive_pid, int status)
1308 {
1309 TTCN_Logger::Severity sev =
1310 (alive_pid && reason == API::ParallelPTC_reason::function__finished)
1311 ? TTCN_Logger::PARALLEL_UNQUALIFIED : TTCN_Logger::PARALLEL_PTC;
1312 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0))
1313 return;
1314 API::TitanLogEvent event;
1315 fill_common_fields(event, sev);
1316
1317 API::ParallelPTC& ptc = event.logEvent().choice().parallelEvent().choice().parallelPTC();
1318 ptc.reason() = reason;
1319 ptc.module__() = module;
1320 ptc.name() = name;
1321 ptc.compref() = compref;
1322 ptc.tc__loc() = tc_loc;
1323 ptc.compname() = compname;
1324 ptc.alive__pid() = alive_pid;
1325 ptc.status() = status;
1326 log(event);
1327 }
1328
1329 void LoggerPluginManager::log_port_queue(int operation, const char *port_name,
1330 int compref, int id, const CHARSTRING& address, const CHARSTRING& param)
1331 {
1332 TTCN_Logger::Severity sev;
1333 switch (operation) {
1334 case API::Port__Queue_operation::enqueue__msg:
1335 case API::Port__Queue_operation::extract__msg:
1336 sev = TTCN_Logger::PORTEVENT_MQUEUE;
1337 break;
1338 case API::Port__Queue_operation::enqueue__call:
1339 case API::Port__Queue_operation::enqueue__exception:
1340 case API::Port__Queue_operation::enqueue__reply:
1341 case API::Port__Queue_operation::extract__op:
1342 sev = TTCN_Logger::PORTEVENT_PQUEUE;
1343 break;
1344 default:
1345 TTCN_error("Invalid operation");
1346 }
1347
1348 if (!TTCN_Logger::log_this_event(sev) && (TTCN_Logger::get_emergency_logging()<=0)) return;
1349 API::TitanLogEvent event;
1350 fill_common_fields(event, sev);
1351
1352 API::Port__Queue& pq = event.logEvent().choice().portEvent().choice().portQueue();
1353 pq.operation() = operation;
1354 pq.port__name() = port_name;
1355 pq.compref() = adjust_compref(compref);
1356 pq.msgid() = id;
1357 pq.address__() = address;
1358 pq.param__() = param;
1359 log(event);
1360 }
1361
1362 void LoggerPluginManager::log_port_state(int operation, const char *port_name)
1363 {
1364 if (!TTCN_Logger::log_this_event(TTCN_Logger::PORTEVENT_STATE)) return;
1365 API::TitanLogEvent event;
1366 fill_common_fields(event, TTCN_Logger::PORTEVENT_STATE);
1367
1368 API::Port__State& ps = event.logEvent().choice().portEvent().choice().portState();
1369 ps.operation() = operation;
1370 ps.port__name() = port_name;
1371 log(event);
1372 }
1373
1374 void LoggerPluginManager::log_procport_send(const char *portname, int operation,
1375 int compref, const CHARSTRING& system, const CHARSTRING& param)
1376 {
1377 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1378 ? TTCN_Logger::PORTEVENT_PMOUT : TTCN_Logger::PORTEVENT_PCOUT;
1379 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1380 return;
1381 API::TitanLogEvent event;
1382 fill_common_fields(event, event_severity);
1383
1384 API::Proc__port__out& pt = event.logEvent().choice().portEvent().choice().procPortSend();
1385 pt.port__name() = portname;
1386 pt.operation() = operation;
1387 pt.compref() = compref;
1388 if (compref == SYSTEM_COMPREF) { // it's mapped
1389 pt.sys__name() = system;
1390 }
1391 pt.parameter() = param;
1392
1393 log(event);
1394 }
1395
1396 void LoggerPluginManager::log_procport_recv(const char *portname, int operation,
1397 int compref, boolean check, const CHARSTRING& param, int id)
1398 {
1399 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1400 ? TTCN_Logger::PORTEVENT_PMIN : TTCN_Logger::PORTEVENT_PCIN;
1401 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1402 return;
1403 API::TitanLogEvent event;
1404 fill_common_fields(event, event_severity);
1405
1406 API::Proc__port__in& pt = event.logEvent().choice().portEvent().choice().procPortRecv();
1407 pt.port__name() = portname;
1408 pt.operation() = operation;
1409 pt.compref() = compref;
1410 pt.check__() = check;
1411 pt.parameter() = param;
1412 pt.msgid() = id;
1413
1414 log(event);
1415 }
1416
1417 void LoggerPluginManager::log_msgport_send(const char *portname, int compref,
1418 const CHARSTRING& param)
1419 {
1420 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1421 ? TTCN_Logger::PORTEVENT_MMSEND : TTCN_Logger::PORTEVENT_MCSEND;
1422 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0)) return;
1423 API::TitanLogEvent event;
1424 fill_common_fields(event, event_severity);
1425
1426 API::Msg__port__send& ms = event.logEvent().choice().portEvent().choice().msgPortSend();
1427 ms.port__name() = portname;
1428 ms.compref() = compref;
1429 ms.parameter() = param;
1430
1431 log(event);
1432 }
1433
1434 void LoggerPluginManager::log_msgport_recv(const char *portname, int operation,
1435 int compref, const CHARSTRING& system, const CHARSTRING& param, int id)
1436 {
1437 TTCN_Logger::Severity event_severity = (compref == SYSTEM_COMPREF)
1438 ? TTCN_Logger::PORTEVENT_MMRECV : TTCN_Logger::PORTEVENT_MCRECV;
1439 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1440 return;
1441 API::TitanLogEvent event;
1442 fill_common_fields(event, event_severity);
1443
1444 API::Msg__port__recv& ms = event.logEvent().choice().portEvent().choice().msgPortRecv();
1445 ms.port__name() = portname;
1446 ms.compref() = compref;
1447 if (compref == SYSTEM_COMPREF) { // it's mapped
1448 ms.sys__name() = system;
1449 }
1450 ms.operation() = operation;
1451 ms.msgid() = id;
1452 ms.parameter() = param;
1453
1454 log(event);
1455 }
1456
1457 void LoggerPluginManager::log_dualport_map(boolean incoming, const char *target_type,
1458 const CHARSTRING& value, int id)
1459 {
1460 TTCN_Logger::Severity event_severity = incoming
1461 ? TTCN_Logger::PORTEVENT_DUALRECV : TTCN_Logger::PORTEVENT_DUALSEND;
1462 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1463 return;
1464 API::TitanLogEvent event;
1465 fill_common_fields(event, event_severity);
1466
1467 API::Dualface__mapped& dual = event.logEvent().choice().portEvent().choice().dualMapped();
1468 dual.incoming() = incoming;
1469 dual.target__type() = target_type;
1470 dual.value__() = value;
1471 dual.msgid() = id;
1472
1473 log(event);
1474 }
1475
1476 void LoggerPluginManager::log_dualport_discard(boolean incoming, const char *target_type,
1477 const char *port_name, boolean unhandled)
1478 {
1479 TTCN_Logger::Severity event_severity = incoming
1480 ? TTCN_Logger::PORTEVENT_DUALRECV : TTCN_Logger::PORTEVENT_DUALSEND;
1481 if (!TTCN_Logger::log_this_event(event_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1482 return;
1483 API::TitanLogEvent event;
1484 fill_common_fields(event, event_severity);
1485
1486 API::Dualface__discard& dualop = event.logEvent().choice().portEvent().choice().dualDiscard();
1487 dualop.incoming() = incoming;
1488 dualop.target__type() = target_type;
1489 dualop.port__name() = port_name;
1490 dualop.unhandled() = unhandled;
1491
1492 log(event);
1493 }
1494
1495 void LoggerPluginManager::log_port_misc(int reason, const char *port_name,
1496 int remote_component, const char *remote_port, const char *ip_address,
1497 int tcp_port, int new_size)
1498 {
1499 if (!TTCN_Logger::log_this_event(TTCN_Logger::PORTEVENT_UNQUALIFIED) && (TTCN_Logger::get_emergency_logging()<=0))
1500 return;
1501 API::TitanLogEvent event;
1502 fill_common_fields(event, TTCN_Logger::PORTEVENT_UNQUALIFIED);
1503
1504 API::Port__Misc& portmisc = event.logEvent().choice().portEvent().choice().portMisc();
1505 portmisc.reason() = reason;
1506 portmisc.port__name() = port_name;
1507 portmisc.remote__component() = remote_component;
1508 portmisc.remote__port() = remote_port;
1509 portmisc.ip__address() = ip_address;
1510 portmisc.tcp__port() = tcp_port;
1511 portmisc.new__size() = new_size;
1512
1513 log(event);
1514 }
1515
1516
1517 // End of externally callable functions
1518
1519 /// Construct an event string, one by one. Event construction is not
1520 /// supported for all event types. E.g. those event types with fixed format
1521 /// like TIMEROP_* events have nothing to do with this at all.
1522 void LoggerPluginManager::append_event_str(const char *str)
1523 {
1524 if (!this->current_event_) return;
1525 ActiveEvent& curr = *this->current_event_;
1526 const size_t str_len = strlen(str);
1527 if (!str_len) return; // don't bother with empty string
1528
1529 if (curr.event_str_ != NULL) { // event_str_ already allocated
1530 if (!curr.fake_) {
1531 // pieces_ may be NULL, in which case Realloc calls Malloc
1532 curr.pieces_ = (size_t*)Realloc(curr.pieces_, sizeof(size_t) * curr.num_pieces_);
1533 // Remember the current end
1534 curr.pieces_[curr.num_pieces_++-1] = curr.event_str_len_;
1535 }
1536 // Don't bother remembering the pieces for a log2str event
1537
1538 if ( curr.event_str_len_ + str_len > curr.event_str_size_) {
1539 for (; curr.event_str_len_ + str_len > curr.event_str_size_;
1540 curr.event_str_size_ *= 2) ; // double until it fits
1541 curr.event_str_ = (char *)Realloc(curr.event_str_, curr.event_str_size_);
1542 memset(curr.event_str_ + curr.event_str_len_, '\0',
1543 curr.event_str_size_ - curr.event_str_len_);
1544 }
1545 memcpy(curr.event_str_ + curr.event_str_len_, str, str_len);
1546 curr.event_str_len_ += str_len;
1547 } else { // the first piece
1548 curr.event_str_len_ = str_len;
1549 curr.event_str_size_ = str_len * 2; // must be strictly bigger than str_len
1550 curr.event_str_ = (char *)Malloc(curr.event_str_size_);
1551 memcpy(curr.event_str_, str, str_len);
1552 memset(curr.event_str_ + str_len, '\0',
1553 curr.event_str_size_ - str_len);
1554 curr.num_pieces_++;
1555 // Do not allocate memory for the first piece; it ends at event_str_len_
1556 }
1557 }
1558
1559 char* LoggerPluginManager::get_current_event_str()
1560 {
1561 if (!this->current_event_) return 0;
1562 size_t str_len = current_event_->event_str_len_ + 1;
1563 char* result = (char*)Malloc(str_len);
1564 memcpy(result, current_event_->event_str_, str_len - 1);
1565 result[str_len - 1] = '\0';
1566 return result;
1567 }
1568
1569 void LoggerPluginManager::begin_event(TTCN_Logger::Severity msg_severity,
1570 bool log2str)
1571 {
1572 event_destination_t event_dest;
1573 if (log2str) event_dest = ED_STRING;
1574 else event_dest =
1575 TTCN_Logger::log_this_event(msg_severity) ? ED_FILE : ED_NONE;
1576 // We are in the middle of another event, allocate a new entry for this
1577 // event. The other active events are available through outer events.
1578 // We're not (re)using the `outermost_event' buffer.
1579 ActiveEvent *new_event = new ActiveEvent(log2str, event_dest);
1580 if (!log2str) fill_common_fields(new_event->get_event(), msg_severity);
1581 new_event->outer_event_ = this->current_event_;
1582 this->current_event_ = new_event;
1583 }
1584
1585 void LoggerPluginManager::end_event()
1586 {
1587 if (this->current_event_ == NULL) {
1588 // Invalid usage.
1589 const char *message = "TTCN_Logger::end_event(): not in event.";
1590 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1591 return;
1592 }
1593
1594 ActiveEvent& curr = *this->current_event_;
1595 switch (curr.event_destination_) {
1596 case ED_NONE:
1597 break;
1598 case ED_FILE:
1599 switch ((TTCN_Logger::Severity)(int)curr.get_event().severity()) {
1600 case TTCN_Logger::DEBUG_ENCDEC:
1601 case TTCN_Logger::DEBUG_TESTPORT:
1602 case TTCN_Logger::DEBUG_UNQUALIFIED:
1603 curr.get_event().logEvent().choice().debugLog().text() =
1604 CHARSTRING(curr.event_str_len_, curr.event_str_);
1605 curr.get_event().logEvent().choice().debugLog().category() = 0; // not yet used
1606 break;
1607
1608 case TTCN_Logger::ERROR_UNQUALIFIED:
1609 curr.get_event().logEvent().choice().errorLog().text() =
1610 CHARSTRING(curr.event_str_len_, curr.event_str_);
1611 curr.get_event().logEvent().choice().errorLog().category() = 0; // not yet used
1612 break;
1613
1614 case TTCN_Logger::ACTION_UNQUALIFIED:
1615 // fall through
1616 case TTCN_Logger::USER_UNQUALIFIED: {
1617 // Select the list for either userLog or action; treatment is the same.
1618 API::Strings_str__list& slist = (curr.get_event().severity() == TTCN_Logger::USER_UNQUALIFIED)
1619 ? curr.get_event().logEvent().choice().userLog().str__list()
1620 : curr.get_event().logEvent().choice().actionEvent().str__list();
1621 if (curr.num_pieces_ > 0) {
1622 // First piece. If num_pieces_==1, pieces_ is not allocated, use the full length.
1623 size_t len0 = curr.num_pieces_ > 1 ? curr.pieces_[0] : curr.event_str_len_;
1624 slist[0] = CHARSTRING(len0, curr.event_str_);
1625 // Subsequent pieces from pieces_[i-1] to pieces_[i] (exclusive)
1626 for (size_t i = 1; i < curr.num_pieces_ - 1; ++i) {
1627 slist[i] = CHARSTRING(
1628 curr.pieces_[i] - curr.pieces_[i - 1],
1629 curr.event_str_ + curr.pieces_[i - 1]);
1630 }
1631 // Last piece (if it's not the same as the first)
1632 if (curr.num_pieces_ > 1) { // i == num_pieces_-1
1633 slist[curr.num_pieces_ - 1]= CHARSTRING(
1634 curr.event_str_len_ - curr.pieces_[curr.num_pieces_-2],
1635 curr.event_str_ + curr.pieces_[curr.num_pieces_-2]);
1636 }
1637 }
1638 else slist = NULL_VALUE; // make sure it's bound but empty
1639 break; }
1640
1641 case TTCN_Logger::WARNING_UNQUALIFIED:
1642 curr.get_event().logEvent().choice().warningLog().text() =
1643 CHARSTRING(curr.event_str_len_, curr.event_str_);
1644 curr.get_event().logEvent().choice().warningLog().category() = 0; // not yet used
1645 break;
1646
1647 default:
1648 curr.get_event().logEvent().choice().unhandledEvent() =
1649 CHARSTRING(curr.event_str_len_, curr.event_str_);
1650 break;
1651 } // switch(severity)
1652 log(curr.get_event());
1653 break;
1654 case ED_STRING:
1655 TTCN_Logger::fatal_error("TTCN_Logger::end_event(): event with string "
1656 "destination was found, missing call of "
1657 "TTCN_Logger::end_event_log2str().");
1658 default:
1659 TTCN_Logger::fatal_error("TTCN_Logger::end_event(): invalid event "
1660 "destination.");
1661 } // switch(event_destination)
1662
1663 // Remove the current (already logged) event from the list of pending
1664 // events and select a higher level event on the stack. We're not
1665 // following the old implementation regarding the `outermost_event' stuff.
1666 ActiveEvent *outer_event = curr.outer_event_;
1667 Free(curr.event_str_);
1668 Free(curr.pieces_);
1669 delete this->current_event_;
1670 this->current_event_ = outer_event;
1671 }
1672
1673 CHARSTRING LoggerPluginManager::end_event_log2str()
1674 {
1675 if (this->current_event_ == NULL) {
1676 // Invalid usage.
1677 const char *message = "TTCN_Logger::end_event_log2str(): not in event.";
1678 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1679 return CHARSTRING(); // unbound!
1680 }
1681
1682 ActiveEvent& curr = *this->current_event_;
1683 CHARSTRING ret_val(curr.event_str_len_, curr.event_str_);
1684
1685 ActiveEvent *outer_event = curr.outer_event_;
1686 Free(curr.event_str_);
1687 Free(curr.pieces_);
1688 delete this->current_event_;
1689 // Otherwise, we don't save the current event to be `outermost_event',
1690 // like the previous implementation. An initialized `outermost_event' is
1691 // not the sign of an initialized logger. NULL or not, assign.
1692 this->current_event_ = outer_event;
1693 return ret_val;
1694 }
1695
1696 void LoggerPluginManager::finish_event()
1697 {
1698 // Drop events which have string destination in case of log2str()
1699 // operations. There is no try-catch block to delete the event. Avoid
1700 // data/log file corruption if there's an exception inside a log2str(),
1701 // which is inside a log().
1702 while (this->current_event_ != NULL &&
1703 this->current_event_->event_destination_ == ED_STRING)
1704 (void)end_event_log2str();
1705
1706 if (this->current_event_ != NULL) {
1707 log_event_str("<unfinished>");
1708 end_event();
1709 }
1710 }
1711
1712 // Simply append the contents STR_PTR to the end of the current event.
1713 // Everything is a string here.
1714 void LoggerPluginManager::log_event_str(const char *str_ptr)
1715 {
1716 if (this->current_event_ != NULL) {
1717 if (this->current_event_->event_destination_ == ED_NONE) return;
1718 if (str_ptr == NULL) str_ptr = "<NULL pointer>";
1719 append_event_str(str_ptr);
1720 } else {
1721 // Invalid usage.
1722 const char *message = "TTCN_Logger::log_event_str(): not in event.";
1723 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1724 }
1725 }
1726
1727 void LoggerPluginManager::log_char(char c)
1728 {
1729 if (this->current_event_ != NULL) {
1730 if (this->current_event_->event_destination_ == ED_NONE || c == '\0') return;
1731 const char c_str[2] = { c, 0 };
1732 append_event_str(c_str);
1733 } else {
1734 // Invalid usage.
1735 const char *message = "TTCN_Logger::log_char(): not in event.";
1736 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1737 }
1738 }
1739
1740 void LoggerPluginManager::log_event_va_list(const char *fmt_str,
1741 va_list p_var)
1742 {
1743 if (this->current_event_ != NULL) {
1744 if (this->current_event_->event_destination_ == ED_NONE) return;
1745 if (fmt_str == NULL) fmt_str = "<NULL format string>";
1746 char *message = mprintf_va_list(fmt_str, p_var);
1747 append_event_str(message);
1748 Free(message);
1749 } else {
1750 // Invalid usage.
1751 const char *message = "TTCN_Logger::log_event(): not in event.";
1752 log_unhandled_event(TTCN_Logger::WARNING_UNQUALIFIED, message, strlen(message));
1753 }
1754 }
1755
1756 void LoggerPluginManager::log_va_list(TTCN_Logger::Severity msg_severity,
1757 const char *fmt_str, va_list p_var)
1758 {
1759 if (!TTCN_Logger::log_this_event(msg_severity) && (TTCN_Logger::get_emergency_logging()<=0))
1760 return;
1761 if (fmt_str == NULL) fmt_str = "<NULL format string>";
1762 // Allocate a temporary buffer for this event.
1763 char *message_buf = mprintf_va_list(fmt_str, p_var);
1764 log_unhandled_event(msg_severity, message_buf, mstrlen(message_buf));
1765 Free(message_buf);
1766 }
1767
1768
1769 LoggerPlugin *LoggerPluginManager::find_plugin(const char *name)
1770 {
1771 assert(name != NULL);
1772 for (size_t i = 0; i < this->n_plugins_; i++) {
1773 const char *plugin_name = this->plugins_[i]->ref_->plugin_name();
1774 // TODO: If the name is not set in the plug-in, a warning should be
1775 // reported instead.
1776 if (plugin_name != NULL && !strcmp(name, plugin_name)) {
1777 return this->plugins_[i];
1778 }
1779 }
1780 return NULL;
1781 }
1782
1783 #ifdef MEMORY_DEBUG
1784 // new has been redefined in dbgnew.hh, undo it
1785 #undef new
1786 #endif
1787
1788 inline void * operator new (size_t, void * p) throw() { return p ; }
1789
1790 LoggerPluginManager::ActiveEvent::ActiveEvent(bool fake_event, event_destination_t dest)
1791 : event_()
1792 , event_str_(NULL)
1793 , event_str_len_(0)
1794 , event_str_size_(0)
1795 , event_destination_(dest)
1796 , outer_event_(NULL)
1797 , num_pieces_(0)
1798 , pieces_(NULL)
1799 , fake_(fake_event)
1800 {
1801 if (!fake_event) {
1802 new (event_) TitanLoggerApi::TitanLogEvent(); // placement new
1803 }
1804 }
1805
1806 LoggerPluginManager::ActiveEvent::~ActiveEvent()
1807 {
1808 if (!fake_) {
1809 get_event().~TitanLogEvent(); // explicit destructor call
1810 }
1811 }
This page took 0.111318 seconds and 5 git commands to generate.