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
34namespace 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 */
48CacheLogger::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
64std::list<CacheLogger::CacheEntry> &
66{
67 return messages_;
68}
69
70void
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 */
82unsigned 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 */
91void
92CacheLogger::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 */
105void
107{
108 mutex->lock();
109}
110
111/** Unlock cache logger. */
112void
114{
115 mutex->unlock();
116}
117
118void
119CacheLogger::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
163void
164CacheLogger::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
202void
203CacheLogger::vlog_debug(const char *component, const char *format, va_list va)
204{
205 push_message(LL_DEBUG, component, format, va);
206}
207
208void
209CacheLogger::vlog_info(const char *component, const char *format, va_list va)
210{
211 push_message(LL_INFO, component, format, va);
212}
213
214void
215CacheLogger::vlog_warn(const char *component, const char *format, va_list va)
216{
217 push_message(LL_WARN, component, format, va);
218}
219
220void
221CacheLogger::vlog_error(const char *component, const char *format, va_list va)
222{
223 push_message(LL_ERROR, component, format, va);
224}
225
226void
227CacheLogger::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
235void
236CacheLogger::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
244void
245CacheLogger::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
253void
254CacheLogger::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
262void
263CacheLogger::log_debug(const char *component, Exception &e)
264{
265 push_message(LL_DEBUG, component, e);
266}
267
268void
269CacheLogger::log_info(const char *component, Exception &e)
270{
271 push_message(LL_INFO, component, e);
272}
273
274void
275CacheLogger::log_warn(const char *component, Exception &e)
276{
277 push_message(LL_WARN, component, e);
278}
279
280void
281CacheLogger::log_error(const char *component, Exception &e)
282{
283 push_message(LL_ERROR, component, e);
284}
285
286void
287CacheLogger::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
332void
333CacheLogger::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
368void
369CacheLogger::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
377void
378CacheLogger::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
386void
387CacheLogger::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
395void
396CacheLogger::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
404void
405CacheLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
406{
407 tlog_push_message(LL_DEBUG, t, component, e);
408}
409
410void
411CacheLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
412{
413 tlog_push_message(LL_INFO, t, component, e);
414}
415
416void
417CacheLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
418{
419 tlog_push_message(LL_WARN, t, component, e);
420}
421
422void
423CacheLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
424{
425 tlog_push_message(LL_ERROR, t, component, e);
426}
427
428void
429CacheLogger::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
434void
435CacheLogger::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
440void
441CacheLogger::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
446void
447CacheLogger::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.