00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00033 #ifndef S3_LOGGER__H
00034 #define S3_LOGGER__H
00035
00079 #include <iostream>
00080 #include <string>
00081 #include <sstream>
00082 #include <fstream>
00083 #include <list>
00084 #include <iomanip>
00085 #include <syslog.h>
00086 #include <s3fc/s3_message.h>
00087 #include <s3fc/s3_exception.h>
00088 #include <s3fc/s3_thread_base.h>
00089 #include <s3fc/s3_conversion.h>
00090 #include <s3fc/s3_mutex.h>
00091
00092
00094 #define S3_LOG_DEFAULT_IDENT "s3_log"
00095
00096 #define S3_DEFAULT_OSTREAM_BUF_SIZE 1024
00097
00106 class s3_file_buffer : public std::filebuf
00107 {
00108 public:
00109
00118 s3_file_buffer( const std::string& filename, bool append = true )
00119 throw( s3_generic_exception )
00120 {
00121 if ( std::filebuf::open(
00122 filename.c_str(),
00123 append ? (std::ios::app | std::ios::out) :
00124 (std::ios::out) ) == 0)
00125 {
00126 throw s3_generic_exception( "s3_file_buffer::s3_file_buffer()",
00127 "file open error" );
00128 }
00129 }
00130
00131 virtual ~s3_file_buffer() {}
00132 };
00133
00134
00144 class s3_generic_streambuf : public std::streambuf
00145 {
00146 private:
00147
00149 std::vector<char> putbuffer;
00150
00155 virtual void write_to_device() = 0;
00156
00157 public:
00158
00164 s3_generic_streambuf( const unsigned int put_buffer_len =
00165 S3_DEFAULT_OSTREAM_BUF_SIZE ) :
00166 putbuffer( put_buffer_len + 1 )
00167 {
00168 setp( &putbuffer[0], &putbuffer[put_buffer_len] );
00169 }
00170
00175 virtual ~s3_generic_streambuf()
00176 {
00177
00178
00179
00180
00181
00182 }
00183
00185 virtual int overflow( int ch )
00186 {
00187 sync();
00188 if ( ch != EOF )
00189 {
00190 *pptr() = static_cast<char>( ch );
00191 pbump( 1 );
00192 }
00193 return ch;
00194 }
00195
00197 virtual int sync( void )
00198 {
00199 if ( pptr() > pbase() )
00200 {
00201 *pptr() = static_cast<char>('\0');
00202 write_to_device();
00203 setp( &putbuffer[0], &putbuffer[putbuffer.size()] );
00204 }
00205 return 0;
00206 }
00207 };
00208
00209
00218 class s3_syslog_buffer : public s3_generic_streambuf
00219 {
00220 private:
00221
00222 std::string remainder_string;
00223
00225 virtual void write_to_device()
00226 {
00227
00228
00229 std::string pbase_str( pbase() );
00230 std::string::size_type start_i = 0;
00231 std::string::size_type idx;
00232
00233 while ( ( idx = pbase_str.find( "\n", start_i ) ) != std::string::npos )
00234 {
00235 syslog( LOG_ERR, (remainder_string + pbase_str.substr( start_i, idx - start_i )).c_str() );
00236 start_i = idx + 1;
00237 remainder_string = "";
00238 }
00239 remainder_string = remainder_string +
00240 pbase_str.substr( start_i, pbase_str.length() - start_i );
00241 }
00242
00243 public:
00244
00248 s3_syslog_buffer( const unsigned int put_buffer_len =
00249 S3_DEFAULT_OSTREAM_BUF_SIZE ) :
00250 s3_generic_streambuf( put_buffer_len ),
00251 remainder_string( "" ) {}
00252
00254 virtual ~s3_syslog_buffer()
00255 {
00256 sync();
00257 }
00258 };
00259
00260
00268 class s3_syslogger : public std::ostream
00269 {
00270 protected:
00271
00273 s3_syslog_buffer logbuf;
00274
00275 public:
00276
00280 s3_syslogger() :
00281 std::ostream( &logbuf ),
00282 logbuf() {}
00283
00284 virtual ~s3_syslogger() {}
00285 };
00286
00287
00296 class s3_msgb_log_buffer : public s3_generic_streambuf
00297 {
00298 private:
00299
00301 virtual void write_to_device()
00302 {
00303 msg_box.send_msg( dest_box_name, std::string( pbase() ) );
00304 }
00305
00309 s3_message_box msg_box;
00310
00312 const std::string dest_box_name;
00313
00314 public:
00315
00334 s3_msgb_log_buffer( const std::string &my_box_name,
00335 const std::string &dst_box_name,
00336 const std::string po_ip = "",
00337 const unsigned int po_port = 0 ) :
00338 msg_box(),
00339 dest_box_name( dst_box_name )
00340 {
00341 if ( ( po_ip != "" ) && ( po_port !=0 ) )
00342 {
00343 if ( s3_message_box::initialised() == false )
00344 {
00345 s3_message_box::init( po_ip, po_port );
00346 }
00347 }
00348
00349 unsigned int try_cnt = 0;
00350 while ( true )
00351 {
00352 try
00353 {
00354 msg_box.set_name( my_box_name + "_" +
00355 s3_conversion::to_string( try_cnt ) );
00356 msg_box.connect();
00357 break;
00358 }
00359 catch ( s3_generic_exception e )
00360 {
00361 if ( std::string( e.what() ).
00362 find( "Name clash" ) != std::string::npos )
00363 {
00364 try_cnt++;
00365 }
00366 else
00367 {
00368 throw e;
00369 }
00370 }
00371 }
00372 }
00373
00375 virtual ~s3_msgb_log_buffer()
00376 {
00377 msg_box.disconnect();
00378 sync();
00379 }
00380 };
00381
00382
00390 class s3_msgb_logger : public std::ostream
00391 {
00392 protected:
00393
00395 s3_msgb_log_buffer logbuf;
00396
00397 public:
00398
00415 s3_msgb_logger( const std::string &my_box_name,
00416 const std::string &dst_box_name,
00417 const std::string po_ip = "",
00418 const unsigned int po_port = 0 ) :
00419 std::ostream( &logbuf ),
00420 logbuf( my_box_name, dst_box_name, po_ip, po_port ) {}
00421 };
00422
00423
00431 class s3_filelogger : public std::ostream
00432 {
00433 private:
00434
00436 s3_file_buffer logbuf;
00437
00438 public:
00439
00447 s3_filelogger( const std::string& filename,
00448 const bool append = true ) :
00449 std::ostream( &logbuf ),
00450 logbuf( filename, append ) {}
00451 };
00452
00453
00468 class s3_log_buffer :
00469 public s3_generic_streambuf,
00470 public std::list<std::ostream*>
00471 {
00472 private:
00473
00475 std::string ident;
00476
00478 int priority;
00479
00481 std::string priority_str;
00482
00484 s3_mutex write_lock;
00485
00487 virtual void write_to_device()
00488 {
00489 write_lock.lock();
00490
00491
00492 for ( std::list<std::ostream*>::iterator it = begin();
00493 it != end(); it++ )
00494 {
00495 **it << ident << priority_str << pbase();
00496 }
00497
00498 write_lock.unlock();
00499 }
00500
00501 bool b_append_info;
00502
00503 public:
00504
00515 s3_log_buffer( const std::string ident_arg,
00516 std::ostream *def_out = 0,
00517 const bool b_append_info_arg = true ) :
00518 ident( ident_arg ),
00519 b_append_info( b_append_info_arg )
00520 {
00521 if ( def_out == 0 )
00522 {
00523 push_back( &std::cerr );
00524 }
00525 else
00526 {
00527 push_back( def_out );
00528 }
00529
00530 s3_log_buffer::set_priority( LOG_ERR );
00531
00532 set_ident( ident_arg );
00533 }
00534
00536 virtual ~s3_log_buffer()
00537 {
00538 sync();
00539 }
00540
00542 void set_ident( const std::string &new_ident )
00543 {
00544 if ( ! b_append_info )
00545 {
00546 ident = "";
00547 return;
00548 }
00549 ident = new_ident;
00550 }
00551
00553 int get_priority( void )
00554 {
00555 return priority;
00556 }
00557
00573 void set_priority( const int new_priority )
00574 {
00575
00576 if ( ! b_append_info )
00577 {
00578 priority_str = "";
00579 return;
00580 }
00581
00582 switch( new_priority )
00583 {
00584 case LOG_EMERG:
00585 priority = new_priority;
00586 priority_str = " [emergency] ";
00587 break;
00588 case LOG_ALERT:
00589 priority = new_priority;
00590 priority_str = " [alert] ";
00591 break;
00592 case LOG_CRIT:
00593 priority = new_priority;
00594 priority_str = " [critical] ";
00595 break;
00596 case LOG_ERR:
00597 priority = new_priority;
00598 priority_str = " [error] ";
00599 break;
00600 case LOG_WARNING:
00601 priority = new_priority;
00602 priority_str = " [warning] ";
00603 break;
00604 case LOG_NOTICE:
00605 priority = new_priority;
00606 priority_str = " [notice] ";
00607 break;
00608 case LOG_INFO:
00609 priority = new_priority;
00610 priority_str = " [info] ";
00611 break;
00612 case LOG_DEBUG:
00613 priority = new_priority;
00614 priority_str = " [debug] ";
00615 break;
00616 }
00617 }
00618 };
00619
00620
00621 class s3_logger;
00622
00623 template<class TP> class s3_smanip;
00624
00625 template<class TP>
00626 inline std::ostream& operator<<( s3_logger& o, const s3_smanip<TP>& m )
00627 {
00628 return m._f( o, m._a );
00629 }
00630
00631 template<class TP>
00632 class s3_smanip
00633 {
00634 std::ostream& (*_f)( s3_logger&, TP );
00635 TP _a;
00636 public:
00637 s3_smanip( std::ostream& (*f)(s3_logger&, TP), TP a ) :
00638 _f( f ),
00639 _a( a ) {}
00640
00641 friend
00642 std::ostream& operator<< <TP>( s3_logger& o, const s3_smanip<TP>& m );
00643 };
00644
00645
00653 class s3_logger : public std::ostream
00654 {
00655 private:
00656
00658 s3_log_buffer logbuf;
00659
00660 public:
00661
00672 s3_logger( const std::string& ident_arg = S3_LOG_DEFAULT_IDENT,
00673 std::ostream *def_out = 0,
00674 const bool b_append_info_arg = true ) :
00675 std::ostream( &logbuf ),
00676 logbuf( ident_arg, def_out, b_append_info_arg ) {}
00677
00678 s3_logger(const bool b_append_info_arg) :
00679 std::ostream( &logbuf ),
00680 logbuf( S3_LOG_DEFAULT_IDENT, 0, b_append_info_arg ) {}
00681
00682
00684 ~s3_logger() {}
00685
00690 std::list<std::ostream*> &ostream_list( void )
00691 {
00692 return logbuf;
00693 }
00694
00696 std::ostream& setident( const std::string &new_ident )
00697 {
00698 logbuf.set_ident( new_ident );
00699 return *this;
00700 }
00701
00706 std::ostream& setpriority( const int new_priority )
00707 {
00708 logbuf.set_priority( new_priority );
00709 return *this;
00710 }
00711
00713 int getpriority( void )
00714 {
00715 return logbuf.get_priority();
00716 }
00717 };
00718
00719 inline extern std::ostream& __iomanip_setpriority ( s3_logger& s, int n )
00720 {
00721 return s.setpriority( n );
00722 }
00723
00724 inline s3_smanip<int> setpriority( int n )
00725 {
00726 return s3_smanip<int>( __iomanip_setpriority, n );
00727 }
00728
00729 inline extern std::ostream& __iomanip_setident ( s3_logger& s, std::string n )
00730 {
00731 return s.setident( n );
00732 }
00733
00734 inline s3_smanip<std::string> setident( std::string n )
00735 {
00736 return s3_smanip<std::string>( __iomanip_setident, n );
00737 }
00738
00739
00753 class s3_msgb_log_rx_thread : public s3_thread_base
00754 {
00755 protected:
00756
00760 s3_message_box msg_box;
00761
00763 std::ostream *ostr;
00764
00765 public:
00766
00785 s3_msgb_log_rx_thread( const std::string &my_box_name,
00786 std::ostream *ostream_arg = 0,
00787 const std::string &po_ip = "",
00788 const unsigned int po_port = 0 ) :
00789 msg_box( my_box_name )
00790 {
00791 if ( ostream_arg == 0 )
00792 {
00793 ostr = &std::cerr;
00794 }
00795 else
00796 {
00797 ostr = ostream_arg;
00798 }
00799
00800 if ( ( po_ip != "" ) && ( po_port !=0 ) )
00801 {
00802 if ( s3_message_box::initialised() == false )
00803 {
00804 s3_message_box::init( po_ip, po_port );
00805 }
00806 }
00807 msg_box.connect();
00808 msg_box.subscribe_arrival( state_changed );
00809 }
00810
00814 virtual ~s3_msgb_log_rx_thread()
00815 {
00816 msg_box.disconnect();
00817 }
00818
00822 void main_loop()
00823 {
00824
00825 bool b_terminate = false;
00826 while ( b_terminate == false )
00827 {
00828 test_cancel();
00829 wait_on_state_changed();
00830
00831
00832 s3_message msg = msg_box.get_msg();
00833 if ( msg.is_empty() == false )
00834 {
00835 if ( ostr)
00836 {
00837 *ostr << msg.get_body() << std::flush;
00838 }
00839 }
00840 }
00841 }
00842 };
00843
00844 extern s3_logger s3_log;
00845
00846 #endif // S3_LOGGER__H
00847
00848