Fawkes API Fawkes Development Version
multi.cpp
1
2/***************************************************************************
3 * multi.h - Fawkes multi logger
4 *
5 * Created: Mon May 07 16:44:15 2007
6 * Copyright 2006-2007 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <core/threading/thread.h>
25#include <core/utils/lock_list.h>
26#include <logging/logger.h>
27#include <logging/multi.h>
28#include <sys/time.h>
29
30#include <time.h>
31
32namespace fawkes {
33
34/// @cond INTERNALS
35class MultiLoggerData
36{
37public:
38 MultiLoggerData()
39 {
40 mutex = new Mutex();
41 }
42
43 ~MultiLoggerData()
44 {
45 delete mutex;
46 mutex = NULL;
47 }
48
49 LockList<Logger *> loggers;
50 LockList<Logger *>::iterator logit;
51 Mutex * mutex;
52 Thread::CancelState old_state;
53};
54/// @endcond
55
56/** @class MultiLogger <logging/multi.h>
57 * Log through multiple loggers.
58 * It can be hand to have the opportunity to log to multiple channels, for
59 * example log to a file and via network to a remote console. This can be
60 * done with the MultiLogger. You can add an arbitrary number of loggers
61 * to log the output to. Use the minimum number of necessary loggers though
62 * because this can cause a high burden on log users if you have too many
63 * loggers.
64 *
65 * Note that the multi logger takes over the ownership of the logger. That
66 * means that the multi logger destroys all sub-loggers when it is deleted
67 * itself. If you want to take over the loggers without destroying them you
68 * have to properly remove them before destroying the multi logger.
69 *
70 * @author Tim Niemueller
71 */
72
73/** Constructor.
74 * This will create the logger without any sub-loggers. Message that are
75 * logged are simply ignored.
76 */
78{
79 data = new MultiLoggerData();
80}
81
82/** Constructor.
83 * This sets one sub-logger that messages are sent to.
84 * @param logger sub-logger
85 */
87{
88 data = new MultiLoggerData();
89 data->loggers.push_back_locked(logger);
90}
91
92/** Destructor.
93 * This will destroy all sub-data->loggers (they are deleted).
94 */
96{
97 data->loggers.lock();
98 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
99 delete (*data->logit);
100 }
101 data->loggers.clear();
102 data->loggers.unlock();
103 delete data;
104}
105
106/** Add a logger.
107 * @param logger new sub-logger to add
108 */
109void
111{
112 data->mutex->lock();
114 data->loggers.lock();
115 data->loggers.push_back(logger);
116 logger->set_loglevel(log_level);
117 data->loggers.sort();
118 data->loggers.unique();
119 data->loggers.unlock();
120 Thread::set_cancel_state(data->old_state);
121 data->mutex->unlock();
122}
123
124/** Remove logger.
125 * @param logger Sub-logger to remove
126 */
127void
129{
130 data->mutex->lock();
132
133 data->loggers.remove_locked(logger);
134 Thread::set_cancel_state(data->old_state);
135 data->mutex->unlock();
136}
137
138void
140{
141 data->mutex->lock();
143 log_level = level;
144
145 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
146 (*data->logit)->set_loglevel(level);
147 }
148 Thread::set_cancel_state(data->old_state);
149 data->mutex->unlock();
150}
151
152void
153MultiLogger::log(LogLevel level, const char *component, const char *format, ...)
154{
155 struct timeval now;
156 gettimeofday(&now, NULL);
157 data->mutex->lock();
159
160 va_list va;
161 va_start(va, format);
162 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
163 va_list vac;
164 va_copy(vac, va);
165 (*data->logit)->vtlog(level, &now, component, format, vac);
166 va_end(vac);
167 }
168 va_end(va);
169 Thread::set_cancel_state(data->old_state);
170 data->mutex->unlock();
171}
172
173void
174MultiLogger::log_debug(const char *component, const char *format, ...)
175{
176 struct timeval now;
177 gettimeofday(&now, NULL);
178 data->mutex->lock();
180
181 va_list va;
182 va_start(va, format);
183 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
184 va_list vac;
185 va_copy(vac, va);
186 (*data->logit)->vlog_debug(component, format, vac);
187 va_end(vac);
188 }
189 va_end(va);
190 Thread::set_cancel_state(data->old_state);
191 data->mutex->unlock();
192}
193
194void
195MultiLogger::log_info(const char *component, const char *format, ...)
196{
197 struct timeval now;
198 gettimeofday(&now, NULL);
199 data->mutex->lock();
201
202 va_list va;
203 va_start(va, format);
204 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
205 va_list vac;
206 va_copy(vac, va);
207 (*data->logit)->vlog_info(component, format, vac);
208 va_end(vac);
209 }
210 va_end(va);
211 Thread::set_cancel_state(data->old_state);
212 data->mutex->unlock();
213}
214
215void
216MultiLogger::log_warn(const char *component, const char *format, ...)
217{
218 struct timeval now;
219 gettimeofday(&now, NULL);
220 data->mutex->lock();
222
223 va_list va;
224 va_start(va, format);
225 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
226 va_list vac;
227 va_copy(vac, va);
228 (*data->logit)->vlog_warn(component, format, vac);
229 va_end(vac);
230 }
231 va_end(va);
232 Thread::set_cancel_state(data->old_state);
233 data->mutex->unlock();
234}
235
236void
237MultiLogger::log_error(const char *component, const char *format, ...)
238{
239 struct timeval now;
240 gettimeofday(&now, NULL);
241 data->mutex->lock();
243
244 va_list va;
245 va_start(va, format);
246 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
247 va_list vac;
248 va_copy(vac, va);
249 (*data->logit)->vlog_error(component, format, vac);
250 va_end(vac);
251 }
252 va_end(va);
253 Thread::set_cancel_state(data->old_state);
254 data->mutex->unlock();
255}
256
257void
258MultiLogger::log(LogLevel level, const char *component, Exception &e)
259{
260 struct timeval now;
261 gettimeofday(&now, NULL);
262 data->mutex->lock();
264
265 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
266 (*data->logit)->log(level, component, e);
267 }
268 Thread::set_cancel_state(data->old_state);
269 data->mutex->unlock();
270}
271
272void
273MultiLogger::log_debug(const char *component, Exception &e)
274{
275 struct timeval now;
276 gettimeofday(&now, NULL);
277 data->mutex->lock();
279
280 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
281 (*data->logit)->tlog_debug(&now, component, e);
282 }
283
284 Thread::set_cancel_state(data->old_state);
285 data->mutex->unlock();
286}
287
288void
289MultiLogger::log_info(const char *component, Exception &e)
290{
291 struct timeval now;
292 gettimeofday(&now, NULL);
293 data->mutex->lock();
295
296 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
297 (*data->logit)->tlog_info(&now, component, e);
298 }
299 Thread::set_cancel_state(data->old_state);
300 data->mutex->unlock();
301}
302
303void
304MultiLogger::log_warn(const char *component, Exception &e)
305{
306 struct timeval now;
307 gettimeofday(&now, NULL);
308 data->mutex->lock();
310
311 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
312 (*data->logit)->tlog_warn(&now, component, e);
313 }
314 Thread::set_cancel_state(data->old_state);
315 data->mutex->unlock();
316}
317
318void
319MultiLogger::log_error(const char *component, Exception &e)
320{
321 struct timeval now;
322 gettimeofday(&now, NULL);
323 data->mutex->lock();
325
326 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
327 (*data->logit)->tlog_error(&now, component, e);
328 }
329 Thread::set_cancel_state(data->old_state);
330 data->mutex->unlock();
331}
332
333void
334MultiLogger::vlog(LogLevel level, const char *component, const char *format, va_list va)
335{
336 struct timeval now;
337 gettimeofday(&now, NULL);
338 data->mutex->lock();
340
341 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
342 va_list vac;
343 va_copy(vac, va);
344 (*data->logit)->vlog(level, component, format, vac);
345 va_end(vac);
346 }
347 Thread::set_cancel_state(data->old_state);
348 data->mutex->unlock();
349}
350
351void
352MultiLogger::vlog_debug(const char *component, const char *format, va_list va)
353{
354 struct timeval now;
355 gettimeofday(&now, NULL);
356 data->mutex->lock();
358
359 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
360 va_list vac;
361 va_copy(vac, va);
362 (*data->logit)->vtlog_debug(&now, component, format, vac);
363 va_end(vac);
364 }
365 Thread::set_cancel_state(data->old_state);
366 data->mutex->unlock();
367}
368
369void
370MultiLogger::vlog_info(const char *component, const char *format, va_list va)
371{
372 struct timeval now;
373 gettimeofday(&now, NULL);
374 data->mutex->lock();
376
377 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
378 va_list vac;
379 va_copy(vac, va);
380 (*data->logit)->vtlog_info(&now, component, format, vac);
381 va_end(vac);
382 }
383 Thread::set_cancel_state(data->old_state);
384 data->mutex->unlock();
385}
386
387void
388MultiLogger::vlog_warn(const char *component, const char *format, va_list va)
389{
390 struct timeval now;
391 gettimeofday(&now, NULL);
392 data->mutex->lock();
394
395 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
396 va_list vac;
397 va_copy(vac, va);
398 (*data->logit)->vtlog_warn(&now, component, format, vac);
399 va_end(vac);
400 }
401 Thread::set_cancel_state(data->old_state);
402 data->mutex->unlock();
403}
404
405void
406MultiLogger::vlog_error(const char *component, const char *format, va_list va)
407{
408 struct timeval now;
409 gettimeofday(&now, NULL);
410 data->mutex->lock();
412
413 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
414 va_list vac;
415 va_copy(vac, va);
416 (*data->logit)->vtlog_error(&now, component, format, vac);
417 va_end(vac);
418 }
419 Thread::set_cancel_state(data->old_state);
420 data->mutex->unlock();
421}
422
423void
424MultiLogger::tlog(LogLevel level, struct timeval *t, const char *component, const char *format, ...)
425{
426 data->mutex->lock();
428 va_list va;
429 va_start(va, format);
430 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
431 va_list vac;
432 va_copy(vac, va);
433 (*data->logit)->vtlog(level, t, component, format, vac);
434 va_end(vac);
435 }
436 va_end(va);
437 Thread::set_cancel_state(data->old_state);
438 data->mutex->unlock();
439}
440
441void
442MultiLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
443{
444 data->mutex->lock();
446 va_list va;
447 va_start(va, format);
448 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
449 va_list vac;
450 va_copy(vac, va);
451 (*data->logit)->vlog_debug(component, format, vac);
452 va_end(vac);
453 }
454 va_end(va);
455 Thread::set_cancel_state(data->old_state);
456 data->mutex->unlock();
457}
458
459void
460MultiLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
461{
462 data->mutex->lock();
464
465 va_list va;
466 va_start(va, format);
467 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
468 va_list vac;
469 va_copy(vac, va);
470 (*data->logit)->vtlog_info(t, component, format, vac);
471 va_end(vac);
472 }
473 va_end(va);
474 Thread::set_cancel_state(data->old_state);
475 data->mutex->unlock();
476}
477
478void
479MultiLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
480{
481 data->mutex->lock();
483
484 va_list va;
485 va_start(va, format);
486 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
487 va_list vac;
488 va_copy(vac, va);
489 (*data->logit)->vtlog_warn(t, component, format, vac);
490 va_end(vac);
491 }
492 va_end(va);
493 Thread::set_cancel_state(data->old_state);
494 data->mutex->unlock();
495}
496
497void
498MultiLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
499{
500 data->mutex->lock();
502
503 va_list va;
504 va_start(va, format);
505 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
506 va_list vac;
507 va_copy(vac, va);
508 (*data->logit)->vtlog_error(t, component, format, vac);
509 va_end(vac);
510 }
511 va_end(va);
512 Thread::set_cancel_state(data->old_state);
513 data->mutex->unlock();
514}
515
516void
517MultiLogger::tlog(LogLevel level, struct timeval *t, const char *component, Exception &e)
518{
519 data->mutex->lock();
521
522 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
523 (*data->logit)->tlog(level, t, component, e);
524 }
525 Thread::set_cancel_state(data->old_state);
526 data->mutex->unlock();
527}
528
529void
530MultiLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
531{
532 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
533 (*data->logit)->tlog_error(t, component, e);
534 }
535}
536
537void
538MultiLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
539{
540 data->mutex->lock();
542
543 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
544 (*data->logit)->tlog_error(t, component, e);
545 }
546 Thread::set_cancel_state(data->old_state);
547 data->mutex->unlock();
548}
549
550void
551MultiLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
552{
553 data->mutex->lock();
555
556 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
557 (*data->logit)->tlog_error(t, component, e);
558 }
559 Thread::set_cancel_state(data->old_state);
560 data->mutex->unlock();
561}
562
563void
564MultiLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
565{
566 data->mutex->lock();
568
569 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
570 (*data->logit)->tlog_error(t, component, e);
571 }
572 Thread::set_cancel_state(data->old_state);
573 data->mutex->unlock();
574}
575
576void
578 struct timeval *t,
579 const char * component,
580 const char * format,
581 va_list va)
582{
583 data->mutex->lock();
585
586 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
587 va_list vac;
588 va_copy(vac, va);
589 (*data->logit)->vtlog(level, t, component, format, vac);
590 va_end(vac);
591 }
592 Thread::set_cancel_state(data->old_state);
593 data->mutex->unlock();
594}
595
596void
597MultiLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
598{
599 data->mutex->lock();
601
602 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
603 va_list vac;
604 va_copy(vac, va);
605 (*data->logit)->vtlog_debug(t, component, format, vac);
606 va_end(vac);
607 }
608 Thread::set_cancel_state(data->old_state);
609 data->mutex->unlock();
610}
611
612void
613MultiLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
614{
615 data->mutex->lock();
617
618 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
619 va_list vac;
620 va_copy(vac, va);
621 (*data->logit)->vtlog_info(t, component, format, vac);
622 va_end(vac);
623 }
624 Thread::set_cancel_state(data->old_state);
625 data->mutex->unlock();
626}
627
628void
629MultiLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
630{
631 data->mutex->lock();
633
634 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
635 va_list vac;
636 va_copy(vac, va);
637 (*data->logit)->vtlog_warn(t, component, format, vac);
638 va_end(vac);
639 }
640 Thread::set_cancel_state(data->old_state);
641 data->mutex->unlock();
642}
643
644void
645MultiLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
646{
647 data->mutex->lock();
649
650 for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
651 va_list vac;
652 va_copy(vac, va);
653 (*data->logit)->vtlog_error(t, component, format, vac);
654 va_end(vac);
655 }
656 Thread::set_cancel_state(data->old_state);
657 data->mutex->unlock();
658}
659
660} // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
Interface for logging.
Definition: logger.h:42
LogLevel
Log level.
Definition: logger.h:51
LogLevel log_level
Minimum log level.
Definition: logger.h:126
virtual void vlog(LogLevel level, const char *component, const char *format, va_list va)
Log message for given log level.
Definition: multi.cpp:334
virtual void log(LogLevel level, const char *component, const char *format,...)
Log message of given log level.
Definition: multi.cpp:153
virtual ~MultiLogger()
Destructor.
Definition: multi.cpp:95
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: multi.cpp:479
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: multi.cpp:195
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: multi.cpp:442
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Log error message for specific time.
Definition: multi.cpp:645
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: multi.cpp:406
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: multi.cpp:352
virtual void vtlog(LogLevel level, struct timeval *t, const char *component, const char *format, va_list va)
Log message for given log level and time.
Definition: multi.cpp:577
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:139
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: multi.cpp:460
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Log debug message for specific time.
Definition: multi.cpp:597
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:110
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: multi.cpp:216
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Log warning message for specific time.
Definition: multi.cpp:629
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:174
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Log informational message for specific time.
Definition: multi.cpp:613
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: multi.cpp:498
virtual void tlog(LogLevel level, struct timeval *t, const char *component, const char *format,...)
Log message of given log level and time.
Definition: multi.cpp:424
MultiLogger()
Constructor.
Definition: multi.cpp:77
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: multi.cpp:370
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: multi.cpp:237
void remove_logger(Logger *logger)
Remove logger.
Definition: multi.cpp:128
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: multi.cpp:388
CancelState
Cancel state.
Definition: thread.h:64
@ CANCEL_DISABLED
thread cannot be cancelled
Definition: thread.h:66
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
Definition: thread.cpp:1396
Fawkes library namespace.