Logger.h
Go to the documentation of this file.
00001 // -*- C++ -*-
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 //      if (traits_type::eq_int_type(c, traits_type::eof()))
00326 //        return c;
00327 //
00328 //      char_type last_char = traits_type::to_char_type(c);
00329 //      if (sputn(&last_char, 1) != 1)
00330 //        return traits_type::eof();
00331 //      else
00332 //        return c;
00333 
00334       if (this->pbase())
00335         {
00336           if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
00337             return traits_type::eof();
00338           // Add extra character to buffer if not EOF
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           // Number of characters to write to file
00346           int bytes_to_write = this->pptr() - this->gptr();
00347           // Overflow doesn't fail if nothing is to be written
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               // Reset next pointer to point to pbase on success
00353               this->pbump(this->pbase() - this->pptr());
00354               this->gbump(this->pbase() - this->gptr());
00355             }
00356         }
00357       // Write extra character to file if not EOF
00358       else if (!traits_type::eq_int_type(c, traits_type::eof()))
00359         {
00360           // Impromptu char buffer (allows "unbuffered" output)
00361           char_type last_char = traits_type::to_char_type(c);
00362           // If gzipped file won't accept this character, fail
00363           if (stream_sputn(&last_char, 1) != 1)
00364             return traits_type::eof();
00365         }
00366       // If you got here, you have succeeded (even if c was EOF)
00367       // The return value should therefore be non-EOF
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     // Types:
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


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Thu Aug 27 2015 14:16:37