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