ISIS Core Library 0.7.2 (api 3.0.0)
|
00001 // 00002 // C++ Implementation: message 00003 // 00004 // Description: 00005 // 00006 // 00007 // Author: Enrico Reimer<reimer@cbs.mpg.de>, (C) 2008 00008 // 00009 // Copyright: See COPYING file that comes with this distribution 00010 // 00011 // 00012 00013 #include "message.hpp" 00014 #include "common.hpp" 00015 #include <sys/types.h> 00016 00017 #include <boost/date_time/posix_time/posix_time.hpp> //we need the to_string functions for the automatic conversion 00018 00019 #ifndef WIN32 00020 #include <signal.h> 00021 #endif 00022 00023 namespace isis 00024 { 00025 namespace util 00026 { 00027 namespace _internal 00028 { 00029 struct IsEqualMsg { 00030 std::string newMsg; 00031 bool operator()( const std::pair<boost::posix_time::ptime, std::string>& ms ) {return ms.second == newMsg;} 00032 }; 00033 } 00034 const char *logLevelName( LogLevel level ) 00035 { 00036 switch( level ) { 00037 case error: 00038 return "error"; 00039 case warning: 00040 return "warning"; 00041 case notice: 00042 return "notice"; 00043 case info: 00044 return "info"; 00045 case verbose_info: 00046 return "verbose"; 00047 } 00048 00049 return "//no_log//"; 00050 } 00051 00052 void MessageHandlerBase::stopBelow( LogLevel stop ) 00053 { 00054 #ifdef WIN32 00055 LOG( Debug, error ) << "Sorry stopping is not supported on Win32"; 00056 return; 00057 #endif 00058 #ifdef NDEBUG 00059 LOG( Debug, error ) << "Wont apply stopping because NDEBUG is set"; 00060 return; 00061 #endif 00062 m_stop_below = stop; 00063 } 00064 00065 bool MessageHandlerBase::requestStop( LogLevel _level ) 00066 { 00067 if ( m_stop_below > _level ) { 00068 #ifdef WIN32 00069 return false; 00070 #else 00071 return kill( getpid(), SIGTSTP ) == 0; 00072 #endif 00073 } else 00074 return false; 00075 } 00076 00077 std::string Message::strTime()const 00078 { 00079 return boost::posix_time::to_simple_string( m_timeStamp ); 00080 } 00081 00082 Message::Message( std::string object, std::string module, std::string file, int line, LogLevel level, boost::weak_ptr<MessageHandlerBase> _commitTo ) 00083 : commitTo( _commitTo ), 00084 m_object( object ), 00085 m_module( module ), 00086 m_file( file ), 00087 m_timeStamp( boost::posix_time::microsec_clock::universal_time() ), 00088 m_line( line ), 00089 m_level( level ) 00090 {} 00091 00092 Message::Message( const Message &src ) //we need a custom copy-constructor, because the copy-contructor of ostringstream is private 00093 : std::ostringstream( src.str() ), 00094 commitTo( src.commitTo ), 00095 m_object( src.m_object ), 00096 m_module( src.m_module ), 00097 m_file( src.m_file ), 00098 m_subjects( src.m_subjects ), 00099 m_timeStamp( src.m_timeStamp ), 00100 m_line( src.m_line ), 00101 m_level( src.m_level ) 00102 {} 00103 00104 Message::~Message() 00105 { 00106 if ( shouldCommit() ) { 00107 commitTo.lock()->commit( *this ); 00108 str( "" ); 00109 clear(); 00110 commitTo.lock()->requestStop( m_level ); 00111 } 00112 } 00113 00114 00115 std::string Message::merge()const 00116 { 00117 std::string ret( str() ); 00118 size_t found = std::string::npos; 00119 std::list<std::string>::const_iterator subj = m_subjects.begin(); 00120 00121 if ( ( found = ret.find( "{o}" ) ) != std::string::npos ) 00122 ret.replace( found, 3, m_object ); 00123 00124 found = 0; 00125 00126 while ( ( found = ret.find( "{s}", found ) ) != std::string::npos ) 00127 ret.replace( found, 3, std::string( "\"" ) + * ( subj++ ) + "\"" ); 00128 00129 return ret; 00130 } 00131 00132 bool Message::shouldCommit()const 00133 { 00134 if( str().empty() ) 00135 return false; 00136 00137 const boost::shared_ptr<MessageHandlerBase> buff( commitTo.lock() ); 00138 00139 if ( buff ) 00140 return ( buff->m_level >= m_level ); 00141 else return false; 00142 } 00143 00144 LogLevel MessageHandlerBase::m_stop_below = error; 00145 00146 00147 std::ostream *DefaultMsgPrint::o = &::std::cerr; 00148 void DefaultMsgPrint::commit( const Message &mesg ) 00149 { 00150 //first remove everything which is to old anyway 00151 std::list< std::pair<boost::posix_time::ptime, std::string> >::iterator begin = last.begin(); 00152 static const boost::posix_time::millisec dist( max_age ); 00153 00154 while( begin != last.end() && begin->first + dist < mesg.m_timeStamp ) { 00155 begin++; 00156 last.pop_front(); 00157 } 00158 00159 const _internal::IsEqualMsg isEqual = {mesg.str()}; 00160 00161 begin = std::find_if( last.begin(), last.end(), isEqual ); 00162 00163 if( begin == last.end() ) { // its not in the list of the last xxx milliseconds - so print it 00164 *o << mesg.m_module << ":" << logLevelName( mesg.m_level ); 00165 #ifndef NDEBUG //if with debug-info 00166 *o << "[" << mesg.m_file.leaf() << ":" << mesg.m_line << "] "; //print the file and the line 00167 #else 00168 *o << "[" << mesg.m_object << "] "; //print the object/method 00169 #endif //NDEBUG 00170 *o << mesg.merge(); //print the message itself 00171 *o << std::endl; 00172 } else { 00173 last.erase( begin ); // it was in the list - remove it 00174 } 00175 00176 last.push_back( std::make_pair( mesg.m_timeStamp, mesg.str() ) ); // put new message on the top 00177 } 00178 00179 void DefaultMsgPrint::setStream( ::std::ostream &_o ) 00180 { 00181 o->flush(); 00182 o = &_o; 00183 } 00184 00185 } 00186 }