00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _LOG_H
00034 #define _LOG_H
00035
00036 #include <stdio.h>
00037 #include <list>
00038 #include <vector>
00039 #include <cstdarg>
00040 #include <iostream>
00041 #include <sstream>
00042 #include <fstream>
00043 #include <pthread.h>
00044
00045 #include "mhash_map.h"
00046 #include "Serializable.h"
00047 #include "LogSelector.h"
00048 #include "BinaryLogObject.h"
00049
00050
00051
00052
00053
00124 struct hash_string;
00125
00126 typedef uint32_t log_id_t;
00127 typedef uint32_t log_level_t;
00128
00165 class Log {
00166 public:
00167 static class LogFlushManipulator {} end, endl;
00168
00173 class MaceTraceStream {
00174 private:
00175 friend class Log;
00176 std::ostringstream* stream;
00177 log_id_t id;
00178
00179 public:
00180 MaceTraceStream& operator<<(const LogFlushManipulator& l) {
00181 if(stream != NULL) {
00182 Log::flush(*this);
00183 }
00184 return *this;
00185 }
00186
00187 template<typename T>
00188 MaceTraceStream& operator<<(const T* r) {
00189 if(stream != NULL) {
00190 std::string tmp;
00191 mace::serialize(tmp, r);
00192 (*stream) << tmp;
00193 }
00194 return *this;
00195 }
00196
00197 template<typename T>
00198 MaceTraceStream& operator<<(const T& r) {
00199 if(stream != NULL) {
00200 std::string tmp;
00201 mace::serialize(tmp, &r);
00202 (*stream) << tmp;
00203 }
00204 return *this;
00205 }
00206
00207 MaceTraceStream(log_id_t lid = NULL_ID) :
00208 stream(lid==NULL_ID ? NULL : new std::ostringstream()), id(lid) {}
00209 bool isNoop() const { return stream == NULL; }
00210 };
00211
00212 class MaceOutputStream {
00213 private:
00214 friend class Log;
00218 std::ostringstream* stream;
00222 log_id_t id;
00223 public:
00225 MaceOutputStream& operator<<(const LogFlushManipulator& l) {
00226 if(stream != NULL) {
00227 Log::flush(*this);
00228 }
00229 return *this;
00230 }
00232 MaceOutputStream& operator<<(std::ostream::__ios_type& (*__pf)(std::ostream::__ios_type&)) {
00233 if(stream != NULL) {
00234 (*stream) << __pf;
00235 }
00236 return *this;
00237 }
00239 MaceOutputStream& operator<<(std::ostream::ios_base& (*__pf)(std::ostream::ios_base&)) {
00240 if(stream != NULL) {
00241 (*stream) << __pf;
00242 }
00243 return *this;
00244 }
00246 MaceOutputStream& operator<<(std::ostream::__ostream_type& (*__pf)(std::ostream::__ostream_type&)) {
00247 if(stream != NULL) {
00248 (*stream) << __pf;
00249 }
00250 return *this;
00251 }
00253 template<typename T>
00254 MaceOutputStream& operator<<(const T* r) {
00255 if(stream != NULL) {
00256 (*stream) << r;
00257 }
00258 return *this;
00259 }
00261 template<typename T>
00262 MaceOutputStream& operator<<(const T& r) {
00263 if(stream != NULL) {
00264 (*stream) << r;
00265 }
00266 return *this;
00267 }
00269 template<typename T>
00270 void printItem(const T* pitem) {
00271 if(stream != NULL) {
00272 mace::printItem(*stream, pitem);
00273 }
00274 }
00276 template<typename T>
00277 void printXml(const T* pitem) {
00278 if(stream != NULL) {
00279 mace::printXml(*stream, pitem, *pitem);
00280 }
00281 }
00282 MaceOutputStream(log_id_t lid = NULL_ID) :
00283 stream(lid==NULL_ID ? NULL : new std::ostringstream()), id(lid) {}
00291 bool isNoop() const { return stream == NULL; }
00292 };
00293
00295 class NullOutputType {
00296 public:
00297 template<typename T>
00298 const NullOutputType& operator<<(const T* r) const { return *this; }
00299 template<typename T>
00300 const NullOutputType& operator<<(const T& r) const { return *this; }
00301
00302 const NullOutputType& operator<<(std::ostream::__ios_type& (*__pf)(std::ostream::__ios_type&)) const {
00303 return *this;
00304 }
00305 const NullOutputType& operator<<(std::ostream::ios_base& (*__pf)(std::ostream::ios_base&)) const {
00306 return *this;
00307 }
00308 const NullOutputType& operator<<(std::ostream::__ostream_type& (*__pf)(std::ostream::__ostream_type&)) const {
00309 return *this;
00310 }
00311 };
00312
00313 typedef mace::hash_map<log_id_t, MaceOutputStream*, mace::SoftState> StreamMap;
00314 typedef mace::hash_map<log_id_t, MaceTraceStream*, mace::SoftState> TraceStreamMap;
00315
00317
00320 class ThreadSpecific {
00321 friend class Log;
00322
00323 public:
00324 ThreadSpecific();
00325 virtual ~ThreadSpecific();
00326 static ThreadSpecific* init();
00327 static unsigned int getVtid();
00328 static StreamMap& getStreams();
00329 static TraceStreamMap& getTraceStreams();
00330
00331 private:
00332 static void initKey();
00333
00334 protected:
00335 unsigned int vtid;
00336 StreamMap streams;
00337 TraceStreamMap traceStreams;
00338
00339 private:
00340 static pthread_key_t pkey;
00341 static pthread_once_t keyOnce;
00342 static unsigned int count;
00343 };
00344
00345
00346 public:
00356 static log_id_t getId(const std::string& selector);
00357 static const std::string& getSelector(log_id_t id);
00372 static void add(const std::string& selector,
00373 FILE* fp = stdout,
00374 LogSelectorTimestamp lt = LOG_TIMESTAMP_DISABLED,
00375 LogSelectorName ln = LOG_NAME_DISABLED,
00376 LogSelectorThreadId ltid = LOG_THREADID_DISABLED,
00377 LogSelectorOutput lso = LOG_FPRINTF);
00391 static void autoAddAll(FILE* fp = stdout,
00392 LogSelectorTimestamp lt = LOG_TIMESTAMP_EPOCH,
00393 LogSelectorName ln = LOG_NAME_ENABLED,
00394 LogSelectorThreadId ltid = LOG_THREADID_ENABLED,
00395 LogSelectorOutput lso = LOG_FPRINTF);
00410 static void autoAdd(const std::string& subselector,
00411 FILE* fp = stdout,
00412 LogSelectorTimestamp lt = LOG_TIMESTAMP_EPOCH,
00413 LogSelectorName ln = LOG_NAME_ENABLED,
00414 LogSelectorThreadId ltid = LOG_THREADID_ENABLED,
00415 LogSelectorOutput lso = LOG_FPRINTF);
00417 static void remove(const std::string& selector, FILE* fp = stdout);
00419 static void removeAll(const std::string& selector);
00421 static FILE* openLogFile(const std::string& path, const char* mode = "a");
00423 static void logToFile(const std::string& path, const std::string& selector,
00424 const char* mode = "w",
00425 LogSelectorTimestamp sts = LOG_TIMESTAMP_EPOCH,
00426 LogSelectorName sn = LOG_NAME_DISABLED,
00427 LogSelectorThreadId stid = LOG_THREADID_DISABLED);
00428 static void closeLogFiles();
00429 static void enableLogging();
00430 static void disableLogging();
00431 static void disableDefaultError() { errorSelected = false; }
00432 static void disableDefaultWarning() { warningSelected = false; }
00433 static void perror(const std::string& s);
00434 static void sslerror(const std::string& s);
00435 static MaceOutputStream& err() { return log("ERROR"); }
00436 static MaceOutputStream& warn() { return log("WARNING"); }
00437 static MaceOutputStream& info() { return log("INFO"); }
00438 static MaceOutputStream& log(log_id_t id, log_level_t level = DEFAULT_LEVEL);
00439
00440 static void binaryLog(log_id_t id, const std::string& log_type,
00441 const std::string& serializedObj,
00442 log_level_t level = DEFAULT_LEVEL);
00444 static void binaryLog(log_id_t id, const mace::BinaryLogObject& object, log_level_t level = DEFAULT_LEVEL);
00449 static MaceOutputStream& log(const std::string& selector,
00450 log_level_t level = DEFAULT_LEVEL);
00452 static void log(log_id_t id, const std::string& message) {
00453 log(id, DEFAULT_LEVEL, message);
00454 }
00456 static void log(log_id_t id, log_level_t level, const std::string& message);
00458 static void log(const std::string& selector, const std::string& message) {
00459 log(selector, DEFAULT_LEVEL, message);
00460 }
00462 static void log(const std::string& selector, log_level_t level,
00463 const std::string& message);
00464
00465 static void log(log_id_t id, const char* message) {
00466 log(id, DEFAULT_LEVEL, message);
00467 }
00469
00470 static void log(log_id_t id, log_level_t level, const char* message);
00472 static void log(const std::string& selector, const char* message) {
00473 log(selector, DEFAULT_LEVEL, message);
00474 }
00476 static void log(const std::string& selector, log_level_t level, const char* message);
00478 static void logf(log_id_t id, const char* format ...) __attribute__((format(printf,2,3)));
00480 static void logf(log_id_t id, log_level_t level, const char* format ...) __attribute__((format(printf,3,4)));
00482 static void logf(const std::string& selector, const char* format ...) __attribute__((format(printf,2,3)));
00484 static void logf(const std::string& selector, log_level_t level, const char* format ...) __attribute__((format(printf,3,4)));
00485 static std::string toHex(const std::string& s);
00486 static void flush(MaceOutputStream& s);
00487 static log_level_t getLevel() { return logLevel; }
00488 static void setLevel(log_level_t l = DEFAULT_LEVEL) { logLevel = l; }
00489
00490 static void configure();
00491
00492 static void nologf() {}
00493 static const NullOutputType& nolog() { return nullOutputVar; }
00494
00495 static log_id_t getTraceId(const std::string& selector);
00496 static MaceTraceStream& trace(log_id_t id);
00497 static void flush(MaceTraceStream& s);
00498 static void traceNewThread(const mace::string& fname);
00499 static std::istream& replay(log_id_t id);
00500
00501 public:
00502 static const log_level_t DEFAULT_LEVEL;
00503 static const log_level_t MAX_LEVEL;
00504 static const log_id_t NULL_ID;
00505
00506 private:
00507 typedef std::list<LogSelector*> SelectorList;
00508
00509 protected:
00510 static bool isSelected(const std::string& selector);
00511 static void remove(SelectorList* l, FILE* f);
00512 static void addl(const std::string& selector,
00513 FILE* fp,
00514 LogSelectorTimestamp,
00515 LogSelectorName,
00516 LogSelectorThreadId,
00517 LogSelectorOutput);
00518 static void scheduleThread(unsigned int id, const mace::string& description);
00519
00521 static void writeBinaryLog(log_id_t id, const LogSelector* sel, const std::string& log_type, const std::string& serializedObj);
00523 static void writeTextLog(const LogSelector* sel, const char* text);
00524
00525 private:
00526 static void lock();
00527 static void unlock();
00528 Log() { }
00529
00530 protected:
00531 static bool enabled;
00532 static bool autoAll;
00533 static const bool FLUSH;
00534
00535 typedef mace::hash_map<std::string, SelectorList*, mace::SoftState, hash_string> SelectorMap;
00536 typedef mace::hash_map<std::string, FILE*, mace::SoftState, hash_string> LogFileMap;
00537 typedef mace::hash_map<std::string, log_id_t, mace::SoftState, hash_string> SelectorIdMap;
00538 typedef mace::hash_map<log_id_t, std::string> IdSelectorMap;
00539 typedef std::vector<SelectorList*> IdSelectorList;
00540
00541
00542
00543 static SelectorMap selectors;
00544 static IdSelectorList selectorLists;
00545 static LogFileMap logFiles;
00546
00547 static SelectorList autoSelectors;
00548 static LogSelector* autoAllDefault;
00549 static pthread_mutex_t llock;
00550 static SelectorIdMap ids;
00551 static IdSelectorMap reverseIds;
00552 static uint32_t idCount;
00553 static const size_t MAX_MESSAGE_SIZE;
00554 static NullOutputType nullOutputVar;
00555 static log_level_t logLevel;
00556 static bool errorSelected;
00557 static bool warningSelected;
00558 static MaceTraceStream traceStream;
00559 static std::ifstream replayStream;
00560 };
00561
00562
00563
00564 namespace mace {
00565 template<typename S>
00566 void printItem(Log::MaceOutputStream& out, const S* pitem) {
00567 out.printItem(pitem);
00568 }
00569
00570 template<typename T> T const & logVal(T const & a, Log::MaceOutputStream& out, const mace::string& prefix) {
00571 out << prefix;
00572 printItem(out, &a);
00573 out << Log::end;
00574 return a;
00575 }
00576
00577 template<typename T> T& logVal(T& a, Log::MaceOutputStream& out, const mace::string& prefix) {
00578 out << prefix;
00579 printItem(out, &a);
00580 out << Log::end;
00581 return a;
00582 }
00583
00584 }
00585
00586 #define __LOG_H_DONE
00587 #include "massert.h"
00588 #endif // _LOG_H