00001
00019 #ifndef SystemLogger_h
00020 #define SystemLogger_h
00021
00022 #include <rtm/RTC.h>
00023
00024 #include <iostream>
00025 #include <fstream>
00026 #include <stdio.h>
00027 #include <stdarg.h>
00028 #include <limits.h>
00029 #include <time.h>
00030 #include <errno.h>
00031
00032
00033 #include <ace/Mutex.h>
00034
00035 #include <rtm/config_rtc.h>
00036
00037 #ifdef RTM_GCC2
00038 #define NO_LOGGING
00039 #endif
00040
00041 #ifdef WIN32
00042
00043 #define __restrict
00044 #endif
00045
00046 namespace RTC
00047 {
00048
00049 #ifndef NO_LOGGING
00050
00066 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00067 class sync_callback
00068 {
00069 public:
00079 virtual ~sync_callback(){}
00080
00103 virtual int operator()(const _CharT* s) = 0;
00104 };
00105
00106
00128 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00129 class basic_logbuf
00130 : public std::basic_filebuf<_CharT, _Traits>
00131 {
00132 public:
00133
00134 typedef _CharT char_type;
00135 typedef _Traits traits_type;
00136 typedef std::basic_filebuf<char_type, traits_type> __filebuf_type;
00137
00153 basic_logbuf()
00154 : __filebuf_type(), m_pCallBack(NULL)
00155 {;}
00156
00180 basic_logbuf(const char_type* s,
00181 std::ios_base::openmode mode = std::ios_base::out,
00182 long protection = 0666)
00183 : __filebuf_type(), m_pCallBack(NULL)
00184 {
00185 this->open(s, mode);
00186 }
00187
00203 virtual ~basic_logbuf()
00204 {
00205 this->sync();
00206 this->close();
00207 };
00208
00235 virtual std::streamsize sputn(const char_type* s, std::streamsize n)
00236 {
00237 ACE_Guard<ACE_Thread_Mutex> gaurd(m_Mutex);
00238
00239
00240
00241 std::streamsize ssize = this->xsputn(s, n);
00242
00243
00244
00245
00246
00247
00248 this->sync();
00249 return ssize;
00250 }
00251
00271 void setSyncCallBack(sync_callback<char_type>& cb)
00272 {
00273 m_pCallBack = &cb;
00274 }
00275
00276 protected:
00296 virtual int sync()
00297 {
00298 std::basic_string<_CharT> s(this->pbase(),
00299 this->pptr() - this->pbase());
00300 if (m_pCallBack != NULL)
00301 {
00302 (*m_pCallBack)(s.c_str());
00303 }
00304
00305 int ret = __filebuf_type::sync();
00306
00307 return ret;
00308 }
00309
00310 private:
00311 ACE_Thread_Mutex m_Mutex;
00312 sync_callback<char_type>* m_pCallBack;
00313 };
00314
00315
00339 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00340 class basic_medlogbuf
00341 : public std::basic_streambuf<_CharT, _Traits>
00342 {
00343 public:
00344
00345 typedef _CharT char_type;
00346 typedef _Traits traits_type;
00347 typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00348 typedef std::basic_filebuf<char_type, traits_type> __filebuf_type;
00349
00363 basic_medlogbuf()
00364 : __streambuf_type(), m_pLogbuf(NULL)
00365 {
00366
00367 m_DateFmt = "[%Y-%m-%dT%H.%M.%S%Z]";
00368 }
00369
00387 basic_medlogbuf(__filebuf_type& filebuf)
00388 : __streambuf_type(), m_pLogbuf(&filebuf)
00389 {
00390 char *pStart = m_Data;
00391 char *pEnd = m_Data + (LINE_MAX - 1);
00392 this->setp(pStart, pEnd);
00393 this->setg(pStart, pStart, pEnd);
00394
00395
00396 m_DateFmt = "[%Y-%m-%dT%H.%M.%S%Z]";
00397 }
00398
00410 basic_medlogbuf(const basic_medlogbuf& x)
00411 : __streambuf_type(), m_pLogbuf(x.m_pLogbuf),
00412 m_DateFmt(x.m_DateFmt), m_Suffix(x.m_Suffix)
00413 {
00414 char *pStart = m_Data;
00415 char *pEnd = m_Data + (LINE_MAX - 1);
00416 this->setp(pStart, pEnd);
00417 this->setg(pStart, pStart, pEnd);
00418 }
00419
00435 virtual ~basic_medlogbuf()
00436 {
00437 this->sync();
00438 }
00439
00457 void setBuffer(__filebuf_type& filebuf)
00458 {
00459 m_pLogbuf = &filebuf;
00460 char *pStart = m_Data;
00461 char *pEnd = m_Data + (LINE_MAX - 1);
00462 this->setp(pStart, pEnd);
00463 this->setg(pStart, pStart, pEnd);
00464 }
00465
00537 void setDateFmt(char* fmt)
00538 {
00539 m_DateFmt = std::string(fmt);
00540 }
00541
00562 void setDateFmt(const std::string& fmt)
00563 {
00564 m_DateFmt = fmt;
00565 }
00566
00586 std::string getFmtDate()
00587 {
00588 const int maxsize = 256;
00589 char buf[maxsize];
00590
00591
00592
00593
00594
00595 time_t timer;
00596 struct tm* date;
00597
00598 timer = time(NULL);
00599 date = localtime(&timer);
00600 strftime(buf, maxsize, m_DateFmt.c_str(), date);
00601
00602 std::string ret(buf);
00603 return ret;
00604 }
00605
00625 void setSuffix(char* suffix)
00626 {
00627 m_Suffix = std::string(suffix);
00628 }
00629
00649 void setSuffix(const std::string& suffix)
00650 {
00651 m_Suffix = suffix;
00652 }
00653
00673 std::string getSuffix()
00674 {
00675 return m_Suffix;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685 protected:
00705 virtual int sync()
00706 {
00707 ACE_Guard<ACE_Thread_Mutex> guard(m_Mutex);
00708 int ret(0);
00709 if (m_pLogbuf != NULL && (this->pptr() - this->pbase()) > 0)
00710 {
00711 {
00712
00713 *(this->pptr()) = '\0';
00714 std::basic_string<_CharT> tmp(this->pbase(),
00715 this->pptr() -
00716 this->pbase());
00717
00718 std::string s = getFmtDate();
00719 s += ( s.size() > 0 ? " " : "" ) + getSuffix();
00720 s += ( getSuffix().size() > 0 ? " " : "" ) + tmp;
00721
00722
00723 m_pLogbuf->sputn(s.c_str(), s.size());
00724 m_pLogbuf->pubsync();
00725
00726
00727 ret = __streambuf_type::sync();
00728 pbump( this->pbase() - this->pptr() );
00729 }
00730 }
00731 return ret;
00732 }
00733
00734 private:
00735 __filebuf_type* m_pLogbuf;
00736 char m_Data[LINE_MAX];
00737 std::string m_DateFmt;
00738 std::string m_Suffix;
00739 ACE_Thread_Mutex m_Mutex;
00740 };
00741
00761 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00762 class basic_dummybuf
00763 : public std::basic_streambuf<_CharT, _Traits>
00764 {
00765 public:
00766
00767 typedef _CharT char_type;
00768 typedef _Traits traits_type;
00769 typedef typename traits_type::int_type int_type;
00770 typedef typename traits_type::pos_type pos_type;
00771 typedef typename traits_type::off_type off_type;
00772 typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00773 typedef std::basic_filebuf<char_type, traits_type> __filebuf_type;
00774
00788 basic_dummybuf()
00789 {
00790 char *pStart = m_Data;
00791 char *pEnd = m_Data + (LINE_MAX - 1);
00792 this->setp(pStart, pEnd);
00793 this->setg(pStart, pStart, pEnd);
00794 }
00795
00811 ~basic_dummybuf()
00812 {
00813 }
00814
00840 int_type overflow(int_type c = _Traits::eof() )
00841 {
00842 pbump( this->pbase() - this->pptr() );
00843 return _Traits::not_eof(c);
00844 }
00845
00865 virtual int sync()
00866 {
00867 pbump( this->pbase() - this->pptr() );
00868 return 0;
00869 }
00870
00871 private:
00872 char m_Data[255];
00873 };
00874
00894 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00895 class basic_logstream
00896 : public std::basic_ostream<_CharT, _Traits>
00897 {
00898 public:
00899
00900 enum
00901 {
00902 RTL_SILENT,
00903 RTL_ERROR,
00904 RTL_WARN,
00905 RTL_INFO,
00906 RTL_NORMAL,
00907 RTL_DEBUG,
00908 RTL_TRACE,
00909 RTL_VERBOSE,
00910 RTL_PARANOID,
00911 RTL_MANDATORY
00912 };
00913
00937 static int strToLogLevel(const std::string& lv)
00938 {
00939 if (lv == "SILENT")
00940 return basic_logstream::RTL_SILENT;
00941 else if (lv == "ERROR")
00942 return basic_logstream::RTL_ERROR;
00943 else if (lv == "WARN")
00944 return basic_logstream::RTL_WARN;
00945 else if (lv == "INFO")
00946 return basic_logstream::RTL_INFO;
00947 else if (lv == "NORNAL")
00948 return basic_logstream::RTL_NORMAL;
00949 else if (lv == "DEBUG")
00950 return basic_logstream::RTL_DEBUG;
00951 else if (lv == "TRACE")
00952 return basic_logstream::RTL_TRACE;
00953 else if (lv == "VERBOSE")
00954 return basic_logstream::RTL_VERBOSE;
00955 else if (lv == "PARANOID")
00956 return basic_logstream::RTL_PARANOID;
00957 else if (lv == "MANDATORY")
00958 return basic_logstream::RTL_MANDATORY;
00959 else
00960 return basic_logstream::RTL_NORMAL;
00961 }
00962
00963
00964 typedef _CharT char_type;
00965 typedef _Traits traits_type;
00966 typedef basic_logbuf<char_type, traits_type> __logbuf_type;
00967 typedef basic_dummybuf<char_type, traits_type> __dummybuf_type;
00968 typedef basic_logstream<char_type, traits_type> __logstream_type;
00969 typedef std::basic_ostream<char_type, traits_type> __ostream_type;
00970 typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00971
00991 basic_logstream(__streambuf_type& streambuf)
00992 : __ostream_type(&streambuf),
00993 m_DummyStream(new __dummybuf_type()),
00994 m_LogLevel(RTL_NORMAL), m_LogLock(false)
00995 {
00996 this->init(&streambuf);
00997 }
00998
01014 ~basic_logstream()
01015 {
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01059 static std::string printf(char const * __restrict fmt, ...)
01060 {
01061 char str[LINE_MAX];
01062 va_list ap;
01063
01064 va_start(ap, fmt);
01065 #ifdef WIN32
01066 _vsnprintf(str, LINE_MAX - 1, fmt, ap);
01067 #else
01068 vsnprintf(str, LINE_MAX - 1, fmt, ap);
01069 #endif
01070 va_end(ap);
01071 std::string s(str);
01072
01073 return s;
01074 }
01075
01095 void setLogLevel(const std::string& level)
01096 {
01097 m_LogLevel = strToLogLevel(level);
01098 }
01099
01119 void setLogLevel(int level)
01120 {
01121 m_LogLevel = level;
01122 }
01123
01143 void setLogLock(bool lock)
01144 {
01145 m_LogLock = lock;
01146 }
01147
01163 void enableLogLock()
01164 {
01165 m_LogLock = true;
01166 }
01167
01183 void disableLogLock()
01184 {
01185 m_LogLock = false;
01186 }
01187
01219 __ostream_type& level(int level)
01220 {
01221 if (m_LogLevel >= level)
01222 {
01223 return *this;
01224 }
01225 else
01226 {
01227 return m_DummyStream;
01228 }
01229 }
01230
01244 inline void acquire()
01245 {
01246 if (m_LogLock) m_Mutex.acquire();
01247 }
01248
01262 inline void release()
01263 {
01264 if (m_LogLock) m_Mutex.release();
01265 }
01266
01274 __ostream_type m_DummyStream;
01275
01276 private:
01277 int m_LogLevel;
01278 bool m_LogLock;
01279 ACE_Thread_Mutex m_Mutex;
01280 };
01281 typedef sync_callback<char> SyncCallback;
01282 typedef basic_logbuf<char> Logbuf;
01283 typedef basic_medlogbuf<char> MedLogbuf;
01284 typedef basic_logstream<char> LogStream;
01285
01286 #else
01287
01288
01304 class SyncCallback
01305 {
01306 public:
01320 SyncCallback() {;};
01321
01343 virtual int operator()(const char* s) {;};
01344 };
01345
01365 class Logbuf
01366 {
01367 public:
01383 Logbuf() {;};
01384
01408 Logbuf(const char* s, int m) {;};
01409
01433 void open(const char* s, int m) {;};
01434
01456 void setSyncCallBack(SyncCallback& cb) {;};
01457 };
01458
01474 class MedLogbuf
01475 {
01476 public:
01490 MedLogbuf() {;};
01491
01509 MedLogbuf(Logbuf& f) {;};
01510
01528 void setDateFmt(char* fmt) {;};
01529
01549 void setDateFmt(const std::string& fmt) {;};
01550
01572 void setSuffix(const char* suffix) {;};
01573
01595 void setSuffix(const std::string& suffix) {;};
01596 };
01597
01617 class LogStream
01618 : public ostream
01619 {
01620 public:
01621 enum
01622 {
01623 SILENT,
01624 ERROR,
01625 WARN,
01626 INFO,
01627 NORMAL,
01628 DEBUG,
01629 TRACE,
01630 VERBOSE,
01631 PARANOID,
01632 MANDATORY
01633 };
01634
01660 static int strToLogLevel(const std::string& lv){return NORMAL;}
01661
01683 LogStream(MedLogbuf& buf) {;};
01684
01706 void setLogLevel(int level) {;};
01707
01729 void setLogLock(int lock) {;};
01730
01754 LogStream& level(int level) {return *this;};
01755
01756
01757
01758
01759
01760
01761 };
01762
01763 #endif // NO_LOGGING
01764
01765
01766
01767 #if 0
01768 #define RTC_LOG(LV, fmt, ...) \
01769 rtcout.level(LV) << rtcout.printf(fmt, __VA_ARGS__) << std::endl;
01770 #define RTC_ERROR(fmt, ...) \
01771 RTC_LOG(LogStream::RTL_ERROR, fmt, __VA_ARGS__)
01772 #define RTC_WARN(fmt, ...) \
01773 RTC_LOG(LogStream::RTL_WARN, fmt, __VA_ARGS__)
01774 #define RTC_NORMAL(fmt, ...) \
01775 RTC_LOG(LogStream::RTL_NORMAL, fmt, __VA_ARGS__)
01776 #define RTC_INFO(fmt, ...) \
01777 RTC_LOG(LogStream::RTL_INFO, fmt, __VA_ARGS__)
01778 #define RTC_DEBUG(fmt, ...) \
01779 RTC_LOG(LogStream::RTL_DEBUG, fmt, __VA_ARGS__)
01780 #define RTC_TRACE(fmt, ...) \
01781 RTC_LOG(LogStream::RTL_TRACE, fmt, __VA_ARGS__)
01782 #define RTC_VERBOSE(fmt, ...) \
01783 RTC_LOG(LogStream::RTL_VERBOSE, fmt, __VA_ARGS__)
01784 #define RTC_PARANOID(fmt, ...) \
01785 RTC_LOG(LogStream::RTL_PARANOID, fmt, __VA_ARGS__)
01786 #endif
01787
01788 #ifndef NO_LOGGING
01789
01805 #define RTC_LOG(LV, fmt) \
01806 rtcout.acquire(); \
01807 rtcout.level(LV) << rtcout.printf fmt << std::endl; \
01808 rtcout.release()
01809
01829 #define RTC_ERROR(fmt) \
01830 rtcout.acquire(); \
01831 rtcout.level(LogStream::RTL_ERROR) << rtcout.printf fmt << std::endl; \
01832 rtcout.release()
01833
01853 #define RTC_WARN(fmt) \
01854 rtcout.acquire(); \
01855 rtcout.level(LogStream::RTL_WARN) << rtcout.printf fmt << std::endl; \
01856 rtcout.release()
01857
01877 #define RTC_INFO(fmt) \
01878 rtcout.acquire(); \
01879 rtcout.level(LogStream::RTL_INFO) << rtcout.printf fmt << std::endl; \
01880 rtcout.release()
01881
01901 #define RTC_NORMAL(fmt) \
01902 rtcout.acquire(); \
01903 rtcout.level(LogStream::RTL_NORMAL) << rtcout.printf fmt << std::endl; \
01904 rtcout.release()
01905
01925 #define RTC_DEBUG(fmt) \
01926 rtcout.acquire(); \
01927 rtcout.level(LogStream::RTL_DEBUG) << rtcout.printf fmt << std::endl; \
01928 rtcout.release()
01929
01949 #define RTC_TRACE(fmt) \
01950 rtcout.acquire(); \
01951 rtcout.level(LogStream::RTL_TRACE) << rtcout.printf fmt << std::endl; \
01952 rtcout.release()
01953
01973 #define RTC_VERBOSE(fmt) \
01974 rtcout.acquire(); \
01975 rtcout.level(LogStream::RTL_VERBOSE) << rtcout.printf fmt << std::endl; \
01976 rtcout.release()
01977
01997 #define RTC_PARANOID(fmt) \
01998 rtcout.acquire(); \
01999 rtcout.level(LogStream::RTL_PARANOID) << rtcout.printf fmt << std::endl; \
02000 rtcout.release()
02001
02002 #else
02003 #define RTC_ERROR(fmt)
02004 #define RTC_WARN(fmt)
02005 #define RTC_NORMAL(fmt)
02006 #define RTC_INFO(fmt)
02007 #define RTC_DEBUG(fmt)
02008 #define RTC_TRACE(fmt)
02009 #define RTC_VERBOSE(fmt)
02010 #define RTC_PARANOID(fmt)
02011 #endif
02012
02013 };
02014
02015 #endif // SystemLogger_h