Fawkes API  Fawkes Development Version
cache.cpp
00001 
00002 /***************************************************************************
00003  *  cache.cpp - Fawkes cache logger
00004  *
00005  *  Created: Wed Feb 11 23:02:08 2009
00006  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <core/threading/mutex.h>
00025 #include <core/threading/mutex_locker.h>
00026 #include <utils/logging/cache.h>
00027 
00028 #include <cstdlib>
00029 #include <sys/time.h>
00030 #include <ctime>
00031 #include <cstdio>
00032 #include <algorithm>
00033 
00034 namespace fawkes {
00035 #if 0 /* just to make Emacs auto-indent happy */
00036 }
00037 #endif
00038 
00039 /** @class CacheLogger <utils/logging/cache.h>
00040  * Logging Cache.
00041  * The CacheLogger will cache the log messages. By default these are
00042  * 20 messages.
00043  * @author Tim Niemueller
00044  */
00045 
00046 /** Constructor.
00047  * @param num_entries number of entries in the cache, if the cache is full and a
00048  * new log message arrives the oldest message is erased.
00049  * @param log_level minimum level to log
00050  */
00051 CacheLogger::CacheLogger(unsigned int num_entries, LogLevel log_level)
00052   : Logger(log_level)
00053 {
00054   __max_num_entries = num_entries;
00055   __num_entries = 0;
00056 
00057   now_s = (struct ::tm *)malloc(sizeof(struct ::tm));
00058   mutex = new Mutex();
00059 }
00060 
00061 /** Destructor. */
00062 CacheLogger::~CacheLogger()
00063 {
00064   free(now_s);
00065   delete mutex;
00066 }
00067 
00068 std::list<CacheLogger::CacheEntry> &
00069 CacheLogger::get_messages()
00070 {
00071   return __messages;
00072 }
00073 
00074 void
00075 CacheLogger::clear()
00076 {
00077   mutex->lock();
00078   __num_entries = 0;
00079   __messages.clear();
00080   mutex->unlock();
00081 }
00082 
00083 
00084 /** Get maximum number of log entries in cache.
00085  * @return maximum number of cache entries
00086  */
00087 unsigned int
00088 CacheLogger::size() const
00089 {
00090   return __max_num_entries;
00091 }
00092 
00093 
00094 /** Set maximum number of log entries in cache.
00095  * @param new_size new size
00096  */
00097 void
00098 CacheLogger::set_size(unsigned int new_size)
00099 {
00100   MutexLocker lock(mutex);
00101   if (new_size < __num_entries) {
00102     __num_entries = new_size;
00103     __messages.resize(__num_entries);
00104   }
00105   __max_num_entries = new_size;
00106 }
00107 
00108 
00109 /** Lock cache logger, no new messages can be added.
00110  * Use with care, can cause critical delays in the whole software stack!
00111  */
00112 void
00113 CacheLogger::lock()
00114 {
00115   mutex->lock();
00116 }
00117 
00118 /** Unlock cache logger. */
00119 void
00120 CacheLogger::unlock()
00121 {
00122   mutex->unlock();
00123 }
00124 
00125 void
00126 CacheLogger::push_message(LogLevel ll, const char *component, const char *format, va_list va)
00127 {
00128   if (log_level <= ll ) {
00129     MutexLocker lock(mutex);
00130     struct timeval now;
00131     gettimeofday(&now, NULL);
00132     localtime_r(&now.tv_sec, now_s);
00133     char *timestr;
00134     if (asprintf(&timestr, "%02d:%02d:%02d.%06ld", now_s->tm_hour,
00135                  now_s->tm_min, now_s->tm_sec, now.tv_usec) == -1) {
00136       // Cannot do anything useful, drop log message
00137       return;
00138     }
00139     char *msg;
00140     if (vasprintf(&msg, format, va) == -1) {
00141       // Cannot do anything useful, drop log message
00142       free(timestr);
00143       return;
00144     }
00145 
00146     CacheEntry e;
00147     e.log_level = ll;
00148     e.component = component;
00149     e.time      = now;
00150     e.timestr   = timestr;
00151     e.message   = msg;
00152     __messages.push_front(e);
00153 
00154     free(timestr);
00155     free(msg);
00156 
00157     if (__num_entries == __max_num_entries) {
00158       __messages.pop_back();
00159     } else {
00160       ++__num_entries;
00161     }
00162   }
00163 }
00164 
00165 void
00166 CacheLogger::push_message(LogLevel ll, const char *component, Exception &e)
00167 {
00168   if (log_level <= ll ) {
00169     MutexLocker lock(mutex);
00170     struct timeval now;
00171     gettimeofday(&now, NULL);
00172     localtime_r(&now.tv_sec, now_s);
00173     char *timestr;
00174     if (asprintf(&timestr, "%02d:%02d:%02d.%06ld", now_s->tm_hour,
00175                  now_s->tm_min, now_s->tm_sec, now.tv_usec) == -1) {
00176       return;
00177     }
00178 
00179     for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
00180       CacheEntry e;
00181       e.log_level = ll;
00182       e.component = component;
00183       e.time      = now;
00184       e.timestr   = timestr;
00185       e.message   = std::string("[EXCEPTION] ") + *i;
00186       __messages.push_front(e);
00187       ++__num_entries;
00188     }
00189 
00190     free(timestr);
00191 
00192     if (__num_entries > __max_num_entries) {
00193       __num_entries = __max_num_entries;
00194       __messages.resize(__max_num_entries);
00195     }
00196   }
00197 }
00198 
00199 void
00200 CacheLogger::vlog_debug(const char *component, const char *format, va_list va)
00201 {
00202   push_message(LL_DEBUG, component, format, va);
00203 }
00204 
00205 void
00206 CacheLogger::vlog_info(const char *component, const char *format, va_list va)
00207 {
00208   push_message(LL_INFO, component, format, va);
00209 }
00210 
00211 void
00212 CacheLogger::vlog_warn(const char *component, const char *format, va_list va)
00213 {
00214   push_message(LL_WARN, component, format, va);
00215 }
00216 
00217 void
00218 CacheLogger::vlog_error(const char *component, const char *format, va_list va)
00219 {
00220   push_message(LL_ERROR, component, format, va);
00221 }
00222 
00223 void
00224 CacheLogger::log_debug(const char *component, const char *format, ...)
00225 {
00226   va_list arg;
00227   va_start(arg, format);
00228   push_message(LL_DEBUG, component, format, arg);
00229   va_end(arg);
00230 }
00231 
00232 void
00233 CacheLogger::log_info(const char *component, const char *format, ...)
00234 {
00235   va_list arg;
00236   va_start(arg, format);
00237   push_message(LL_INFO, component, format, arg);
00238   va_end(arg);
00239 }
00240 
00241 void
00242 CacheLogger::log_warn(const char *component, const char *format, ...)
00243 {
00244   va_list arg;
00245   va_start(arg, format);
00246   push_message(LL_WARN, component, format, arg);
00247   va_end(arg);
00248 }
00249 
00250 void
00251 CacheLogger::log_error(const char *component, const char *format, ...)
00252 {
00253   va_list arg;
00254   va_start(arg, format);
00255   push_message(LL_ERROR, component, format, arg);
00256   va_end(arg);
00257 }
00258 
00259 void
00260 CacheLogger::log_debug(const char *component, Exception &e)
00261 {
00262   push_message(LL_DEBUG, component, e);
00263 }
00264 
00265 void
00266 CacheLogger::log_info(const char *component, Exception &e)
00267 {
00268   push_message(LL_INFO, component, e);
00269 }
00270 
00271 void
00272 CacheLogger::log_warn(const char *component, Exception &e)
00273 {
00274   push_message(LL_WARN, component, e);
00275 }
00276 
00277 void
00278 CacheLogger::log_error(const char *component, Exception &e)
00279 {
00280   push_message(LL_ERROR, component, e);
00281 }
00282 
00283 void
00284 CacheLogger::tlog_push_message(LogLevel ll, struct timeval *t, const char *component,
00285                           const char *format, va_list va)
00286 {
00287   if (log_level <= ll ) {
00288     MutexLocker lock(mutex);
00289     localtime_r(&t->tv_sec, now_s);
00290     char *timestr;
00291     if (asprintf(&timestr, "%02d:%02d:%02d.%06ld", now_s->tm_hour,
00292                  now_s->tm_min, now_s->tm_sec, t->tv_usec) == -1) {
00293       return;
00294     }
00295     char *msg;
00296     if (vasprintf(&msg, format, va) == -1) {
00297       free(timestr);
00298       return;
00299     }
00300 
00301     CacheEntry e;
00302     e.log_level = ll;
00303     e.component = component;
00304     e.time      = *t;
00305     e.timestr   = timestr;
00306     e.message   = msg;
00307     __messages.push_front(e);
00308 
00309     free(timestr);
00310     free(msg);
00311 
00312     if (__num_entries == __max_num_entries) {
00313       __messages.pop_back();
00314     } else {
00315       ++__num_entries;
00316     }
00317     mutex->unlock();
00318   }
00319 }
00320 
00321 void
00322 CacheLogger::tlog_push_message(LogLevel ll, struct timeval *t, const char *component, Exception &e)
00323 {
00324   if (log_level <= ll ) {
00325     MutexLocker lock(mutex);
00326     localtime_r(&t->tv_sec, now_s);
00327     char *timestr;
00328     if (asprintf(&timestr, "%02d:%02d:%02d.%06ld", now_s->tm_hour,
00329                  now_s->tm_min, now_s->tm_sec, t->tv_usec) == -1) {
00330       return;
00331     }
00332     for (Exception::iterator i = e.begin(); i != e.end(); ++i) {
00333       CacheEntry e;
00334       e.log_level = ll;
00335       e.component = component;
00336       e.time      = *t;
00337       e.timestr   = timestr;
00338       e.message   = std::string("[EXCEPTION] ") + *i;
00339       __messages.push_front(e);
00340       ++__num_entries;
00341     }
00342 
00343     free(timestr);
00344 
00345     if (__num_entries > __max_num_entries) {
00346       __num_entries = __max_num_entries;
00347       __messages.resize(__max_num_entries);
00348     }
00349   }
00350 }
00351 
00352 void
00353 CacheLogger::tlog_debug(struct timeval *t, const char *component, const char *format, ...)
00354 {
00355   va_list arg;
00356   va_start(arg, format);
00357   tlog_push_message(LL_DEBUG, t, component, format, arg);
00358   va_end(arg);
00359 }
00360 
00361 void
00362 CacheLogger::tlog_info(struct timeval *t, const char *component, const char *format, ...)
00363 {
00364   va_list arg;
00365   va_start(arg, format);
00366   tlog_push_message(LL_INFO, t, component, format, arg);
00367   va_end(arg);
00368 }
00369 
00370 void
00371 CacheLogger::tlog_warn(struct timeval *t, const char *component, const char *format, ...)
00372 {
00373   va_list arg;
00374   va_start(arg, format);
00375   tlog_push_message(LL_WARN, t, component, format, arg);
00376   va_end(arg);
00377 }
00378 
00379 void
00380 CacheLogger::tlog_error(struct timeval *t, const char *component, const char *format, ...)
00381 {
00382   va_list arg;
00383   va_start(arg, format);
00384   tlog_push_message(LL_ERROR, t, component, format, arg);
00385   va_end(arg);
00386 }
00387 
00388 void
00389 CacheLogger::tlog_debug(struct timeval *t, const char *component, Exception &e)
00390 {
00391   tlog_push_message(LL_DEBUG, t, component, e);
00392 }
00393 
00394 void
00395 CacheLogger::tlog_info(struct timeval *t, const char *component, Exception &e)
00396 {
00397   tlog_push_message(LL_INFO, t, component, e);
00398 }
00399 
00400 void
00401 CacheLogger::tlog_warn(struct timeval *t, const char *component, Exception &e)
00402 {
00403   tlog_push_message(LL_WARN, t, component, e);
00404 }
00405 
00406 void
00407 CacheLogger::tlog_error(struct timeval *t, const char *component, Exception &e)
00408 {
00409   tlog_push_message(LL_ERROR, t, component, e);
00410 }
00411 
00412 void
00413 CacheLogger::vtlog_debug(struct timeval *t, const char *component, const char *format, va_list va)
00414 {
00415   tlog_push_message(LL_DEBUG, t, component, format, va);
00416 }
00417 
00418 void
00419 CacheLogger::vtlog_info(struct timeval *t, const char *component, const char *format, va_list va)
00420 {
00421   tlog_push_message(LL_INFO, t, component, format, va);
00422 }
00423 
00424 void
00425 CacheLogger::vtlog_warn(struct timeval *t, const char *component, const char *format, va_list va)
00426 {
00427   tlog_push_message(LL_WARN, t, component, format, va);
00428 }
00429 
00430 void
00431 CacheLogger::vtlog_error(struct timeval *t, const char *component, const char *format, va_list va)
00432 {
00433   tlog_push_message(LL_ERROR, t, component, format, va);
00434 }
00435 
00436 } // end namespace fawkes