log.cpp

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 
00018 #include <pthread.h>
00019 
00020 #include "log.h"
00021 #include "perThread.h"
00022 #include "thread.h"
00023 
00024 using namespace std;
00025 
00026 #ifdef WIN32_VC
00027 #  define atoll _atoi64
00028 #endif
00029 
00030 
00031 namespace eq
00032 {
00033 namespace base
00034 {
00035 
00036 static int      getLogLevel();
00037 static unsigned getLogTopics();
00038 
00039 namespace
00040 {
00041 class LogTable
00042 {
00043 public:
00044     LogTable( const LogLevel _level, const string& _name )
00045             : level( _level ), name( _name ) {}
00046 
00047     LogLevel level;
00048     string   name;
00049 };
00050 
00051 #define LOG_TABLE_ENTRY( name ) LogTable( LOG_ ## name, string( #name ))
00052 #define LOG_TABLE_SIZE (5)
00053 
00054 static LogTable _logTable[ LOG_TABLE_SIZE ] =
00055 {
00056     LOG_TABLE_ENTRY( ERROR ),
00057     LOG_TABLE_ENTRY( WARN ),
00058     LOG_TABLE_ENTRY( INFO ),
00059     LOG_TABLE_ENTRY( VERB ),
00060     LOG_TABLE_ENTRY( ALL )
00061 };
00062 }
00063 
00064 int        Log::level  = getLogLevel();
00065 unsigned   Log::topics = getLogTopics();
00066 Clock      _defaultClock;
00067 Clock*     _clock = &_defaultClock;
00068 
00069 static PerThread< Log > _logInstance;
00070 
00071 #ifdef NDEBUG
00072     static std::ostream* _logStream = &std::cout;
00073 #else
00074     static std::ostream* _logStream = &std::cerr;
00075 #endif
00076 
00077 int getLogLevel()
00078 {
00079     const char *env = getenv("EQ_LOG_LEVEL");
00080     if( env )
00081     {
00082         const int level = atoi( env );
00083         if( level )
00084             return level;
00085 
00086         const string envString( env );
00087         for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
00088             if( _logTable[i].name == envString )
00089                 return _logTable[i].level;
00090     }
00091 
00092 #ifdef NDEBUG
00093     return LOG_WARN;
00094 #else
00095     return LOG_INFO;
00096 #endif
00097 }
00098 
00099 std::string& Log::getLogLevelString()
00100 {
00101     for( uint32_t i=0; i<LOG_TABLE_SIZE; ++i )
00102         if( _logTable[i].level == level )
00103                 return _logTable[i].name;
00104 
00105     return _logTable[0].name;
00106 }
00107 
00108 unsigned getLogTopics()
00109 {
00110     const char *env = getenv("EQ_LOG_TOPICS");
00111     if( env )
00112         return atoll(env);
00113 
00114     if( getLogLevel() == LOG_ALL )
00115         return 0xffffffffu;
00116 
00117     return 0;
00118 }
00119 
00120 Log& Log::instance( const char* subdir, const char* file,
00121                               const int line )
00122 {
00123     Log* log = _logInstance.get();
00124     if( !log )
00125     {
00126         log = new Log();
00127         _logInstance = log;
00128     }
00129 
00130     log->setLogInfo( subdir, file, line );
00131     return *log;
00132 }
00133 
00134 void Log::exit()
00135 {
00136     Log* log = _logInstance.get();
00137     _logInstance = 0;
00138     delete log;
00139 }
00140 
00141 void Log::setOutput( std::ostream& stream )
00142 {
00143     _logStream = &stream;
00144     exit();
00145 }
00146 
00147 void Log::setClock( Clock* clock )
00148 {
00149     if( clock )
00150         _clock = clock;
00151     else
00152         _clock = &_defaultClock;
00153 }
00154 
00155 std::ostream& Log::getOutput()
00156 {
00157     return *_logStream;
00158 }
00159 
00160 
00161 LogBuffer::int_type LogBuffer::overflow( LogBuffer::int_type c )
00162 {
00163     if( c == EOF )
00164         return EOF;
00165 
00166     if( _newLine )
00167     {
00168         if( !_noHeader )
00169         {
00170             _stringStream << getpid()  << " " 
00171                           << eq::base::Thread::getSelfThreadID()
00172                           << " " << _file << ":" << _line << " ";
00173 
00174             const int prec = _stringStream.precision();
00175 
00176             _stringStream.precision( 5 );
00177             _stringStream << std::setw(5) << (_clock->getTime64() % 100000)
00178                           << " ";
00179             _stringStream.precision( prec );
00180         }
00181 
00182         for( int i=0; i<_indent; ++i )
00183             _stringStream << "    ";
00184         _newLine = false;
00185     }
00186 
00187     _stringStream << (char)c;
00188     return c;
00189 }
00190 
00191 
00192 std::ostream& indent( std::ostream& os )
00193 {
00194     Log* log = dynamic_cast<Log*>(&os);
00195     if( log )
00196         log->indent();
00197     return os;
00198 }
00199 std::ostream& exdent( std::ostream& os )
00200 {
00201     Log* log = dynamic_cast<Log*>(&os);
00202     if( log )
00203         log->exdent();
00204         return os;
00205 }
00206 
00207 std::ostream& disableFlush( std::ostream& os )
00208 {
00209     Log* log = dynamic_cast<Log*>(&os);
00210     if( log )
00211         log->disableFlush();
00212     return os;
00213 }
00214 std::ostream& enableFlush( std::ostream& os )
00215 {
00216     Log* log = dynamic_cast<Log*>(&os);
00217     if( log )
00218         log->enableFlush();
00219     return os;
00220 }
00221 std::ostream& forceFlush( std::ostream& os )
00222 {
00223     Log* log = dynamic_cast<Log*>(&os);
00224     if( log )
00225         log->forceFlush();
00226     return os;
00227 }
00228 
00229 std::ostream& disableHeader( std::ostream& os )
00230 {
00231     Log* log = dynamic_cast<Log*>(&os);
00232     if( log )
00233         log->disableHeader();
00234     return os;
00235 }
00236 std::ostream& enableHeader( std::ostream& os )
00237 {
00238     Log* log = dynamic_cast<Log*>(&os);
00239     if( log )
00240         log->enableHeader();
00241     return os;
00242 }
00243 
00244 }
00245 }
Generated on Mon Aug 10 18:58:40 2009 for Equalizer 0.9 by  doxygen 1.5.8