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  data->loggers.sort();
122  data->loggers.unique();
123  data->loggers.unlock();
124  Thread::set_cancel_state(data->old_state);
125  data->mutex->unlock();
126 }
127 
128 
129 /** Remove logger.
130  * @param logger Sub-logger to remove
131  */
132 void
134 {
135  data->mutex->lock();
137 
138  data->loggers.remove_locked(logger);
139  Thread::set_cancel_state(data->old_state);
140  data->mutex->unlock();
141 }
142 
143 
144 void
146 {
147  data->mutex->lock();
149 
150  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
151  (*data->logit)->set_loglevel(level);
152  }
153  Thread::set_cancel_state(data->old_state);
154  data->mutex->unlock();
155 }
156 
157 
158 void
159 MultiLogger::log(LogLevel level, const char *component, const char *format, ...)
160 {
161  struct timeval now;
162  gettimeofday(&now, NULL);
163  data->mutex->lock();
165 
166  va_list va;
167  va_start(va, format);
168  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
169  va_list vac;
170  va_copy(vac, va);
171  (*data->logit)->vtlog(level, &now, component, format, vac);
172  va_end(vac);
173  }
174  va_end(va);
175  Thread::set_cancel_state(data->old_state);
176  data->mutex->unlock();
177 }
178 
179 
180 void
181 MultiLogger::log_debug(const char *component, const char *format, ...)
182 {
183  struct timeval now;
184  gettimeofday(&now, NULL);
185  data->mutex->lock();
187 
188  va_list va;
189  va_start(va, format);
190  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
191  va_list vac;
192  va_copy(vac, va);
193  (*data->logit)->vlog_debug(component, format, vac);
194  va_end(vac);
195  }
196  va_end(va);
197  Thread::set_cancel_state(data->old_state);
198  data->mutex->unlock();
199 }
200 
201 
202 void
203 MultiLogger::log_info(const char *component, const char *format, ...)
204 {
205  struct timeval now;
206  gettimeofday(&now, NULL);
207  data->mutex->lock();
209 
210  va_list va;
211  va_start(va, format);
212  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
213  va_list vac;
214  va_copy(vac, va);
215  (*data->logit)->vlog_info(component, format, vac);
216  va_end(vac);
217  }
218  va_end(va);
219  Thread::set_cancel_state(data->old_state);
220  data->mutex->unlock();
221 }
222 
223 
224 void
225 MultiLogger::log_warn(const char *component, const char *format, ...)
226 {
227  struct timeval now;
228  gettimeofday(&now, NULL);
229  data->mutex->lock();
231 
232  va_list va;
233  va_start(va, format);
234  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
235  va_list vac;
236  va_copy(vac, va);
237  (*data->logit)->vlog_warn(component, format, vac);
238  va_end(vac);
239  }
240  va_end(va);
241  Thread::set_cancel_state(data->old_state);
242  data->mutex->unlock();
243 }
244 
245 
246 void
247 MultiLogger::log_error(const char *component, const char *format, ...)
248 {
249  struct timeval now;
250  gettimeofday(&now, NULL);
251  data->mutex->lock();
253 
254  va_list va;
255  va_start(va, format);
256  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
257  va_list vac;
258  va_copy(vac, va);
259  (*data->logit)->vlog_error(component, format, vac);
260  va_end(vac);
261  }
262  va_end(va);
263  Thread::set_cancel_state(data->old_state);
264  data->mutex->unlock();
265 }
266 
267 
268 void
269 MultiLogger::log(LogLevel level, const char *component, Exception &e)
270 {
271  struct timeval now;
272  gettimeofday(&now, NULL);
273  data->mutex->lock();
275 
276  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
277  (*data->logit)->log(level, component, e);
278  }
279  Thread::set_cancel_state(data->old_state);
280  data->mutex->unlock();
281 }
282 
283 
284 void
285 MultiLogger::log_debug(const char *component, Exception &e)
286 {
287  struct timeval now;
288  gettimeofday(&now, NULL);
289  data->mutex->lock();
291 
292  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
293  (*data->logit)->tlog_debug(&now, component, e);
294  }
295 
296  Thread::set_cancel_state(data->old_state);
297  data->mutex->unlock();
298 }
299 
300 void
301 MultiLogger::log_info(const char *component, Exception &e)
302 {
303  struct timeval now;
304  gettimeofday(&now, NULL);
305  data->mutex->lock();
307 
308  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
309  (*data->logit)->tlog_info(&now, component, e);
310  }
311  Thread::set_cancel_state(data->old_state);
312  data->mutex->unlock();
313 }
314 
315 
316 void
317 MultiLogger::log_warn(const char *component, Exception &e)
318 {
319  struct timeval now;
320  gettimeofday(&now, NULL);
321  data->mutex->lock();
323 
324  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
325  (*data->logit)->tlog_warn(&now, component, e);
326  }
327  Thread::set_cancel_state(data->old_state);
328  data->mutex->unlock();
329 }
330 
331 
332 void
333 MultiLogger::log_error(const char *component, Exception &e)
334 {
335  struct timeval now;
336  gettimeofday(&now, NULL);
337  data->mutex->lock();
339 
340  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
341  (*data->logit)->tlog_error(&now, component, e);
342  }
343  Thread::set_cancel_state(data->old_state);
344  data->mutex->unlock();
345 }
346 
347 
348 void
350  const char *component, const char *format, va_list va)
351 {
352  struct timeval now;
353  gettimeofday(&now, NULL);
354  data->mutex->lock();
356 
357  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
358  va_list vac;
359  va_copy(vac, va);
360  (*data->logit)->vlog(level, component, format, vac);
361  va_end(vac);
362  }
363  Thread::set_cancel_state(data->old_state);
364  data->mutex->unlock();
365 }
366 
367 
368 void
369 MultiLogger::vlog_debug(const char *component, const char *format, va_list va)
370 {
371  struct timeval now;
372  gettimeofday(&now, NULL);
373  data->mutex->lock();
375 
376  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
377  va_list vac;
378  va_copy(vac, va);
379  (*data->logit)->vtlog_debug(&now, component, format, vac);
380  va_end(vac);
381  }
382  Thread::set_cancel_state(data->old_state);
383  data->mutex->unlock();
384 }
385 
386 
387 void
388 MultiLogger::vlog_info(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_info(&now, component, format, vac);
399  va_end(vac);
400  }
401  Thread::set_cancel_state(data->old_state);
402  data->mutex->unlock();
403 }
404 
405 
406 void
407 MultiLogger::vlog_warn(const char *component, const char *format, va_list va)
408 {
409  struct timeval now;
410  gettimeofday(&now, NULL);
411  data->mutex->lock();
413 
414  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
415  va_list vac;
416  va_copy(vac, va);
417  (*data->logit)->vtlog_warn(&now, component, format, vac);
418  va_end(vac);
419  }
420  Thread::set_cancel_state(data->old_state);
421  data->mutex->unlock();
422 }
423 
424 
425 void
426 MultiLogger::vlog_error(const char *component, const char *format, va_list va)
427 {
428  struct timeval now;
429  gettimeofday(&now, NULL);
430  data->mutex->lock();
432 
433  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
434  va_list vac;
435  va_copy(vac, va);
436  (*data->logit)->vtlog_error(&now, component, format, vac);
437  va_end(vac);
438  }
439  Thread::set_cancel_state(data->old_state);
440  data->mutex->unlock();
441 }
442 
443 void
444 MultiLogger::tlog(LogLevel level, struct timeval *t,
445  const char *component, const char *format, ...)
446 {
447  data->mutex->lock();
449  va_list va;
450  va_start(va, format);
451  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
452  va_list vac;
453  va_copy(vac, va);
454  (*data->logit)->vtlog(level, t, component, format, vac);
455  va_end(vac);
456  }
457  va_end(va);
458  Thread::set_cancel_state(data->old_state);
459  data->mutex->unlock();
460 }
461 
462 
463 void
464 MultiLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
465 {
466  data->mutex->lock();
468  va_list va;
469  va_start(va, format);
470  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
471  va_list vac;
472  va_copy(vac, va);
473  (*data->logit)->vlog_debug(component, format, vac);
474  va_end(vac);
475  }
476  va_end(va);
477  Thread::set_cancel_state(data->old_state);
478  data->mutex->unlock();
479 }
480 
481 
482 void
483 MultiLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
484 {
485  data->mutex->lock();
487 
488  va_list va;
489  va_start(va, format);
490  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
491  va_list vac;
492  va_copy(vac, va);
493  (*data->logit)->vtlog_info(t, component, format, vac);
494  va_end(vac);
495  }
496  va_end(va);
497  Thread::set_cancel_state(data->old_state);
498  data->mutex->unlock();
499 }
500 
501 
502 void
503 MultiLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
504 {
505  data->mutex->lock();
507 
508  va_list va;
509  va_start(va, format);
510  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
511  va_list vac;
512  va_copy(vac, va);
513  (*data->logit)->vtlog_warn(t, component, format, vac);
514  va_end(vac);
515  }
516  va_end(va);
517  Thread::set_cancel_state(data->old_state);
518  data->mutex->unlock();
519 }
520 
521 
522 void
523 MultiLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
524 {
525  data->mutex->lock();
527 
528  va_list va;
529  va_start(va, format);
530  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
531  va_list vac;
532  va_copy(vac, va);
533  (*data->logit)->vtlog_error(t, component, format, vac);
534  va_end(vac);
535  }
536  va_end(va);
537  Thread::set_cancel_state(data->old_state);
538  data->mutex->unlock();
539 }
540 
541 
542 void
543 MultiLogger::tlog(LogLevel level, struct timeval *t, const char *component, Exception &e)
544 {
545  data->mutex->lock();
547 
548  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
549  (*data->logit)->tlog(level, t, component, e);
550  }
551  Thread::set_cancel_state(data->old_state);
552  data->mutex->unlock();
553 }
554 
555 
556 void
557 MultiLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
558 {
559  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
560  (*data->logit)->tlog_error(t, component, e);
561  }
562 }
563 
564 void
565 MultiLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
566 {
567  data->mutex->lock();
569 
570  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
571  (*data->logit)->tlog_error(t, component, e);
572  }
573  Thread::set_cancel_state(data->old_state);
574  data->mutex->unlock();
575 }
576 
577 
578 void
579 MultiLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
580 {
581  data->mutex->lock();
583 
584  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
585  (*data->logit)->tlog_error(t, component, e);
586  }
587  Thread::set_cancel_state(data->old_state);
588  data->mutex->unlock();
589 }
590 
591 
592 void
593 MultiLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
594 {
595  data->mutex->lock();
597 
598  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
599  (*data->logit)->tlog_error(t, component, e);
600  }
601  Thread::set_cancel_state(data->old_state);
602  data->mutex->unlock();
603 }
604 
605 
606 
607 
608 void
609 MultiLogger::vtlog(LogLevel level, struct timeval *t,
610  const char *component, const char *format, va_list va)
611 {
612  data->mutex->lock();
614 
615  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
616  va_list vac;
617  va_copy(vac, va);
618  (*data->logit)->vtlog(level, t, component, format, vac);
619  va_end(vac);
620  }
621  Thread::set_cancel_state(data->old_state);
622  data->mutex->unlock();
623 }
624 
625 
626 void
627 MultiLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
628 {
629  data->mutex->lock();
631 
632  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
633  va_list vac;
634  va_copy(vac, va);
635  (*data->logit)->vtlog_debug(t, component, format, vac);
636  va_end(vac);
637  }
638  Thread::set_cancel_state(data->old_state);
639  data->mutex->unlock();
640 }
641 
642 
643 void
644 MultiLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
645 {
646  data->mutex->lock();
648 
649  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
650  va_list vac;
651  va_copy(vac, va);
652  (*data->logit)->vtlog_info(t, component, format, vac);
653  va_end(vac);
654  }
655  Thread::set_cancel_state(data->old_state);
656  data->mutex->unlock();
657 }
658 
659 
660 void
661 MultiLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
662 {
663  data->mutex->lock();
665 
666  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
667  va_list vac;
668  va_copy(vac, va);
669  (*data->logit)->vtlog_warn(t, component, format, vac);
670  va_end(vac);
671  }
672  Thread::set_cancel_state(data->old_state);
673  data->mutex->unlock();
674 }
675 
676 
677 void
678 MultiLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
679 {
680  data->mutex->lock();
682 
683  for (data->logit = data->loggers.begin(); data->logit != data->loggers.end(); ++data->logit) {
684  va_list vac;
685  va_copy(vac, va);
686  (*data->logit)->vtlog_error(t, component, format, vac);
687  va_end(vac);
688  }
689  Thread::set_cancel_state(data->old_state);
690  data->mutex->unlock();
691 }
692 
693 
694 } // 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:627
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: multi.cpp:247
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:523
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: multi.cpp:503
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:444
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:678
static void set_cancel_state(CancelState new_state, CancelState *old_state=0)
Set the cancel state of the current thread.
Definition: thread.cpp:1327
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: multi.cpp:483
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:644
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:464
virtual void set_loglevel(LogLevel level)
Sets the log level.
Definition: multi.cpp:145
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:426
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:609
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: multi.cpp:369
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:159
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: multi.cpp:225
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: multi.cpp:388
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:661
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: multi.cpp:407
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: multi.cpp:203
virtual void vlog(LogLevel level, const char *component, const char *format, va_list va)
Log message for given log level.
Definition: multi.cpp:349
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:181
void remove_logger(Logger *logger)
Remove logger.
Definition: multi.cpp:133
CancelState
Cancel state.
Definition: thread.h:60
Interface for logging.
Definition: logger.h:34