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 //----------------------------------------------------------------------------