OpenRTM-aist  1.2.1
Logger.h
Go to the documentation of this file.
1 // -*- C++ -*-
20 #ifndef LOGGER_H
21 #define LOGGER_H
22 
23 #include <limits.h>
24 #include <iostream>
25 #include <fstream>
26 #include <vector>
27 #include <string>
28 
29 #include <coil/Mutex.h>
30 #include <coil/Guard.h>
31 
32 #ifndef LINE_MAX
33 #define LINE_MAX 1024
34 #endif
35 
36 #define BUFFER_LEN LINE_MAX
37 
38 namespace coil
39 {
53  template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
55  : public ::std::basic_streambuf<_CharT, _Traits>
56  {
57  public:
58  typedef _CharT char_type;
59  typedef _Traits traits_type;
60  typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
61  typedef coil::Mutex Mutex;
63 
80  : streambuf_type()
81  {
82  char *pStart = m_buf;
83  char *pEnd = m_buf + (BUFFER_LEN - 1);
84  this->setp(pStart, pEnd);
85  this->setg(pStart, pStart, pEnd);
86  }
87 
103  virtual ~log_streambuf()
104  {
105  }
106 
136  void addStream(streambuf_type* stream, bool cleanup = false)
137  {
138  m_streams.push_back(Stream(stream, cleanup));
139  }
140 
163  bool removeStream(streambuf_type* stream)
164  {
165  std::vector<coil::log_streambuf<char>::Stream>::iterator it;
166  for( it = m_streams.begin(); it != m_streams.end(); it++ )
167  {
168  if (it->stream_ == stream)
169  {
170  m_streams.erase(it);
171  return true;
172  }
173  }
174  return false;
175  }
176 
196  std::vector<streambuf_type*> getBuffers()
197  {
198  std::vector<streambuf_type*> buffs;
199  for (int i(0), len(m_streams.size()); i < len; ++i)
200  {
201  buffs.push_back(m_streams[i].stream_);
202  }
203  return buffs;
204  }
205 
206  protected:
226  virtual std::streamsize xsputn(const char_type* s, std::streamsize n)
227  {
228  stream_sputn();
229  for (size_t i(0), len(m_streams.size()); i < len; ++i)
230  {
231  Guard gaurd(m_streams[i].mutex_);
232  m_streams[i].stream_->sputn(s, n);
233  }
234  return n;
235  }
236 
252  virtual std::streamsize stream_sputn()
253  {
254  size_t bytes_to_write;
255  bytes_to_write = this->pptr() - this->gptr();
256  if (bytes_to_write > 0)
257  {
258  for (size_t i(0), len(m_streams.size()); i < len; ++i)
259  {
260  Guard gaurd(m_streams[i].mutex_);
261  m_streams[i].stream_->sputn(this->gptr(), bytes_to_write);
262  }
263  this->gbump(static_cast<int>(bytes_to_write));
264  if (this->gptr() >= this->pptr())
265  {
266  this->pbump(static_cast<int>(this->pbase() - this->pptr()));
267  this->gbump(static_cast<int>(this->pbase() - this->gptr()));
268  }
269  }
270  return bytes_to_write;
271  }
272 
293  virtual std::streamsize stream_sputn(const char_type* s, std::streamsize n)
294  {
295 
296  for (size_t i(0), len(m_streams.size()); i < len; ++i)
297  {
298  Guard gaurd(m_streams[i].mutex_);
299  m_streams[i].stream_->sputn(s, n);
300  m_streams[i].stream_->pubsync();
301  }
302  return n;
303  }
322  virtual int overflow (int c = traits_type::eof())
323  {
324  Guard guard(m_mutex);
325 // if (traits_type::eq_int_type(c, traits_type::eof()))
326 // return c;
327 //
328 // char_type last_char = traits_type::to_char_type(c);
329 // if (sputn(&last_char, 1) != 1)
330 // return traits_type::eof();
331 // else
332 // return c;
333 
334  if (this->pbase())
335  {
336  if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
337  return traits_type::eof();
338  // Add extra character to buffer if not EOF
339  if (!traits_type::eq_int_type(c, traits_type::eof()))
340  {
341  this->pbump(-1);
342  *(this->pptr()) = traits_type::to_char_type(c);
343  this->pbump(1);
344  }
345  // Number of characters to write to file
346  size_t bytes_to_write = this->pptr() - this->gptr();
347  // Overflow doesn't fail if nothing is to be written
348  if (bytes_to_write > 0)
349  {
350  if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
351  return traits_type::eof();
352  // Reset next pointer to point to pbase on success
353  this->pbump(static_cast<int>(this->pbase() - this->pptr()));
354  this->gbump(static_cast<int>(this->pbase() - this->gptr()));
355  }
356  }
357  // Write extra character to file if not EOF
358  else if (!traits_type::eq_int_type(c, traits_type::eof()))
359  {
360  // Impromptu char buffer (allows "unbuffered" output)
361  char_type last_char = traits_type::to_char_type(c);
362  // If gzipped file won't accept this character, fail
363  if (stream_sputn(&last_char, 1) != 1)
364  return traits_type::eof();
365  }
366  // If you got here, you have succeeded (even if c was EOF)
367  // The return value should therefore be non-EOF
368  if (traits_type::eq_int_type(c, traits_type::eof()))
369  return traits_type::not_eof(c);
370  else
371  return c;
372  }
373 
389  virtual int sync()
390  {
391  if (this->pbase())
392  {
393  Guard guard(m_mutex);
394  if (this->pptr() > this->epptr() || this->pptr() < this->pbase())
395  return -1;
396 
397  size_t bytes_to_write;
398  bytes_to_write = this->pptr() - this->gptr();
399  if (bytes_to_write > 0)
400  {
401  if (stream_sputn(this->gptr(), bytes_to_write) != bytes_to_write)
402  {
403  return -1;
404  }
405  this->gbump(static_cast<int>(bytes_to_write));
406  if (this->gptr() >= this->pptr())
407  {
408  this->pbump(static_cast<int>(this->pbase() - this->pptr()));
409  this->gbump(static_cast<int>(this->pbase() - this->gptr()));
410  }
411  }
412  }
413  else
414  {
415  this->overflow();
416  }
417  return 0;
418  }
419 
420  public:
421 
433  struct Stream
434  {
435  Stream(streambuf_type* stream, bool cleanup = false)
436  : stream_(stream), cleanup_(cleanup)
437  {
438  }
439 
440  virtual ~Stream()
441  {
442  }
443 
444  Stream(const Stream& x)
445  : stream_(x.stream_)
446  {
447  }
448 
450  {
451  Stream tmp(x);
452  tmp.swap(*this);
453  return *this;
454  }
455 
456  void swap(Stream& x)
457  {
458  streambuf_type* stream = x.stream_;
459  bool cleanup = x.cleanup_;
460 
461  x.stream_ = this->stream_;
462  x.cleanup_ = this->cleanup_;
463 
464  this->stream_ = stream;
465  this->cleanup_ = cleanup;
466  }
467  mutable Mutex mutex_;
468  streambuf_type* stream_;
469  bool cleanup_;
470  };
471 
472  private:
473 
493  log_streambuf(const log_streambuf& x);
494 
519 
520  std::vector<Stream> m_streams;
521  Mutex m_mutex;
522  char m_buf[BUFFER_LEN];
523  };
524 
525 
539  template <typename _CharT, typename _Traits=std::char_traits<_CharT> >
541  : public std::basic_ostream<_CharT, _Traits>
542  {
543  public:
544  // Types:
545  typedef _CharT char_type;
546  typedef _Traits traits_type;
547  typedef std::basic_ostream<char_type, traits_type> ostream_type;
548  typedef std::basic_streambuf<char_type, traits_type> streambuf_type;
551 
577  log_stream(streambuf_type* sb, int levelmin, int levelmax, int level)
578  : ostream_type(sb),
579  m_minLevel(levelmin), m_maxLevel(levelmax), m_logLevel(level)
580  {
581  if (m_minLevel >= m_maxLevel) throw std::bad_alloc();
582  this->init(sb);
583  }
584 
603  virtual void header(int level)
604  {
605  return;
606  }
607 
627  bool setLevel(int level)
628  {
629  if (m_minLevel <= level && level <= m_maxLevel)
630  {
631  m_logLevel = level;
632  return true;
633  }
634  return false;
635  }
636 
656  int getLevel() const
657  {
658  return m_logLevel;
659  }
660 
676  void enableLock()
677  {
678  m_lockEnable = true;
679  }
680 
696  void disableLock()
697  {
698  m_lockEnable = false;
699  }
700 
732  ostream_type& level(int level)
733  {
734  if (m_minLevel <= level && level <= m_logLevel)
735  {
736  header(level);
737  return *this;
738  }
739  else
740  {
741  return m_dummy;
742  }
743  }
744 
769  inline bool isValid(int level) const
770  {
771  return m_minLevel <= level && level <= m_logLevel;
772  }
773 
787  inline void lock()
788  {
789  if (m_lockEnable) m_mutex.lock();
790  }
791 
805  inline void unlock()
806  {
807  if (m_lockEnable) m_mutex.unlock();
808  }
809 
810 
811  protected:
812 
829 
845  log_stream();
846 
866  log_stream(const log_stream& x);
867 
891  log_stream& operator=(const log_stream& x);
892 
893  private:
894  int m_minLevel, m_maxLevel;
895  int m_logLevel;
896 
904  std::ofstream m_dummy;
905  public:
906 
914  static bool m_lockEnable;
915 
923  static Mutex m_mutex;
924  };
925 
926  template <typename _CharT, typename _Traits >
928 
929  template <typename _CharT, typename _Traits >
931 
934 
935 };
936 #endif // LOGGER_H
void swap(Stream &x)
Definition: Logger.h:456
bool isValid(int level) const
Log level effective check.
Definition: Logger.h:769
log_streambuf template class
Definition: Logger.h:54
coil::Mutex Mutex
Definition: Logger.h:61
Mutex class.
Definition: Mutex.h:40
coil::Mutex Mutex
Definition: Logger.h:549
_Traits traits_type
Definition: Logger.h:59
_CharT char_type
Definition: Logger.h:545
virtual int sync()
override of basic_streambuf::sync
Definition: Logger.h:389
virtual ~Stream()
Definition: Logger.h:440
static Mutex m_mutex
Mutual exclusion object.
Definition: Logger.h:923
Structure for stream management.
Definition: Logger.h:433
coil::Guard< Mutex > Guard
Definition: Logger.h:550
log_stream(streambuf_type *sb, int levelmin, int levelmax, int level)
Constructor.
Definition: Logger.h:577
log_streambuf()
Constructor.
Definition: Logger.h:79
log_stream< char > LogStream
Definition: Logger.h:933
Stream(streambuf_type *stream, bool cleanup=false)
Definition: Logger.h:435
virtual std::streamsize stream_sputn(const char_type *s, std::streamsize n)
Writes up to n characters from the array pointed by s to the output sequence controlled by the stream...
Definition: Logger.h:293
std::vector< streambuf_type * > getBuffers()
Get stream buffer list.
Definition: Logger.h:196
virtual std::streamsize stream_sputn()
Write the stream buffer in stream.
Definition: Logger.h:252
coil::Guard< coil::Mutex > Guard
Definition: Logger.h:62
#define BUFFER_LEN
Definition: Logger.h:36
_CharT char_type
Definition: Logger.h:58
void addStream(streambuf_type *stream, bool cleanup=false)
Destructor.
Definition: Logger.h:136
virtual ~log_streambuf()
Destructor.
Definition: Logger.h:103
log_stream template class
Definition: Logger.h:540
Guard template class.
virtual std::streamsize xsputn(const char_type *s, std::streamsize n)
override of basic_streambuf::xsputn
Definition: Logger.h:226
_Traits traits_type
Definition: Logger.h:546
Stream & operator=(const Stream &x)
Definition: Logger.h:449
void enableLock()
Enable the lock mode.
Definition: Logger.h:676
bool setLevel(int level)
Set the log level.
Definition: Logger.h:627
std::basic_streambuf< char_type, traits_type > streambuf_type
Definition: Logger.h:548
log_streambuf< char > LogStreamBuffer
Definition: Logger.h:932
ostream_type & level(int level)
Acquire log stream.
Definition: Logger.h:732
streambuf_type * stream_
Definition: Logger.h:468
std::basic_streambuf< char_type, traits_type > streambuf_type
Definition: Logger.h:60
Stream(const Stream &x)
Definition: Logger.h:444
Mutex mutex_
Definition: Logger.h:467
virtual int overflow(int c=traits_type::eof())
override of basic_streambuf::overflow
Definition: Logger.h:322
std::basic_ostream< char_type, traits_type > ostream_type
Definition: Logger.h:547
void lock()
Acquire log lock Acquire log lock when the lock mode is set.
Definition: Logger.h:787
virtual void header(int level)
Message header appender function.
Definition: Logger.h:603
static bool m_lockEnable
Lock enable mode.
Definition: Logger.h:914
void disableLock()
Disable the lock mode.
Definition: Logger.h:696
void unlock()
Release the log lock Release the log lock when the lock mode is set.
Definition: Logger.h:805
bool removeStream(streambuf_type *stream)
Destructor.
Definition: Logger.h:163
int getLevel() const
Get the log level.
Definition: Logger.h:656
~log_stream()
Destructor.
Definition: Logger.h:828
Common Object Interface Layer.
Definition: Affinity.h:28
bool cleanup_
Definition: Logger.h:469