00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*- 00002 00003 // -- BEGIN LICENSE BLOCK ---------------------------------------------- 00004 // This file is part of FZIs ic_workspace. 00005 // 00006 // This program is free software licensed under the LGPL 00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3). 00008 // You can find a copy of this license in LICENSE folder in the top 00009 // directory of the source code. 00010 // 00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany 00012 // 00013 // -- END LICENSE BLOCK ------------------------------------------------ 00014 00015 //---------------------------------------------------------------------- 00022 //---------------------------------------------------------------------- 00023 #include "LogStream.h" 00024 00025 #include <assert.h> 00026 #include <iostream> 00027 00028 #include "icl_core/os_lxrt.h" 00029 #include "icl_core/os_string.h" 00030 #include "icl_core_logging/LoggingManager.h" 00031 #include "icl_core_logging/LogOutputStream.h" 00032 #include "icl_core_logging/ThreadStream.h" 00033 00034 namespace icl_core { 00035 namespace logging { 00036 00037 ThreadId LogStream::m_empty_thread_id(0); 00038 00039 LogStream::LogStream(const std::string& name, icl_core::logging::LogLevel initial_level) 00040 : m_initial_level(initial_level), 00041 m_name(name), 00042 m_active(true), 00043 m_mutex(1) 00044 { 00045 LoggingManager::instance().assertInitialized(); 00046 00047 for (size_t i = 0; i < cDEFAULT_LOG_THREAD_STREAM_POOL_SIZE; ++i) 00048 { 00049 m_thread_stream_map.push_back(ThreadStreamInfo(m_empty_thread_id, eLL_MUTE, 00050 new icl_core::logging::ThreadStream(this))); 00051 } 00052 } 00053 00054 LogStream::~LogStream() 00055 { 00056 LoggingManager::instance().removeLogStream(m_name); 00057 00058 ThreadStreamMap::const_iterator it = m_thread_stream_map.begin(); 00059 for (; it != m_thread_stream_map.end(); ++it) 00060 { 00061 delete it->thread_stream; 00062 } 00063 m_thread_stream_map.clear(); 00064 } 00065 00066 icl_core::logging::LogLevel LogStream::getLogLevel() const 00067 { 00068 // TODO: Implement individual log levels for each thread. 00069 return m_initial_level; 00070 } 00071 00072 void LogStream::addOutputStream(LogOutputStream *new_stream) 00073 { 00074 if (m_mutex.wait()) 00075 { 00076 m_output_stream_list.insert(new_stream); 00077 m_mutex.post(); 00078 } 00079 } 00080 00081 void LogStream::removeOutputStream(LogOutputStream *stream) 00082 { 00083 if (m_mutex.wait()) 00084 { 00085 m_output_stream_list.erase(stream); 00086 m_mutex.post(); 00087 } 00088 } 00089 00090 icl_core::logging::ThreadStream& LogStream::threadStream(icl_core::logging::LogLevel log_level) 00091 { 00092 icl_core::logging::ThreadStream *thread_stream = NULL; 00093 00094 while (!m_mutex.wait()) 00095 { } 00096 00097 ThreadId thread_id = icl_core::os::threadSelf(); 00098 00099 // Try to find the stream for the current thread, if it has already been assigned. 00100 for (ThreadStreamMap::const_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 == thread_id && find_it->log_level == log_level) 00104 { 00105 thread_stream = find_it->thread_stream; 00106 break; 00107 } 00108 } 00109 00110 // Take a thread stream from the pool, if one is available. 00111 if (thread_stream == NULL) 00112 { 00113 for (ThreadStreamMap::iterator find_it = m_thread_stream_map.begin(); 00114 find_it != m_thread_stream_map.end(); ++find_it) 00115 { 00116 if (find_it->thread_id == m_empty_thread_id) 00117 { 00118 find_it->thread_id = thread_id; 00119 find_it->log_level = log_level; 00120 thread_stream = find_it->thread_stream; 00121 break; 00122 } 00123 } 00124 } 00125 00126 // There are no more threads streams available, so create a new one. 00127 if (thread_stream == NULL) 00128 { 00129 #ifdef _SYSTEM_LXRT_ 00130 // Leave hard real-time to create a new thread stream. 00131 bool re_enter_hrt = false; 00132 if (icl_core::os::isThisHRT()) 00133 { 00134 icl_core::os::ensureNoHRT(); 00135 re_enter_hrt = true; 00136 } 00137 #endif 00138 thread_stream = new icl_core::logging::ThreadStream(this); 00139 m_thread_stream_map.push_back(ThreadStreamInfo(thread_id, log_level, thread_stream)); 00140 #ifdef _SYSTEM_LXRT_ 00141 if (re_enter_hrt) 00142 { 00143 icl_core::os::makeHRT(); 00144 } 00145 #endif 00146 } 00147 00148 m_mutex.post(); 00149 00150 // Set the log level for the thread stream. 00151 thread_stream->changeLevel(this->getLogLevel()); 00152 00153 return *thread_stream; 00154 } 00155 00156 void LogStream::printConfiguration() const 00157 { 00158 for (std::set<LogOutputStream*>::const_iterator it = m_output_stream_list.begin(); 00159 it != m_output_stream_list.end(); ++it) 00160 { 00161 std::cerr << (*it)->name() << " "; 00162 } 00163 } 00164 00166 #ifdef _IC_BUILDER_DEPRECATED_STYLE_ 00167 00171 icl_core::String LogStream::Name() const 00172 { 00173 return name(); 00174 } 00175 00176 const char *LogStream::NameCStr() const 00177 { 00178 return nameCStr(); 00179 } 00180 00184 void LogStream::SetActive(bool active) 00185 { 00186 setActive(active); 00187 } 00188 00192 icl_core::logging::LogLevel LogStream::InitialLogLevel() const 00193 { 00194 return initialLogLevel(); 00195 } 00196 00200 bool LogStream::IsActive() const 00201 { 00202 return isActive(); 00203 } 00204 00205 ICL_CORE_VC_DEPRECATE_STYLE_USE(LogStream::getLogLevel) 00206 icl_core::logging::LogLevel LogStream::LogLevel() const 00207 { 00208 return getLogLevel(); 00209 } 00210 00215 void LogStream::AddOutputStream(LogOutputStream *new_stream) 00216 { 00217 addOutputStream(new_stream); 00218 } 00219 00224 void LogStream::RemoveOutputStream(LogOutputStream *stream) 00225 { 00226 removeOutputStream(stream); 00227 } 00228 00232 void LogStream::PrintConfiguration() const 00233 { 00234 printConfiguration(); 00235 } 00236 00242 ICL_CORE_VC_DEPRECATE_STYLE 00243 icl_core::logging::ThreadStream& LogStream::ThreadStream(icl_core::logging::LogLevel log_level) 00244 { 00245 return threadStream(log_level); 00246 } 00247 00248 #endif 00249 00250 00251 00252 void LogStream::releaseThreadStream(icl_core::logging::ThreadStream *thread_stream) 00253 { 00254 for (ThreadStreamMap::iterator find_it = m_thread_stream_map.begin(); 00255 find_it != m_thread_stream_map.end(); ++find_it) 00256 { 00257 if (find_it->thread_stream == thread_stream) 00258 { 00259 find_it->thread_id = m_empty_thread_id; 00260 break; 00261 } 00262 } 00263 } 00264 00265 } 00266 }