00001
00020 #ifndef LOGGER_H
00021 #define LOGGER_H
00022
00023 #include <limits.h>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <vector>
00027 #include <string>
00028
00029 #include <coil/Mutex.h>
00030 #include <coil/Guard.h>
00031
00032 #ifndef LINE_MAX
00033 #define LINE_MAX 1024
00034 #endif
00035
00036 #define BUFFER_LEN LINE_MAX
00037
00038 namespace coil
00039 {
00053 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00054 class log_streambuf
00055 : public ::std::basic_streambuf<_CharT, _Traits>
00056 {
00057 public:
00058 typedef _CharT char_type;
00059 typedef _Traits traits_type;
00060 typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
00061 typedef coil::Mutex Mutex;
00062 typedef coil::Guard<coil::Mutex> Guard;
00063
00079 log_streambuf()
00080 : streambuf_type()
00081 {
00082 char *pStart = m_buf;
00083 char *pEnd = m_buf + (BUFFER_LEN - 1);
00084 this->setp(pStart, pEnd);
00085 this->setg(pStart, pStart, pEnd);
00086 }
00087
00103 virtual ~log_streambuf()
00104 {
00105 }
00106
00136 void addStream(streambuf_type* stream, bool cleanup = false)
00137 {
00138 m_streams.push_back(Stream(stream, cleanup));
00139 }
00140
00163 bool removeStream(streambuf_type* stream)
00164 {
00165 std::vector<coil::log_streambuf<char>::Stream>::iterator it;
00166 for( it = m_streams.begin(); it != m_streams.end(); it++ )
00167 {
00168 if (it->stream_ == stream)
00169 {
00170 m_streams.erase(it);
00171 return true;
00172 }
00173 }
00174 return false;
00175 }
00176
00196 std::vector<streambuf_type*> getBuffers()
00197 {
00198 std::vector<streambuf_type*> buffs;
00199 for (int i(0), len(m_streams.size()); i < len; ++i)
00200 {
00201 buffs.push_back(m_streams[i].stream_);
00202 }
00203 return buffs;
00204 }
00205
00206 protected:
00226 virtual std::streamsize xsputn(const char_type* s, std::streamsize n)
00227 {
00228 stream_sputn();
00229 for (int i(0), len(m_streams.size()); i < len; ++i)
00230 {
00231 Guard gaurd(m_streams[i].mutex_);
00232 m_streams[i].stream_->sputn(s, n);
00233 }
00234 return n;
00235 }
00236
00252 virtual std::streamsize stream_sputn()
00253 {
00254 int bytes_to_write;
00255 bytes_to_write = this->pptr() - this->gptr();
00256 if (bytes_to_write > 0)
00257 {
00258 for (int i(0), len(m_streams.size()); i < len; ++i)
00259 {
00260 Guard gaurd(m_streams[i].mutex_);
00261 m_streams[i].stream_->sputn(this->gptr(), bytes_to_write);
00262 }
00263 this->gbump(bytes_to_write);
00264 if (this->gptr() >= this->pptr())
00265 {
00266 this->pbump(this->pbase() - this->pptr());
00267 this->gbump(this->pbase() - this->gptr());
00268 }
00269 }
00270 return bytes_to_write;
00271 }
00272
00293 virtual std::streamsize stream_sputn(const char_type* s, std::streamsize n)
00294 {
00295
00296 for (int i(0), len(m_streams.size()); i < len; ++i)
00297 {
00298 Guard gaurd(m_streams[i].mutex_);
00299 m_streams[i].stream_->sputn(s, n);
00300 m_streams[i].stream_->pubsync();
00301 }
00302 return n;
00303 }
00322 virtual int overflow (int c = traits_type::eof())
00323 {
00324 Guard guard(m_mutex);
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 if (this->pbase())
00335 {
00336 if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00337 return traits_type::eof();
00338
00339 if (!traits_type::eq_int_type(c, traits_type::eof()))
00340 {
00341 this->pbump(-1);
00342 *(this->pptr()) = traits_type::to_char_type(c);
00343 this->pbump(1);
00344 }
00345
00346 int bytes_to_write = this->pptr() - this->gptr();
00347
00348 if (bytes_to_write > 0)
00349 {
00350 if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
00351 return traits_type::eof();
00352
00353 this->pbump(this->pbase() - this->pptr());
00354 this->gbump(this->pbase() - this->gptr());
00355 }
00356 }
00357
00358 else if (!traits_type::eq_int_type(c, traits_type::eof()))
00359 {
00360
00361 char_type last_char = traits_type::to_char_type(c);
00362
00363 if (stream_sputn(&last_char, 1) != 1)
00364 return traits_type::eof();
00365 }
00366
00367
00368 if (traits_type::eq_int_type(c, traits_type::eof()))
00369 return traits_type::not_eof(c);
00370 else
00371 return c;
00372 }
00373
00389 virtual int sync()
00390 {
00391 if (this->pbase())
00392 {
00393 Guard guard(m_mutex);
00394 if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00395 return -1;
00396
00397 int bytes_to_write;
00398 bytes_to_write = this->pptr() - this->gptr();
00399 if (bytes_to_write > 0)
00400 {
00401 if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
00402 {
00403 return -1;
00404 }
00405 this->gbump(bytes_to_write);
00406 if (this->gptr() >= this->pptr())
00407 {
00408 this->pbump(this->pbase() - this->pptr());
00409 this->gbump(this->pbase() - this->gptr());
00410 }
00411 }
00412 }
00413 else
00414 {
00415 this->overflow();
00416 }
00417 return 0;
00418 }
00419
00420 public:
00421
00433 struct Stream
00434 {
00435 Stream(streambuf_type* stream, bool cleanup = false)
00436 : stream_(stream), cleanup_(cleanup)
00437 {
00438 }
00439
00440 virtual ~Stream()
00441 {
00442 }
00443
00444 Stream(const Stream& x)
00445 : stream_(x.stream_)
00446 {
00447 }
00448
00449 Stream& operator=(const Stream& x)
00450 {
00451 Stream tmp(x);
00452 tmp.swap(*this);
00453 return *this;
00454 }
00455
00456 void swap(Stream& x)
00457 {
00458 streambuf_type* stream = x.stream_;
00459 bool cleanup = x.cleanup_;
00460
00461 x.stream_ = this->stream_;
00462 x.cleanup_ = this->cleanup_;
00463
00464 this->stream_ = stream;
00465 this->cleanup_ = cleanup;
00466 }
00467 mutable Mutex mutex_;
00468 streambuf_type* stream_;
00469 bool cleanup_;
00470 };
00471
00472 private:
00473
00493 log_streambuf(const log_streambuf& x);
00494
00518 log_streambuf& operator=(const log_streambuf& x);
00519
00520 std::vector<Stream> m_streams;
00521 Mutex m_mutex;
00522 char m_buf[BUFFER_LEN];
00523 };
00524
00525
00539 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00540 class log_stream
00541 : public std::basic_ostream<_CharT, _Traits>
00542 {
00543 public:
00544
00545 typedef _CharT char_type;
00546 typedef _Traits traits_type;
00547 typedef std::basic_ostream<char_type, traits_type> ostream_type;
00548 typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
00549 typedef coil::Mutex Mutex;
00550 typedef coil::Guard<Mutex> Guard;
00551
00577 log_stream(streambuf_type* sb, int levelmin, int levelmax, int level)
00578 : ostream_type(sb),
00579 m_minLevel(levelmin), m_maxLevel(levelmax), m_logLevel(level)
00580 {
00581 if (m_minLevel >= m_maxLevel) throw std::bad_alloc();
00582 this->init(sb);
00583 }
00584
00603 virtual void header(int level)
00604 {
00605 return;
00606 }
00607
00627 bool setLevel(int level)
00628 {
00629 if (m_minLevel <= level && level <= m_maxLevel)
00630 {
00631 m_logLevel = level;
00632 return true;
00633 }
00634 return false;
00635 }
00636
00656 int getLevel() const
00657 {
00658 return m_logLevel;
00659 }
00660
00676 void enableLock()
00677 {
00678 m_lockEnable = true;
00679 }
00680
00696 void disableLock()
00697 {
00698 m_lockEnable = false;
00699 }
00700
00732 ostream_type& level(int level)
00733 {
00734 if (m_minLevel <= level && level <= m_logLevel)
00735 {
00736 header(level);
00737 return *this;
00738 }
00739 else
00740 {
00741 return m_dummy;
00742 }
00743 }
00744
00769 bool isValid(int level) const
00770 {
00771 return m_minLevel <= level && level <= m_logLevel;
00772 }
00773
00787 inline void lock()
00788 {
00789 if (m_lockEnable) m_mutex.lock();
00790 }
00791
00805 inline void unlock()
00806 {
00807 if (m_lockEnable) m_mutex.unlock();
00808 }
00809
00810
00811 protected:
00812
00828 ~log_stream(){};
00829
00845 log_stream();
00846
00866 log_stream(const log_stream& x);
00867
00891 log_stream& operator=(const log_stream& x);
00892
00893 private:
00894 int m_minLevel, m_maxLevel;
00895 int m_logLevel;
00896
00904 std::ofstream m_dummy;
00905 public:
00906
00914 static bool m_lockEnable;
00915
00923 static Mutex m_mutex;
00924 };
00925
00926 template <typename _CharT, typename _Traits >
00927 bool log_stream<_CharT,_Traits >::m_lockEnable = true;
00928
00929 template <typename _CharT, typename _Traits >
00930 coil::Mutex log_stream<_CharT,_Traits>::m_mutex("Mutex for Logger.");
00931
00932 typedef log_streambuf<char> LogStreamBuffer;
00933 typedef log_stream<char> LogStream;
00934
00935 };
00936 #endif // LOGGER_H