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 <logging/multi.h>
25 #include <logging/logger.h>
26 
27 #include <core/utils/lock_list.h>
28 #include <core/threading/thread.h>
29 
30 #include <sys/time.h>
31 #include <time.h>
32 
33 namespace fawkes {
34 
35 /// @cond INTERNALS
36 class MultiLoggerData
37 {
38  public:
39  MultiLoggerData()
40  {
41  mutex = new Mutex();
42  }
43 
44  ~MultiLoggerData()
45  {
46  delete mutex;
47  mutex = NULL;
48  }
49 
50  LockList<Logger *> loggers;
51  LockList<Logger *>::iterator logit;
52  Mutex *mutex;
53  Thread::CancelState old_state;
54 };
55 /// @endcond
56 
57 
58 /** @class MultiLogger <logging/multi.h>
59  * Log through multiple loggers.
60  * It can be hand to have the opportunity to log to multiple channels, for
61  * example log to a file and via network to a remote console. This can be
62  * done with the MultiLogger. You can add an arbitrary number of loggers
63  * to log the output to. Use the minimum number of necessary loggers though
64  * because this can cause a high burden on log users if you have too many
65  * loggers.
66  *
67  * Note that the multi logger takes over the ownership of the logger. That
68  * means that the multi logger destroys all sub-loggers when it is deleted
69  * itself. If you want to take over the loggers without destroying them you
70  * have to properly remove them before destroying the multi logger.
71  *
72  * @author Tim Niemueller
73  */
74 
75 /** Constructor.
76  * This will create the logger without any sub-loggers. Message that are
77  * logged are simply ignored.
78  */
80 {
81  data = new MultiLoggerData();
82 }
83 
84 
85 /** Constructor.
86  * This sets one sub-logger that messages are sent to.
87  * @param logger sub-logger
88  */
90 {
91  data = new MultiLoggerData();
92  data->loggers.push_back_locked(logger);
93 }
94 
95 
96 /** Destructor.
97  * This will destroy all sub-data->loggers (they are deleted).
98  */
100 {
101  data->loggers.lock();
102  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
103  delete (*data->logit);
104  }
105  data->loggers.clear();
106  data->loggers.unlock();
107  delete data;
108 }
109 
110 
111 /** Add a logger.
112  * @param logger new sub-logger to add
113  */
114 void
116 {
117  data->mutex->lock();
119  data->loggers.lock();
120  data->loggers.push_back(logger);
121  logger->set_loglevel(log_level);
122  data->loggers.sort();
123  data->loggers.unique();
124  data->loggers.unlock();
125  Thread::set_cancel_state(data->old_state);
126  data->mutex->unlock();
127 }
128 
129 
130 /** Remove logger.
131  * @param logger Sub-logger to remove
132  */
133 void
135 {
136  data->mutex->lock();
138 
139  data->loggers.remove_locked(logger);
140  Thread::set_cancel_state(data->old_state);
141  data->mutex->unlock();
142 }
143 
144 
145 void
147 {
148  data->mutex->lock();
150  log_level = level;
151 
152  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
153  (*data->logit)->set_loglevel(level);
154  }
155  Thread::set_cancel_state(data->old_state);
156  data->mutex->unlock();
157 }
158 
159 
160 void
161 MultiLogger::log(LogLevel level, const char *component, const char *format, ...)
162 {
163  struct timeval now;
164  gettimeofday(&now, NULL);
165  data->mutex->lock();
167 
168  va_list va;
169  va_start(va, format);
170  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
171  va_list vac;
172  va_copy(vac, va);
173  (*data->logit)->vtlog(level, &now, component, format, vac);
174  va_end(vac);
175  }
176  va_end(va);
177  Thread::set_cancel_state(data->old_state);
178  data->mutex->unlock();
179 }
180 
181 
182 void
183 MultiLogger::log_debug(const char *component, const char *format, ...)
184 {
185  struct timeval now;
186  gettimeofday(&now, NULL);
187  data->mutex->lock();
189 
190  va_list va;
191  va_start(va, format);
192  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
193  va_list vac;
194  va_copy(vac, va);
195  (*data->logit)->vlog_debug(component, format, vac);
196  va_end(vac);
197  }
198  va_end(va);
199  Thread::set_cancel_state(data->old_state);
200  data->mutex->unlock();
201 }
202 
203 
204 void
205 MultiLogger::log_info(const char *component, const char *format, ...)
206 {
207  struct timeval now;
208  gettimeofday(&now, NULL);
209  data->mutex->lock();
211 
212  va_list va;
213  va_start(va, format);
214  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
215  va_list vac;
216  va_copy(vac, va);
217  (*data->logit)->vlog_info(component, format, vac);
218  va_end(vac);
219  }
220  va_end(va);
221  Thread::set_cancel_state(data->old_state);
222  data->mutex->unlock();
223 }
224 
225 
226 void
227 MultiLogger::log_warn(const char *component, const char *format, ...)
228 {
229  struct timeval now;
230  gettimeofday(&now, NULL);
231  data->mutex->lock();
233 
234  va_list va;
235  va_start(va, format);
236  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
237  va_list vac;
238  va_copy(vac, va);
239  (*data->logit)->vlog_warn(component, format, vac);
240  va_end(vac);
241  }
242  va_end(va);
243  Thread::set_cancel_state(data->old_state);
244  data->mutex->unlock();
245 }
246 
247 
248 void
249 MultiLogger::log_error(const char *component, const char *format, ...)
250 {
251  struct timeval now;
252  gettimeofday(&now, NULL);
253  data->mutex->lock();
255 
256  va_list va;
257  va_start(va, format);
258  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
259  va_list vac;
260  va_copy(vac, va);
261  (*data->logit)->vlog_error(component, format, vac);
262  va_end(vac);
263  }
264  va_end(va);
265  Thread::set_cancel_state(data->old_state);
266  data->mutex->unlock();
267 }
268 
269 
270 void
271 MultiLogger::log(LogLevel level, const char *component, Exception &e)
272 {
273  struct timeval now;
274  gettimeofday(&now, NULL);
275  data->mutex->lock();
277 
278  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
279  (*data->logit)->log(level, component, e);
280  }
281  Thread::set_cancel_state(data->old_state);
282  data->mutex->unlock();
283 }
284 
285 
286 void
287 MultiLogger::log_debug(const char *component, Exception &e)
288 {
289  struct timeval now;
290  gettimeofday(&now, NULL);
291  data->mutex->lock();
293 
294  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
295  (*data->logit)->tlog_debug(&now, component, e);
296  }
297 
298  Thread::set_cancel_state(data->old_state);
299  data->mutex->unlock();
300 }
301 
302 void
303 MultiLogger::log_info(const char *component, Exception &e)
304 {
305  struct timeval now;
306  gettimeofday(&now, NULL);
307  data->mutex->lock();
309 
310  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
311  (*data->logit)->tlog_info(&now, component, e);
312  }
313  Thread::set_cancel_state(data->old_state);
314  data->mutex->unlock();
315 }
316 
317 
318 void
319 MultiLogger::log_warn(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_warn(&now, component, e);
328  }
329  Thread::set_cancel_state(data->old_state);
330  data->mutex->unlock();
331 }
332 
333 
334 void
335 MultiLogger::log_error(const char *component, Exception &e)
336 {
337  struct timeval now;
338  gettimeofday(&now, NULL);
339  data->mutex->lock();
341 
342  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
343  (*data->logit)->tlog_error(&now, component, e);
344  }
345  Thread::set_cancel_state(data->old_state);
346  data->mutex->unlock();
347 }
348 
349 
350 void
352  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)->vlog(level, component, format, vac);
363  va_end(vac);
364  }
365  Thread::set_cancel_state(data->old_state);
366  data->mutex->unlock();
367 }
368 
369 
370 void
371 MultiLogger::vlog_debug(const char *component, const char *format, va_list va)
372 {
373  struct timeval now;
374  gettimeofday(&now, NULL);
375  data->mutex->lock();
377 
378  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
379  va_list vac;
380  va_copy(vac, va);
381  (*data->logit)->vtlog_debug(&now, component, format, vac);
382  va_end(vac);
383  }
384  Thread::set_cancel_state(data->old_state);
385  data->mutex->unlock();
386 }
387 
388 
389 void
390 MultiLogger::vlog_info(const char *component, const char *format, va_list va)
391 {
392  struct timeval now;
393  gettimeofday(&now, NULL);
394  data->mutex->lock();
396 
397  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
398  va_list vac;
399  va_copy(vac, va);
400  (*data->logit)->vtlog_info(&now, component, format, vac);
401  va_end(vac);
402  }
403  Thread::set_cancel_state(data->old_state);
404  data->mutex->unlock();
405 }
406 
407 
408 void
409 MultiLogger::vlog_warn(const char *component, const char *format, va_list va)
410 {
411  struct timeval now;
412  gettimeofday(&now, NULL);
413  data->mutex->lock();
415 
416  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
417  va_list vac;
418  va_copy(vac, va);
419  (*data->logit)->vtlog_warn(&now, component, format, vac);
420  va_end(vac);
421  }
422  Thread::set_cancel_state(data->old_state);
423  data->mutex->unlock();
424 }
425 
426 
427 void
428 MultiLogger::vlog_error(const char *component, const char *format, va_list va)
429 {
430  struct timeval now;
431  gettimeofday(&now, NULL);
432  data->mutex->lock();
434 
435  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
436  va_list vac;
437  va_copy(vac, va);
438  (*data->logit)->vtlog_error(&now, component, format, vac);
439  va_end(vac);
440  }
441  Thread::set_cancel_state(data->old_state);
442  data->mutex->unlock();
443 }
444 
445 void
446 MultiLogger::tlog(LogLevel level, struct timeval *t,
447  const char *component, const char *format, ...)
448 {
449  data->mutex->lock();
451  va_list va;
452  va_start(va, format);
453  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
454  va_list vac;
455  va_copy(vac, va);
456  (*data->logit)->vtlog(level, t, component, format, vac);
457  va_end(vac);
458  }
459  va_end(va);
460  Thread::set_cancel_state(data->old_state);
461  data->mutex->unlock();
462 }
463 
464 
465 void
466 MultiLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
467 {
468  data->mutex->lock();
470  va_list va;
471  va_start(va, format);
472  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
473  va_list vac;
474  va_copy(vac, va);
475  (*data->logit)->vlog_debug(component, format, vac);
476  va_end(vac);
477  }
478  va_end(va);
479  Thread::set_cancel_state(data->old_state);
480  data->mutex->unlock();
481 }
482 
483 
484 void
485 MultiLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
486 {
487  data->mutex->lock();
489 
490  va_list va;
491  va_start(va, format);
492  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
493  va_list vac;
494  va_copy(vac, va);
495  (*data->logit)->vtlog_info(t, component, format, vac);
496  va_end(vac);
497  }
498  va_end(va);
499  Thread::set_cancel_state(data->old_state);
500  data->mutex->unlock();
501 }
502 
503 
504 void
505 MultiLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
506 {
507  data->mutex->lock();
509 
510  va_list va;
511  va_start(va, format);
512  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
513  va_list vac;
514  va_copy(vac, va);
515  (*data->logit)->vtlog_warn(t, component, format, vac);
516  va_end(vac);
517  }
518  va_end(va);
519  Thread::set_cancel_state(data->old_state);
520  data->mutex->unlock();
521 }
522 
523 
524 void
525 MultiLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
526 {
527  data->mutex->lock();
529 
530  va_list va;
531  va_start(va, format);
532  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
533  va_list vac;
534  va_copy(vac, va);
535  (*data->logit)->vtlog_error(t, component, format, vac);
536  va_end(vac);
537  }
538  va_end(va);
539  Thread::set_cancel_state(data->old_state);
540  data->mutex->unlock();
541 }
542 
543 
544 void
545 MultiLogger::tlog(LogLevel level, struct timeval *t, const char *component, Exception &e)
546 {
547  data->mutex->lock();
549 
550  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
551  (*data->logit)->tlog(level, t, component, e);
552  }
553  Thread::set_cancel_state(data->old_state);
554  data->mutex->unlock();
555 }
556 
557 
558 void
559 MultiLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
560 {
561  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
562  (*data->logit)->tlog_error(t, component, e);
563  }
564 }
565 
566 void
567 MultiLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
568 {
569  data->mutex->lock();
571 
572  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
573  (*data->logit)->tlog_error(t, component, e);
574  }
575  Thread::set_cancel_state(data->old_state);
576  data->mutex->unlock();
577 }
578 
579 
580 void
581 MultiLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
582 {
583  data->mutex->lock();
585 
586  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
587  (*data->logit)->tlog_error(t, component, e);
588  }
589  Thread::set_cancel_state(data->old_state);
590  data->mutex->unlock();
591 }
592 
593 
594 void
595 MultiLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
596 {
597  data->mutex->lock();
599 
600  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
601  (*data->logit)->tlog_error(t, component, e);
602  }
603  Thread::set_cancel_state(data->old_state);
604  data->mutex->unlock();
605 }
606 
607 
608 
609 
610 void
611 MultiLogger::vtlog(LogLevel level, struct timeval *t,
612  const char *component, const char *format, va_list va)
613 {
614  data->mutex->lock();
616 
617  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
618  va_list vac;
619  va_copy(vac, va);
620  (*data->logit)->vtlog(level, t, component, format, vac);
621  va_end(vac);
622  }
623  Thread::set_cancel_state(data->old_state);
624  data->mutex->unlock();
625 }
626 
627 
628 void
629 MultiLogger::vtlog_debug(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_debug(t, component, format, vac);
638  va_end(vac);
639  }
640  Thread::set_cancel_state(data->old_state);
641  data->mutex->unlock();
642 }
643 
644 
645 void
646 MultiLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
647 {
648  data->mutex->lock();
650 
651  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
652  va_list vac;
653  va_copy(vac, va);
654  (*data->logit)->vtlog_info(t, component, format, vac);
655  va_end(vac);
656  }
657  Thread::set_cancel_state(data->old_state);
658  data->mutex->unlock();
659 }
660 
661 
662 void
663 MultiLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
664 {
665  data->mutex->lock();
667 
668  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
669  va_list vac;
670  va_copy(vac, va);
671  (*data->logit)->vtlog_warn(t, component, format, vac);
672  va_end(vac);
673  }
674  Thread::set_cancel_state(data->old_state);
675  data->mutex->unlock();
676 }
677 
678 
679 void
680 MultiLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
681 {
682  data->mutex->lock();
684 
685  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
686  va_list vac;
687  va_copy(vac, va);
688  (*data->logit)->vtlog_error(t, component, format, vac);
689  va_end(vac);
690  }
691  Thread::set_cancel_state(data->old_state);
692  data->mutex->unlock();
693 }
694 
695 
696 } // end namespace fawkes
LogLevel
Log level.
Definition: logger.h:45
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:629
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: multi.cpp:249
Fawkes library namespace.
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: multi.cpp:525
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: multi.cpp:505
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:446
thread cannot be cancelled
Definition: thread.h:62
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:680
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
Definition: thread.cpp:1350
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: multi.cpp:485
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:646
virtual ~MultiLogger()
Destructor.
Definition: multi.cpp:99
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: multi.cpp:466
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:146
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: multi.cpp:428
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:611
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: multi.cpp:371
MultiLogger()
Constructor.
Definition: multi.cpp:79
virtual void log(LogLevel level, const char *component, const char *format,...)
Log message of given log level.
Definition: multi.cpp:161
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: multi.cpp:227
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: multi.cpp:390
void add_logger(Logger *logger)
Add a logger.
Definition: multi.cpp:115
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:663
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: multi.cpp:409
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: multi.cpp:205
virtual void vlog(LogLevel level, const char *component, const char *format, va_list va)
Log message for given log level.
Definition: multi.cpp:351
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:183
void remove_logger(Logger *logger)
Remove logger.
Definition: multi.cpp:134
CancelState
Cancel state.
Definition: thread.h:60
Interface for logging.
Definition: logger.h:34
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: logger.cpp:244