Fawkes API
Fawkes Development Version
|
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 <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 <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(×tr, "%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(×tr, "%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(×tr, "%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(×tr, "%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