lib/base/log.h

Go to the documentation of this file.
00001 
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00027 #ifndef EQBASE_LOG_H
00028 #define EQBASE_LOG_H
00029 
00030 #include <eq/base/base.h>
00031 #include <eq/base/clock.h>
00032 
00033 #include <assert.h>
00034 #include <iomanip>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <time.h>
00038 
00039 #ifdef WIN32_API
00040 #  include <process.h>
00041 #  define getpid _getpid
00042 #endif
00043 
00044 namespace eq
00045 {
00046 namespace base
00047 {
00049     enum LogLevel
00050     {
00051         LOG_ERROR = 1, 
00052         LOG_WARN,      
00053         LOG_INFO,      
00054         LOG_VERB,      
00055         LOG_ALL
00056     };
00057 
00063     enum LogTopic
00064     {
00065         LOG_CUSTOM = 0x10,       
00066         LOG_ANY    = 0xffffu     
00067     };
00068 
00070     class LogBuffer : public std::streambuf
00071     {
00072     public:
00073         LogBuffer( std::ostream& stream )
00074                 : _line(0), _indent(0), _blocked(0), _noHeader(0), 
00075                   _newLine(true), _stream(stream)
00076             {}
00077         virtual ~LogBuffer() {}
00078 
00079         void indent() { ++_indent; }
00080         void exdent() { --_indent; }
00081 
00082         void disableFlush() { ++_blocked; } // use counted variable to allow
00083         void enableFlush()                  //   nested enable/disable calls
00084             { 
00085                 assert( _blocked );// Too many enableFlush on log stream
00086                 --_blocked;
00087                 if( !_blocked ) 
00088                     pubsync();
00089             }
00090 
00091         void disableHeader() { ++_noHeader; } // use counted variable to allow
00092         void enableHeader()  { --_noHeader; } //   nested enable/disable calls
00093 
00094 #ifdef WIN32
00095         void setLogInfo( const char* subdir, const char* file, const int line )
00096             { _file = file; _line = line; } // SUBDIR not needed on WIN32
00097 #else
00098         void setLogInfo( const char* subdir, const char* file, const int line )
00099             { _file = std::string( subdir ) + '/' + file; _line = line; }
00100 #endif
00101 
00102     protected:
00103         virtual int_type overflow( LogBuffer::int_type c );
00104         
00105         virtual int sync() 
00106             {
00107                 if( !_blocked )
00108                 {
00109                     const std::string& string = _stringStream.str();
00110                     _stream.write( string.c_str(), string.length( ));
00111                     _stringStream.str( "" );
00112                 }
00113                 _newLine = true;
00114                 return 0;
00115             }
00116 
00117     private:
00118         LogBuffer( const LogBuffer& );
00119         LogBuffer& operator = ( const LogBuffer& );
00120 
00122         std::string _file;
00123 
00125         int _line;
00126 
00128         int _indent;
00129 
00131         int _blocked;
00132 
00134         int _noHeader;
00135 
00137         bool _newLine;
00138 
00140         std::ostringstream _stringStream;
00141 
00143         std::ostream& _stream;
00144     };
00145 
00147     class Log : public std::ostream
00148     {
00149     public:
00150 
00151         Log() : std::ostream( &_logBuffer ), _logBuffer( getOutput( )){}
00152         virtual ~Log() { _logBuffer.pubsync(); }
00153 
00154         void indent() { _logBuffer.indent(); }
00155         void exdent() { _logBuffer.exdent(); }
00156         void disableFlush() { _logBuffer.disableFlush(); }
00157         void enableFlush()  { _logBuffer.enableFlush();  }
00158         void forceFlush()  { _logBuffer.pubsync();  }
00159         void disableHeader() { _logBuffer.disableHeader(); }
00160         void enableHeader()  { _logBuffer.enableHeader();  }
00161 
00163         static EQ_EXPORT int level;
00164 
00166         static EQ_EXPORT unsigned topics;
00167 
00169         static EQ_EXPORT Log& instance( const char* subdir, const char* file,
00170                                         const int line );
00171 
00173         static EQ_EXPORT void exit();
00174 
00176         static std::string& getLogLevelString();
00177 
00179         static EQ_EXPORT void setOutput( std::ostream& stream );
00180 
00182         static std::ostream& getOutput ();
00183 
00192         static EQ_EXPORT void setClock( Clock* clock );
00193 
00194         void notifyPerThreadDelete() { delete this; }
00195 
00196     private:
00197         LogBuffer _logBuffer; 
00198 
00199         Log( const Log& );
00200         Log& operator = ( const Log& );
00201 
00202         void setLogInfo( const char* subdir, const char* file, const int line )
00203             { _logBuffer.setLogInfo( subdir, file, line ); }
00204 
00205     };
00206 
00211     EQ_EXPORT std::ostream& indent( std::ostream& os );
00213     EQ_EXPORT std::ostream& exdent( std::ostream& os );
00214 
00216     EQ_EXPORT std::ostream& disableFlush( std::ostream& os );
00218     EQ_EXPORT std::ostream& enableFlush( std::ostream& os );
00220     EQ_EXPORT std::ostream& forceFlush( std::ostream& os );
00221 
00223     EQ_EXPORT std::ostream& disableHeader( std::ostream& os );
00225     EQ_EXPORT std::ostream& enableHeader( std::ostream& os );
00226 
00227 #ifdef WIN32
00228 
00229     inline std::string getErrorString( const DWORD error )
00230     {
00231         char text[512] = "";
00232         FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, text, 511, 0 );
00233         const size_t length = strlen( text );
00234         if( length>2 && text[length-2] == '\r' )
00235             text[length-2] = '\0';
00236         return std::string( text );
00237     }
00239     inline std::string getLastErrorString()
00240     {
00241          return getErrorString( GetLastError( ));
00242     }
00243 #endif
00244 }
00245 }
00246 
00247 #ifndef SUBDIR
00248 #  define SUBDIR ""
00249 #endif
00250 
00252 #define EQERROR (eq::base::Log::level >= eq::base::LOG_ERROR) &&    \
00253     eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00254 
00255 #define EQWARN  (eq::base::Log::level >= eq::base::LOG_WARN)  &&    \
00256     eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00257 
00258 #define EQINFO  (eq::base::Log::level >= eq::base::LOG_INFO)  &&    \
00259     eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00260 
00261 #define EQVERB  (eq::base::Log::level >= eq::base::LOG_VERB)  &&    \
00262     eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00263 
00265 #define EQLOG(topic)  (eq::base::Log::topics & (topic))  &&  \
00266     eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00267 
00268 #endif //EQBASE_LOG_H
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8