00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*- 00002 //---------------------------------------------------------------------- 00009 //---------------------------------------------------------------------- 00010 #include "LogStream.h" 00011 00012 #include <assert.h> 00013 #include <iostream> 00014 00015 #include "icl_core/os_lxrt.h" 00016 #include "icl_core/os_string.h" 00017 #include "icl_core_logging/LoggingManager.h" 00018 #include "icl_core_logging/LogOutputStream.h" 00019 #include "icl_core_logging/ThreadStream.h" 00020 00021 namespace icl_core { 00022 namespace logging { 00023 00024 ThreadId LogStream::m_empty_thread_id(0); 00025 00026 LogStream::LogStream(const std::string& name, icl_core::logging::LogLevel initial_level) 00027 : m_initial_level(initial_level), 00028 m_name(name), 00029 m_active(true), 00030 m_mutex(1) 00031 { 00032 LoggingManager::instance().assertInitialized(); 00033 00034 for (size_t i = 0; i < cDEFAULT_LOG_THREAD_STREAM_POOL_SIZE; ++i) 00035 { 00036 m_thread_stream_map.push_back(ThreadStreamInfo(m_empty_thread_id, eLL_MUTE, 00037 new icl_core::logging::ThreadStream(this))); 00038 } 00039 } 00040 00041 LogStream::~LogStream() 00042 { 00043 LoggingManager::instance().removeLogStream(m_name); 00044 00045 ThreadStreamMap::const_iterator it = m_thread_stream_map.begin(); 00046 for (; it != m_thread_stream_map.end(); ++it) 00047 { 00048 delete it->thread_stream; 00049 } 00050 m_thread_stream_map.clear(); 00051 } 00052 00053 icl_core::logging::LogLevel LogStream::getLogLevel() const 00054 { 00055 // TODO: Implement individual log levels for each thread. 00056 return m_initial_level; 00057 } 00058 00059 void LogStream::addOutputStream(LogOutputStream *new_stream) 00060 { 00061 if (m_mutex.wait()) 00062 { 00063 m_output_stream_list.insert(new_stream); 00064 m_mutex.post(); 00065 } 00066 } 00067 00068 void LogStream::removeOutputStream(LogOutputStream *stream) 00069 { 00070 if (m_mutex.wait()) 00071 { 00072 m_output_stream_list.erase(stream); 00073 m_mutex.post(); 00074 } 00075 } 00076 00077 icl_core::logging::ThreadStream& LogStream::threadStream(icl_core::logging::LogLevel log_level) 00078 { 00079 icl_core::logging::ThreadStream *thread_stream = NULL; 00080 00081 while (!m_mutex.wait()) 00082 { } 00083 00084 ThreadId thread_id = icl_core::os::threadSelf(); 00085 00086 // Try to find the stream for the current thread, if it has already been assigned. 00087 for (ThreadStreamMap::const_iterator find_it = m_thread_stream_map.begin(); 00088 find_it != m_thread_stream_map.end(); ++find_it) 00089 { 00090 if (find_it->thread_id == thread_id && find_it->log_level == log_level) 00091 { 00092 thread_stream = find_it->thread_stream; 00093 break; 00094 } 00095 } 00096 00097 // Take a thread stream from the pool, if one is available. 00098 if (thread_stream == NULL) 00099 { 00100 for (ThreadStreamMap::iterator find_it = m_thread_stream_map.begin(); 00101 find_it != m_thread_stream_map.end(); ++find_it) 00102 { 00103 if (find_it->thread_id == m_empty_thread_id) 00104 { 00105 find_it->thread_id = thread_id; 00106 find_it->log_level = log_level; 00107 thread_stream = find_it->thread_stream; 00108 break; 00109 } 00110 } 00111 } 00112 00113 // There are no more threads streams available, so create a new one. 00114 if (thread_stream == NULL) 00115 { 00116 #ifdef _SYSTEM_LXRT_ 00117 // Leave hard real-time to create a new thread stream. 00118 bool re_enter_hrt = false; 00119 if (icl_core::os::isThisHRT()) 00120 { 00121 icl_core::os::ensureNoHRT(); 00122 re_enter_hrt = true; 00123 } 00124 #endif 00125 thread_stream = new icl_core::logging::ThreadStream(this); 00126 m_thread_stream_map.push_back(ThreadStreamInfo(thread_id, log_level, thread_stream)); 00127 #ifdef _SYSTEM_LXRT_ 00128 if (re_enter_hrt) 00129 { 00130 icl_core::os::makeHRT(); 00131 } 00132 #endif 00133 } 00134 00135 m_mutex.post(); 00136 00137 // Set the log level for the thread stream. 00138 thread_stream->changeLevel(this->getLogLevel()); 00139 00140 return *thread_stream; 00141 } 00142 00143 void LogStream::printConfiguration() const 00144 { 00145 for (std::set<LogOutputStream*>::const_iterator it = m_output_stream_list.begin(); 00146 it != m_output_stream_list.end(); ++it) 00147 { 00148 std::cerr << (*it)->name() << " "; 00149 } 00150 } 00151 00153 #ifdef _IC_BUILDER_DEPRECATED_STYLE_ 00154 00158 icl_core::String LogStream::Name() const 00159 { 00160 return name(); 00161 } 00162 00163 const char *LogStream::NameCStr() const 00164 { 00165 return nameCStr(); 00166 } 00167 00171 void LogStream::SetActive(bool active) 00172 { 00173 setActive(active); 00174 } 00175 00179 icl_core::logging::LogLevel LogStream::InitialLogLevel() const 00180 { 00181 return initialLogLevel(); 00182 } 00183 00187 bool LogStream::IsActive() const 00188 { 00189 return isActive(); 00190 } 00191 00192 ICL_CORE_VC_DEPRECATE_STYLE_USE(LogStream::getLogLevel) 00193 icl_core::logging::LogLevel LogStream::LogLevel() const 00194 { 00195 return getLogLevel(); 00196 } 00197 00202 void LogStream::AddOutputStream(LogOutputStream *new_stream) 00203 { 00204 addOutputStream(new_stream); 00205 } 00206 00211 void LogStream::RemoveOutputStream(LogOutputStream *stream) 00212 { 00213 removeOutputStream(stream); 00214 } 00215 00219 void LogStream::PrintConfiguration() const 00220 { 00221 printConfiguration(); 00222 } 00223 00229 ICL_CORE_VC_DEPRECATE_STYLE 00230 icl_core::logging::ThreadStream& LogStream::ThreadStream(icl_core::logging::LogLevel log_level) 00231 { 00232 return threadStream(log_level); 00233 } 00234 00235 #endif 00236 00237 00238 00239 void LogStream::releaseThreadStream(icl_core::logging::ThreadStream *thread_stream) 00240 { 00241 for (ThreadStreamMap::iterator find_it = m_thread_stream_map.begin(); 00242 find_it != m_thread_stream_map.end(); ++find_it) 00243 { 00244 if (find_it->thread_stream == thread_stream) 00245 { 00246 find_it->thread_id = m_empty_thread_id; 00247 break; 00248 } 00249 } 00250 } 00251 00252 } 00253 }