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 {
00040 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00041 class log_streambuf
00042 : public ::std::basic_streambuf<_CharT, _Traits>
00043 {
00044 public:
00045 typedef _CharT char_type;
00046 typedef _Traits traits_type;
00047 typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
00048 typedef coil::Mutex Mutex;
00049 typedef coil::Guard<coil::Mutex> Guard;
00050
00066 log_streambuf()
00067 : streambuf_type()
00068 {
00069 char *pStart = m_buf;
00070 char *pEnd = m_buf + (BUFFER_LEN - 1);
00071 this->setp(pStart, pEnd);
00072 this->setg(pStart, pStart, pEnd);
00073 }
00074
00090 virtual ~log_streambuf()
00091 {
00092 }
00093
00123 void addStream(streambuf_type* stream, bool cleanup = false)
00124 {
00125 m_streams.push_back(Stream(stream, cleanup));
00126 }
00127
00150 bool removeStream(streambuf_type* stream)
00151 {
00152 std::vector<coil::log_streambuf<char>::Stream>::iterator it;
00153 for( it = m_streams.begin(); it != m_streams.end(); it++ )
00154 {
00155 if (it->stream_ == stream)
00156 {
00157 m_streams.erase(it);
00158 return true;
00159 }
00160 }
00161 return false;
00162 }
00163
00164
00165 std::vector<streambuf_type*> getBuffers()
00166 {
00167 std::vector<streambuf_type*> buffs;
00168 for (int i(0), len(m_streams.size()); i < len; ++i)
00169 {
00170 buffs.push_back(m_streams[i].stream_);
00171 }
00172 return buffs;
00173 }
00174
00175 protected:
00195 virtual std::streamsize xsputn(const char_type* s, std::streamsize n)
00196 {
00197 stream_sputn();
00198 for (int i(0), len(m_streams.size()); i < len; ++i)
00199 {
00200 Guard gaurd(m_streams[i].mutex_);
00201 m_streams[i].stream_->sputn(s, n);
00202 }
00203 return n;
00204 }
00205
00221 virtual std::streamsize stream_sputn()
00222 {
00223 int bytes_to_write;
00224 bytes_to_write = this->pptr() - this->gptr();
00225 if (bytes_to_write > 0)
00226 {
00227 for (int i(0), len(m_streams.size()); i < len; ++i)
00228 {
00229 Guard gaurd(m_streams[i].mutex_);
00230 m_streams[i].stream_->sputn(this->gptr(), bytes_to_write);
00231 }
00232 this->gbump(bytes_to_write);
00233 if (this->gptr() >= this->pptr())
00234 {
00235 this->pbump(this->pbase() - this->pptr());
00236 this->gbump(this->pbase() - this->gptr());
00237 }
00238 }
00239 return bytes_to_write;
00240 }
00241
00262 virtual std::streamsize stream_sputn(const char_type* s, std::streamsize n)
00263 {
00264
00265 for (int i(0), len(m_streams.size()); i < len; ++i)
00266 {
00267 Guard gaurd(m_streams[i].mutex_);
00268 m_streams[i].stream_->sputn(s, n);
00269 m_streams[i].stream_->pubsync();
00270 }
00271 return n;
00272 }
00290 virtual int overflow (int c = traits_type::eof())
00291 {
00292 Guard guard(m_mutex);
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 if (this->pbase())
00303 {
00304 if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00305 return traits_type::eof();
00306
00307 if (!traits_type::eq_int_type(c, traits_type::eof()))
00308 {
00309 this->pbump(-1);
00310 *(this->pptr()) = traits_type::to_char_type(c);
00311 this->pbump(1);
00312 }
00313
00314 int bytes_to_write = this->pptr() - this->gptr();
00315
00316 if (bytes_to_write > 0)
00317 {
00318 if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
00319 return traits_type::eof();
00320
00321 this->pbump(this->pbase() - this->pptr());
00322 this->gbump(this->pbase() - this->gptr());
00323 }
00324 }
00325
00326 else if (!traits_type::eq_int_type(c, traits_type::eof()))
00327 {
00328
00329 char_type last_char = traits_type::to_char_type(c);
00330
00331 if (stream_sputn(&last_char, 1) != 1)
00332 return traits_type::eof();
00333 }
00334
00335
00336 if (traits_type::eq_int_type(c, traits_type::eof()))
00337 return traits_type::not_eof(c);
00338 else
00339 return c;
00340 }
00341
00357 virtual int sync()
00358 {
00359 if (this->pbase())
00360 {
00361 Guard guard(m_mutex);
00362 if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00363 return -1;
00364
00365 int bytes_to_write;
00366 bytes_to_write = this->pptr() - this->gptr();
00367 if (bytes_to_write > 0)
00368 {
00369 if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
00370 {
00371 return -1;
00372 }
00373 this->gbump(bytes_to_write);
00374 if (this->gptr() >= this->pptr())
00375 {
00376 this->pbump(this->pbase() - this->pptr());
00377 this->gbump(this->pbase() - this->gptr());
00378 }
00379 }
00380 }
00381 else
00382 {
00383 this->overflow();
00384 }
00385 return 0;
00386 }
00387
00388 public:
00389 struct Stream
00390 {
00391 Stream(streambuf_type* stream, bool cleanup = false)
00392 : stream_(stream), cleanup_(cleanup)
00393 {
00394 }
00395
00396 virtual ~Stream()
00397 {
00398 }
00399
00400 Stream(const Stream& x)
00401 : stream_(x.stream_)
00402 {
00403 }
00404
00405 Stream& operator=(const Stream& x)
00406 {
00407 Stream tmp(x);
00408 tmp.swap(*this);
00409 return *this;
00410 }
00411
00412 void swap(Stream& x)
00413 {
00414 streambuf_type* stream = x.stream_;
00415 bool cleanup = x.cleanup_;
00416
00417 x.stream_ = this->stream_;
00418 x.cleanup_ = this->cleanup_;
00419
00420 this->stream_ = stream;
00421 this->cleanup_ = cleanup;
00422 }
00423 mutable Mutex mutex_;
00424 streambuf_type* stream_;
00425 bool cleanup_;
00426 };
00427
00428 private:
00429 log_streambuf(const log_streambuf& x);
00430 log_streambuf& operator=(const log_streambuf& x);
00431
00432 std::vector<Stream> m_streams;
00433 Mutex m_mutex;
00434 char m_buf[BUFFER_LEN];
00435 };
00436
00437
00447 template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
00448 class log_stream
00449 : public std::basic_ostream<_CharT, _Traits>
00450 {
00451 public:
00452
00453 typedef _CharT char_type;
00454 typedef _Traits traits_type;
00455 typedef std::basic_ostream<char_type, traits_type> ostream_type;
00456 typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
00457 typedef coil::Mutex Mutex;
00458 typedef coil::Guard<Mutex> Guard;
00459
00485 log_stream(streambuf_type* sb, int levelmin, int levelmax, int level)
00486 : ostream_type(sb),
00487 m_minLevel(levelmin), m_maxLevel(levelmax), m_logLevel(level)
00488 {
00489 if (m_minLevel >= m_maxLevel) throw std::bad_alloc();
00490 this->init(sb);
00491 }
00492
00511 virtual void header(int level)
00512 {
00513 return;
00514 }
00515
00535 bool setLevel(int level)
00536 {
00537 if (m_minLevel <= level && level <= m_maxLevel)
00538 {
00539 m_logLevel = level;
00540 return true;
00541 }
00542 return false;
00543 }
00544
00564 int getLevel() const
00565 {
00566 return m_logLevel;
00567 }
00568
00584 void enableLock()
00585 {
00586 m_lockEnable = true;
00587 }
00588
00604 void disableLock()
00605 {
00606 m_lockEnable = false;
00607 }
00608
00640 ostream_type& level(int level)
00641 {
00642 if (m_minLevel <= level && level <= m_logLevel)
00643 {
00644 header(level);
00645 return *this;
00646 }
00647 else
00648 {
00649 return m_dummy;
00650 }
00651 }
00652
00653 bool isValid(int level) const
00654 {
00655 return m_minLevel <= level && level <= m_logLevel;
00656 }
00657
00658
00672 inline void lock()
00673 {
00674 if (m_lockEnable) m_mutex.lock();
00675 }
00676
00690 inline void unlock()
00691 {
00692 if (m_lockEnable) m_mutex.unlock();
00693 }
00694
00695
00696 protected:
00697 ~log_stream(){};
00698 log_stream();
00699 log_stream(const log_stream& x);
00700 log_stream& operator=(const log_stream& x);
00701
00702 private:
00703 int m_minLevel, m_maxLevel;
00704 int m_logLevel;
00705
00713 std::ofstream m_dummy;
00714 public:
00715 static bool m_lockEnable;
00716 static Mutex m_mutex;
00717 };
00718
00719 template <typename _CharT, typename _Traits >
00720 bool log_stream<_CharT,_Traits >::m_lockEnable = true;
00721
00722 template <typename _CharT, typename _Traits >
00723 coil::Mutex log_stream<_CharT,_Traits>::m_mutex("Mutex for Logger.");
00724
00725 typedef log_streambuf<char> LogStreamBuffer;
00726 typedef log_stream<char> LogStream;
00727
00728 };
00729 #endif // LOGGER_H