Fawkes API  Fawkes Development Version
cache.cpp
1 
2 /***************************************************************************
3  * cache.cpp - Fawkes cache logger
4  *
5  * Created: Wed Feb 11 23:02:08 2009
6  * Copyright 2006-2009 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/mutex.h>
25 #include <core/threading/mutex_locker.h>
26 #include <logging/cache.h>
27 #include <sys/time.h>
28 
29 #include <algorithm>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <ctime>
33 
34 namespace fawkes {
35 
36 /** @class CacheLogger <logging/cache.h>
37  * Logging Cache.
38  * The CacheLogger will cache the log messages. By default these are
39  * 20 messages.
40  * @author Tim Niemueller
41  */
42 
43 /** Constructor.
44  * @param num_entries number of entries in the cache, if the cache is full and a
45  * new log message arrives the oldest message is erased.
46  * @param log_level minimum level to log
47  */
48 CacheLogger::CacheLogger(unsigned int num_entries, LogLevel log_level) : Logger(log_level)
49 {
50  max_num_entries_ = num_entries;
51  num_entries_ = 0;
52 
53  now_s = (struct ::tm *)malloc(sizeof(struct ::tm));
54  mutex = new Mutex();
55 }
56 
57 /** Destructor. */
59 {
60  free(now_s);
61  delete mutex;
62 }
63 
64 std::list<CacheLogger::CacheEntry> &
66 {
67  return messages_;
68 }
69 
70 void
72 {
73  mutex->lock();
74  num_entries_ = 0;
75  messages_.clear();
76  mutex->unlock();
77 }
78 
79 /** Get maximum number of log entries in cache.
80  * @return maximum number of cache entries
81  */
82 unsigned int
84 {
85  return max_num_entries_;
86 }
87 
88 /** Set maximum number of log entries in cache.
89  * @param new_size new size
90  */
91 void
92 CacheLogger::set_size(unsigned int new_size)
93 {
94  MutexLocker lock(mutex);
95  if (new_size < num_entries_) {
96  num_entries_ = new_size;
97  messages_.resize(num_entries_);
98  }
99  max_num_entries_ = new_size;
100 }
101 
102 /** Lock cache logger, no new messages can be added.
103  * Use with care, can cause critical delays in the whole software stack!
104  */
105 void
107 {
108  mutex->lock();
109 }
110 
111 /** Unlock cache logger. */
112 void
114 {
115  mutex->unlock();
116 }
117 
118 void
119 CacheLogger::push_message(LogLevel ll, const char *component, const char *format, va_list va)
120 {
121  if (log_level <= ll) {
122  MutexLocker lock(mutex);
123  struct timeval now;
124  gettimeofday(&now, NULL);
125  localtime_r(&now.tv_sec, now_s);
126  char *timestr;
127  if (asprintf(&timestr,
128  "%02d:%02d:%02d.%06ld",
129  now_s->tm_hour,
130  now_s->tm_min,
131  now_s->tm_sec,
132  now.tv_usec)
133  == -1) {
134  // Cannot do anything useful, drop log message
135  return;
136  }
137  char *msg;
138  if (vasprintf(&msg, format, va) == -1) {
139  // Cannot do anything useful, drop log message
140  free(timestr);
141  return;
142  }
143 
144  CacheEntry e;
145  e.log_level = ll;
146  e.component = component;
147  e.time = now;
148  e.timestr = timestr;
149  e.message = msg;
150  messages_.push_front(e);
151 
152  free(timestr);
153  free(msg);
154 
155  if (num_entries_ == max_num_entries_) {
156  messages_.pop_back();
157  } else {
158  ++num_entries_;
159  }
160  }
161 }
162 
163 void
164 CacheLogger::push_message(LogLevel ll, const char *component, Exception &e)
165 {
166  if (log_level <= ll) {
167  MutexLocker lock(mutex);
168  struct timeval now;
169  gettimeofday(&now, NULL);
170  localtime_r(&now.tv_sec, now_s);
171  char *timestr;
172  if (asprintf(&timestr,
173  "%02d:%02d:%02d.%06ld",
174  now_s->tm_hour,
175  now_s->tm_min,
176  now_s->tm_sec,
177  now.tv_usec)
178  == -1) {
179  return;
180  }
181 
182  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
183  CacheEntry ce;
184  ce.log_level = ll;
185  ce.component = component;
186  ce.time = now;
187  ce.timestr = timestr;
188  ce.message = std::string("[EXCEPTION] ") + *i;
189  messages_.push_front(ce);
190  ++num_entries_;
191  }
192 
193  free(timestr);
194 
195  if (num_entries_ > max_num_entries_) {
196  num_entries_ = max_num_entries_;
197  messages_.resize(max_num_entries_);
198  }
199  }
200 }
201 
202 void
203 CacheLogger::vlog_debug(const char *component, const char *format, va_list va)
204 {
205  push_message(LL_DEBUG, component, format, va);
206 }
207 
208 void
209 CacheLogger::vlog_info(const char *component, const char *format, va_list va)
210 {
211  push_message(LL_INFO, component, format, va);
212 }
213 
214 void
215 CacheLogger::vlog_warn(const char *component, const char *format, va_list va)
216 {
217  push_message(LL_WARN, component, format, va);
218 }
219 
220 void
221 CacheLogger::vlog_error(const char *component, const char *format, va_list va)
222 {
223  push_message(LL_ERROR, component, format, va);
224 }
225 
226 void
227 CacheLogger::log_debug(const char *component, const char *format, ...)
228 {
229  va_list arg;
230  va_start(arg, format);
231  push_message(LL_DEBUG, component, format, arg);
232  va_end(arg);
233 }
234 
235 void
236 CacheLogger::log_info(const char *component, const char *format, ...)
237 {
238  va_list arg;
239  va_start(arg, format);
240  push_message(LL_INFO, component, format, arg);
241  va_end(arg);
242 }
243 
244 void
245 CacheLogger::log_warn(const char *component, const char *format, ...)
246 {
247  va_list arg;
248  va_start(arg, format);
249  push_message(LL_WARN, component, format, arg);
250  va_end(arg);
251 }
252 
253 void
254 CacheLogger::log_error(const char *component, const char *format, ...)
255 {
256  va_list arg;
257  va_start(arg, format);
258  push_message(LL_ERROR, component, format, arg);
259  va_end(arg);
260 }
261 
262 void
263 CacheLogger::log_debug(const char *component, Exception &e)
264 {
265  push_message(LL_DEBUG, component, e);
266 }
267 
268 void
269 CacheLogger::log_info(const char *component, Exception &e)
270 {
271  push_message(LL_INFO, component, e);
272 }
273 
274 void
275 CacheLogger::log_warn(const char *component, Exception &e)
276 {
277  push_message(LL_WARN, component, e);
278 }
279 
280 void
281 CacheLogger::log_error(const char *component, Exception &e)
282 {
283  push_message(LL_ERROR, component, e);
284 }
285 
286 void
287 CacheLogger::tlog_push_message(LogLevel ll,
288  struct timeval *t,
289  const char * component,
290  const char * format,
291  va_list va)
292 {
293  if (log_level <= ll) {
294  MutexLocker lock(mutex);
295  localtime_r(&t->tv_sec, now_s);
296  char *timestr;
297  if (asprintf(&timestr,
298  "%02d:%02d:%02d.%06ld",
299  now_s->tm_hour,
300  now_s->tm_min,
301  now_s->tm_sec,
302  t->tv_usec)
303  == -1) {
304  return;
305  }
306  char *msg;
307  if (vasprintf(&msg, format, va) == -1) {
308  free(timestr);
309  return;
310  }
311 
312  CacheEntry e;
313  e.log_level = ll;
314  e.component = component;
315  e.time = *t;
316  e.timestr = timestr;
317  e.message = msg;
318  messages_.push_front(e);
319 
320  free(timestr);
321  free(msg);
322 
323  if (num_entries_ == max_num_entries_) {
324  messages_.pop_back();
325  } else {
326  ++num_entries_;
327  }
328  mutex->unlock();
329  }
330 }
331 
332 void
333 CacheLogger::tlog_push_message(LogLevel ll, struct timeval *t, const char *component, Exception &e)
334 {
335  if (log_level <= ll) {
336  MutexLocker lock(mutex);
337  localtime_r(&t->tv_sec, now_s);
338  char *timestr;
339  if (asprintf(&timestr,
340  "%02d:%02d:%02d.%06ld",
341  now_s->tm_hour,
342  now_s->tm_min,
343  now_s->tm_sec,
344  t->tv_usec)
345  == -1) {
346  return;
347  }
348  for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
349  CacheEntry ce;
350  ce.log_level = ll;
351  ce.component = component;
352  ce.time = *t;
353  ce.timestr = timestr;
354  ce.message = std::string("[EXCEPTION] ") + *i;
355  messages_.push_front(ce);
356  ++num_entries_;
357  }
358 
359  free(timestr);
360 
361  if (num_entries_ > max_num_entries_) {
362  num_entries_ = max_num_entries_;
363  messages_.resize(max_num_entries_);
364  }
365  }
366 }
367 
368 void
369 CacheLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
370 {
371  va_list arg;
372  va_start(arg, format);
373  tlog_push_message(LL_DEBUG, t, component, format, arg);
374  va_end(arg);
375 }
376 
377 void
378 CacheLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
379 {
380  va_list arg;
381  va_start(arg, format);
382  tlog_push_message(LL_INFO, t, component, format, arg);
383  va_end(arg);
384 }
385 
386 void
387 CacheLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
388 {
389  va_list arg;
390  va_start(arg, format);
391  tlog_push_message(LL_WARN, t, component, format, arg);
392  va_end(arg);
393 }
394 
395 void
396 CacheLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
397 {
398  va_list arg;
399  va_start(arg, format);
400  tlog_push_message(LL_ERROR, t, component, format, arg);
401  va_end(arg);
402 }
403 
404 void
405 CacheLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
406 {
407  tlog_push_message(LL_DEBUG, t, component, e);
408 }
409 
410 void
411 CacheLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
412 {
413  tlog_push_message(LL_INFO, t, component, e);
414 }
415 
416 void
417 CacheLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
418 {
419  tlog_push_message(LL_WARN, t, component, e);
420 }
421 
422 void
423 CacheLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
424 {
425  tlog_push_message(LL_ERROR, t, component, e);
426 }
427 
428 void
429 CacheLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
430 {
431  tlog_push_message(LL_DEBUG, t, component, format, va);
432 }
433 
434 void
435 CacheLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
436 {
437  tlog_push_message(LL_INFO, t, component, format, va);
438 }
439 
440 void
441 CacheLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
442 {
443  tlog_push_message(LL_WARN, t, component, format, va);
444 }
445 
446 void
447 CacheLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
448 {
449  tlog_push_message(LL_ERROR, t, component, format, va);
450 }
451 
452 } // end namespace fawkes
virtual void vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
Log error message for specific time.
Definition: cache.cpp:447
virtual void tlog_debug(struct timeval *t, const char *component, const char *format,...)
Log debug message for specific time.
Definition: cache.cpp:369
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: cache.cpp:227
virtual void vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
Log debug message for specific time.
Definition: cache.cpp:429
virtual void tlog_warn(struct timeval *t, const char *component, const char *format,...)
Log warning message for specific time.
Definition: cache.cpp:387
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: cache.cpp:236
std::list< CacheEntry > & get_messages()
Get messages.
Definition: cache.cpp:65
void clear()
Clear messages.
Definition: cache.cpp:71
unsigned int size() const
Get maximum number of log entries in cache.
Definition: cache.cpp:83
virtual void vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
Log informational message for specific time.
Definition: cache.cpp:435
virtual void vlog_error(const char *component, const char *format, va_list va)
Log error message.
Definition: cache.cpp:221
void lock()
Lock cache logger, no new messages can be added.
Definition: cache.cpp:106
virtual void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: cache.cpp:245
void set_size(unsigned int new_size)
Set maximum number of log entries in cache.
Definition: cache.cpp:92
virtual void vlog_debug(const char *component, const char *format, va_list va)
Log debug message.
Definition: cache.cpp:203
void unlock()
Unlock cache logger.
Definition: cache.cpp:113
virtual void tlog_info(struct timeval *t, const char *component, const char *format,...)
Log informational message for specific time.
Definition: cache.cpp:378
CacheLogger(unsigned int num_entries=20, LogLevel log_level=LL_DEBUG)
Constructor.
Definition: cache.cpp:48
virtual void vlog_warn(const char *component, const char *format, va_list va)
Log warning message.
Definition: cache.cpp:215
virtual ~CacheLogger()
Destructor.
Definition: cache.cpp:58
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: cache.cpp:254
virtual void vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
Log warning message for specific time.
Definition: cache.cpp:441
virtual void vlog_info(const char *component, const char *format, va_list va)
Log informational message.
Definition: cache.cpp:209
virtual void tlog_error(struct timeval *t, const char *component, const char *format,...)
Log error message for specific time.
Definition: cache.cpp:396
Base class for exceptions in Fawkes.
Definition: exception.h:36
Interface for logging.
Definition: logger.h:42
LogLevel
Log level.
Definition: logger.h:51
@ LL_INFO
informational output about normal procedures
Definition: logger.h:53
@ LL_WARN
warning, should be investigated but software still functions, an example is that something was reques...
Definition: logger.h:54
@ LL_ERROR
error, may be recoverable (software still running) or not (software has to terminate).
Definition: logger.h:57
@ LL_DEBUG
debug output, relevant only when tracking down problems
Definition: logger.h:52
LogLevel log_level
Minimum log level.
Definition: logger.h:126
Mutex locking helper.
Definition: mutex_locker.h:34
Mutex mutual exclusion lock.
Definition: mutex.h:33
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
Fawkes library namespace.