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 
32 namespace fawkes {
33 
34 /// @cond INTERNALS
35 class MultiLoggerData
36 {
37 public:
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  */
109 void
110 MultiLogger::add_logger(Logger *logger)
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  */
127 void
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 
138 void
139 MultiLogger::set_loglevel(LogLevel level)
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 
152 void
153 MultiLogger::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 
173 void
174 MultiLogger::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 
194 void
195 MultiLogger::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 
215 void
216 MultiLogger::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 
236 void
237 MultiLogger::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 
257 void
258 MultiLogger::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 
272 void
273 MultiLogger::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 
288 void
289 MultiLogger::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 
303 void
304 MultiLogger::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 
318 void
319 MultiLogger::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 
333 void
334 MultiLogger::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 
351 void
352 MultiLogger::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 
369 void
370 MultiLogger::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 
387 void
388 MultiLogger::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 
405 void
406 MultiLogger::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 
423 void
424 MultiLogger::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 
441 void
442 MultiLogger::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 
459 void
460 MultiLogger::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 
478 void
479 MultiLogger::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 
497 void
498 MultiLogger::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 
516 void
517 MultiLogger::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 
529 void
530 MultiLogger::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 
537 void
538 MultiLogger::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 
550 void
551 MultiLogger::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 
563 void
564 MultiLogger::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 
576 void
577 MultiLogger::vtlog(LogLevel level,
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 
596 void
597 MultiLogger::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 
612 void
613 MultiLogger::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 
628 void
629 MultiLogger::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 
644 void
645 MultiLogger::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
fawkes::MultiLogger::vtlog_debug
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Definition: multi.cpp:601
fawkes::MultiLogger::log_error
virtual void log_error(const char *component, const char *format,...)
Definition: multi.cpp:241
fawkes::MultiLogger::vlog_info
virtual void vlog_info(const char *component, const char *format, va_list va)
Definition: multi.cpp:374
fawkes::MultiLogger::vlog
virtual void vlog(LogLevel level, const char *component, const char *format, va_list va)
Log message for given log level.
Definition: multi.cpp:338
fawkes::Logger::log_level
LogLevel log_level
Minimum log level.
Definition: logger.h:125
fawkes::MultiLogger::vtlog_info
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Definition: multi.cpp:617
fawkes::MultiLogger::add_logger
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:114
fawkes::MultiLogger::remove_logger
void remove_logger(Logger *logger)
Remove logger.
Definition: multi.cpp:132
fawkes::MultiLogger::tlog_warn
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Definition: multi.cpp:483
fawkes::Thread::CancelState
CancelState
Cancel state.
Definition: thread.h:63
fawkes::MultiLogger::vlog_error
virtual void vlog_error(const char *component, const char *format, va_list va)
Definition: multi.cpp:410
fawkes::MultiLogger::log_debug
virtual void log_debug(const char *component, const char *format,...)
Definition: multi.cpp:178
fawkes::MultiLogger::log_warn
virtual void log_warn(const char *component, const char *format,...)
Definition: multi.cpp:220
fawkes::MultiLogger::tlog_info
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Definition: multi.cpp:464
fawkes::MultiLogger::MultiLogger
MultiLogger()
Constructor.
Definition: multi.cpp:81
fawkes::MultiLogger::log
virtual void log(LogLevel level, const char *component, const char *format,...)
Log message of given log level.
Definition: multi.cpp:157
fawkes::MultiLogger::tlog
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:428
fawkes::Logger
Definition: logger.h:40
fawkes::MultiLogger::set_loglevel
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:143
fawkes
fawkes::MultiLogger::~MultiLogger
virtual ~MultiLogger()
Destructor.
Definition: multi.cpp:99
fawkes::MultiLogger::vtlog_error
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Definition: multi.cpp:649
fawkes::Thread::CANCEL_DISABLED
thread cannot be cancelled
Definition: thread.h:65
fawkes::MultiLogger::vlog_warn
virtual void vlog_warn(const char *component, const char *format, va_list va)
Definition: multi.cpp:392
fawkes::MultiLogger::vlog_debug
virtual void vlog_debug(const char *component, const char *format, va_list va)
Definition: multi.cpp:356
fawkes::MultiLogger::tlog_debug
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Definition: multi.cpp:446
fawkes::MultiLogger::vtlog
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:581
fawkes::Thread::set_cancel_state
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
Definition: thread.cpp:1400
fawkes::MultiLogger::tlog_error
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Definition: multi.cpp:502
fawkes::MultiLogger::vtlog_warn
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Definition: multi.cpp:633
fawkes::MultiLogger::log_info
virtual void log_info(const char *component, const char *format,...)
Definition: multi.cpp:199