Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

Logger.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file Logger.cpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "Logger.hpp"
00007 
00008 using namespace benzene;
00009 
00010 //----------------------------------------------------------------------------
00011 
00012 Logger::Logger()
00013     : m_streams(),
00014       m_levels()
00015 {
00016     for (int i = 0; i < MAX_THREADS; ++i)
00017         m_thread_buffer[i].id = 0;
00018     AddStream(std::cerr, LOG_LEVEL_INFO);
00019 }
00020 
00021 Logger::~Logger()
00022 {
00023 }
00024 
00025 Logger& Logger::Global()
00026 {
00027     static Logger s_global_logger;
00028     return s_global_logger;
00029 }
00030 
00031 //----------------------------------------------------------------------------
00032 
00033 void Logger::AddStream(std::ostream& stream, LogLevel level)
00034 {
00035     m_streams.push_back(&stream);
00036     m_levels.push_back(level);
00037 }
00038 
00039 void Logger::ClearStreams()
00040 {
00041     m_streams.clear();
00042     m_levels.clear();
00043 }
00044 
00045 Logger::ThreadBuffer& Logger::GetThreadBuffer()
00046 {
00047     int i;
00048     int first_empty = -1;
00049     pthread_t self = pthread_self();
00050     pthread_mutex_lock(&m_buffer_mutex);
00051     // look for a pre-existing buffer for this thread
00052     for (i = 0; i < MAX_THREADS; ++i) 
00053     {
00054         if (m_thread_buffer[i].id == self)
00055             break;
00056         else if (m_thread_buffer[i].id == 0 && first_empty == -1)
00057             first_empty = i;
00058     }
00059     if (i == MAX_THREADS)
00060     {
00061         // if one does not exist, use the first empty buffer
00062         if (first_empty != -1) 
00063         {
00064             m_thread_buffer[first_empty].id = self;
00065             i = first_empty;
00066         }
00067         else
00068         {
00069             // no free buffer... just return first buffer. This sucks!!
00070             std::cerr << "####### LOG HAS NO FREE BUFFER! #######\n";
00071             i = 0;
00072         }
00073     }
00074     pthread_mutex_unlock(&m_buffer_mutex);
00075     return m_thread_buffer[i];
00076 }
00077 
00078 void Logger::SetLevel(LogLevel level)
00079 {
00080     pthread_mutex_lock(&m_map_mutex);
00081     m_thread_level[pthread_self()] = level;
00082     pthread_mutex_unlock(&m_map_mutex);
00083 }
00084 
00085 LogLevel Logger::GetThreadLevel()
00086 {
00087     LogLevel level;
00088     pthread_mutex_lock(&m_map_mutex);    
00089     level = m_thread_level[pthread_self()];
00090     pthread_mutex_unlock(&m_map_mutex);
00091     return level;
00092 }
00093 
00094 void Logger::Flush()
00095 {
00096     ThreadBuffer& buffer = GetThreadBuffer();
00097     if (buffer.buffer.str() == "") 
00098         return;
00099 
00100     // dump msg to handlers of appropriate level; grab the
00101     // buffer mutex so no one else can do this or change the
00102     // buffers in any way. 
00103     pthread_mutex_lock(&m_buffer_mutex);
00104     for (std::size_t i = 0; i < m_streams.size(); ++i) 
00105     {
00106         LogLevel level = GetThreadLevel();
00107         if (level < m_levels[i]) 
00108             continue;
00109         std::ostream& stream = *m_streams[i];
00110         stream << std::hex << pthread_self() << " " 
00111                << LogLevelUtil::toString(level) << ": " 
00112                << buffer.buffer.str();
00113         stream.flush();
00114     }
00115 
00116     // clear buffer and set it to unused
00117     buffer.buffer.str("");
00118     buffer.id = 0;
00119     pthread_mutex_unlock(&m_buffer_mutex);
00120 }
00121 
00122 //----------------------------------------------------------------------------
00123 
00124 bool LogLevelUtil::IsValidLevel(LogLevel level)
00125 {
00126     if (level == LOG_LEVEL_ALL || level == LOG_LEVEL_FINER 
00127         || level == LOG_LEVEL_FINE || level == LOG_LEVEL_CONFIG 
00128         || level == LOG_LEVEL_INFO || level == LOG_LEVEL_WARNING 
00129         || level == LOG_LEVEL_SEVERE || level == LOG_LEVEL_OFF)
00130         return true;
00131     return false;
00132 }
00133     
00134 std::string LogLevelUtil::toString(LogLevel level)
00135 {
00136     if (level == LOG_LEVEL_ALL) return "all";
00137     if (level == LOG_LEVEL_FINER) return "finer";
00138     if (level == LOG_LEVEL_FINE) return "fine";
00139     if (level == LOG_LEVEL_CONFIG) return "config";
00140     if (level == LOG_LEVEL_INFO) return "info";
00141     if (level == LOG_LEVEL_WARNING) return "warning";
00142     if (level == LOG_LEVEL_SEVERE) return "severe";
00143     return "off";
00144 }
00145 
00146 LogLevel LogLevelUtil::fromString(std::string level)
00147 {
00148     if (level == "all") return LOG_LEVEL_ALL;
00149     if (level == "finer") return LOG_LEVEL_FINER;
00150     if (level == "fine") return LOG_LEVEL_FINE;
00151     if (level == "config") return LOG_LEVEL_CONFIG;
00152     if (level == "info") return LOG_LEVEL_INFO;
00153     if (level == "warning") return LOG_LEVEL_WARNING;
00154     if (level == "severe") return LOG_LEVEL_SEVERE;
00155     return LOG_LEVEL_OFF;
00156 }
00157 
00158 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3