MessageHandler.cc
00001
00002
00003
00004
00005 #include "MessageHandler.hh"
00006 #include "Message.hh"
00007 #include <time.h>
00008 #include <cctype>
00009 #include <algorithm>
00010 #include <exception>
00011 #include <stdexcept>
00012 #ifndef SINGLETHREAD
00013 #include "boost/ref.hpp"
00014 #include "boost/thread/thread.hpp"
00015 #include "boost/thread/mutex.hpp"
00016 #include "boost/thread/condition.hpp"
00017 #endif
00018
00019 #include "ConfigHandler.hh"
00020 #include "CommandSwitchFunctions.hh"
00021
00022 namespace MessageLevelConversion{
00023 std::string EnumToString(MESSAGE_LEVEL level)
00024 {
00025 switch(level){
00026 case DEBUG3: return "DEBUG3";
00027 case DEBUG2: return "DEBUG2";
00028 case DEBUG: return "DEBUG";
00029 case INFO: return "INFO";
00030 case WARNING: return "WARNING";
00031 case ERROR: return "ERROR";
00032 case CRITICAL: return "CRITICAL";
00033 case EXCEPTION: return "EXCEPTION";
00034 default:
00035 std::cerr<<"Unknown MESSAGE_LEVEL passed: "<<(int)(level)<<"!\n";
00036 }
00037
00038 return "";
00039 }
00040
00041 void convert_to_upper(char& c){ c = std::toupper(c); }
00042
00043 MESSAGE_LEVEL StringToEnum(std::string s)
00044 {
00045
00046 std::for_each(s.begin(),s.end(),convert_to_upper);
00047
00048 if(s == "DEBUG1") s = "DEBUG";
00049 for(int i=0; i<N_MESSAGE_LEVELS; ++i){
00050 if(s == EnumToString((MESSAGE_LEVEL(i))) )
00051 return MESSAGE_LEVEL(i);
00052 }
00053
00054 MESSAGE_LEVEL newlevel =
00055 MessageHandler::GetInstance()->GetDefaultMessageThreshold();
00056 std::cerr<<"ERROR: Unknown message level "<<s
00057 <<"; setting to "<<newlevel<<"\n";
00058 return newlevel;
00059 }
00060 }
00061
00062
00063
00064 std::ostream& operator<<(std::ostream& out, const MESSAGE_LEVEL& level)
00065 {
00066 return out<<MessageLevelConversion::EnumToString(level);
00067 }
00068
00069 std::istream& operator>>(std::istream& in, MESSAGE_LEVEL& level)
00070 {
00071 std::string temp;
00072 in>>temp;
00073 level = MessageLevelConversion::StringToEnum(temp);
00074 return in;
00075 }
00076
00077 MESSAGE_LEVEL& operator++(MESSAGE_LEVEL& level)
00078 {
00079 if( level == (N_MESSAGE_LEVELS-1) )
00080 return level;
00081 else
00082 return level = (MESSAGE_LEVEL)( (int)level + 1 );
00083 }
00084
00085 MESSAGE_LEVEL& operator--(MESSAGE_LEVEL& level)
00086 {
00087 if( (int)level == 0 )
00088 return level;
00089 else
00090 return level = (MESSAGE_LEVEL)( (int)level - 1 );
00091 }
00092
00093 typedef MessageHandler::PrintToStream PrintToStream;
00094
00095
00096
00097
00098 MessageHandler MessageHandler::_instance;
00099
00100 void PrintToStream::operator()(const std::string& s, MESSAGE_LEVEL level,
00101 time_t t)
00102 {
00103 std::string color = "", header = "";
00104 if(level <= DEBUG){
00105 header = "DEBUG: ";
00106
00107 }
00108 else if(level == WARNING){
00109
00110 color = "\x1B[33m";
00111 header = "WARNING: ";
00112 }
00113 else if(level >= ERROR){
00114 color = "\x1B[31m";
00115 header = MessageLevelConversion::EnumToString(level)+": ";
00116 }
00117
00118
00119 const char* set_norm = "\x1B[0m";
00120
00121 struct tm * timeinfo;
00122 char timestamp[12];
00123 timeinfo = localtime( &t );
00124 strftime(timestamp,12,"%X ",timeinfo);
00125 if(_use_color)
00126 _stream<<color;
00127 _stream << timestamp << header << s;
00128 if(_use_color)
00129 _stream<<set_norm<<std::flush;
00130 }
00131
00132 MessageHandler::MessageHandler() : _default_threshold(INFO)
00133 {
00134 AddMessenger(INFO,PrintToStream());
00135 #ifndef SINGLETHREAD
00136 _kill_thread=false;
00137 _inbox_mutex = new boost::mutex;
00138 _message_waiting = new boost::condition_variable;
00139 _delivery_thread = new boost::thread(boost::ref(*this));
00140 #endif
00141 ConfigHandler* config = ConfigHandler::GetInstance();
00142 config->RegisterParameter("verbosity", _default_threshold,
00143 "Threshold below which messages are suppressed");
00144 config->AddCommandSwitch('v',"verbose","increment verbosity",
00145 CommandSwitch::Decrement<MESSAGE_LEVEL>
00146 (_default_threshold));
00147 config->AddCommandSwitch('q',"quiet","decrement verbosity",
00148 CommandSwitch::Increment<MESSAGE_LEVEL>
00149 (_default_threshold));
00150 config->AddCommandSwitch(' ',"verbosity","set verbosity to <level>",
00151 CommandSwitch::DefaultRead<MESSAGE_LEVEL>
00152 (_default_threshold), "level");
00153 }
00154
00155 void MessageHandler::End()
00156 {
00157 #ifndef SINGLETHREAD
00158 _kill_thread = true;
00159 _message_waiting->notify_one();
00160
00161 _delivery_thread->join();
00162 #endif
00163 }
00164
00165 MessageHandler::~MessageHandler()
00166 {
00167 End();
00168 #ifndef SINGLETHREAD
00169 delete _delivery_thread;
00170 delete _inbox_mutex;
00171 delete _message_waiting;
00172 #endif
00173 for(std::set<VMessenger*>::iterator it = _messengers.begin();
00174 it!=_messengers.end(); ++it)
00175 delete *it;
00176 _messengers.clear();
00177 }
00178
00179 void MessageHandler::RemoveMessenger(void* messenger)
00180 {
00181 VMessenger* m = (VMessenger*)messenger;
00182 if(_messengers.erase(m))
00183 delete m;
00184 }
00185
00186 void MessageHandler::SetThreshold(MESSAGE_LEVEL thresh, void* messenger)
00187 {
00188 if(messenger){
00189 VMessenger* m = (VMessenger*)messenger;
00190 if(_messengers.count(m))
00191 m->SetThreshold(thresh);
00192 else
00193 std::cerr<<"No messenger known at pointer "<<messenger<<std::endl;
00194 }
00195 else{
00196 for(std::set<VMessenger*>::iterator it = _messengers.begin();
00197 it != _messengers.end();
00198 ++it){
00199 (*it)->SetThreshold(thresh);
00200 }
00201 }
00202 }
00203
00204 void MessageHandler::Deliver(std::ostringstream* msg, MESSAGE_LEVEL level,
00205 time_t t)
00206 {
00207 for(std::set<VMessenger*>::iterator it = _messengers.begin();
00208 it != _messengers.end(); it++){
00209 if( *it != 0)
00210 (*it)->Deliver(msg, level, t);
00211 }
00212 delete msg;
00213 }
00214
00215 #ifndef SINGLETHREAD
00216
00217 void MessageHandler::Post(std::ostringstream* msg, MESSAGE_LEVEL level)
00218 {
00219 boost::unique_lock<boost::mutex> lock(*_inbox_mutex);
00220 _inbox.push( MsgData(msg,level));
00221 _message_waiting->notify_one();
00222 }
00223
00224 void MessageHandler::operator()()
00225 {
00226
00227 while(1){
00228 boost::unique_lock<boost::mutex> lock(*_inbox_mutex);
00229 while(_inbox.empty() && !_kill_thread ){
00230 _message_waiting->wait(lock);
00231
00232 }
00233 if( _kill_thread && _inbox.empty()) break;
00234
00235 MsgData next = _inbox.front();
00236 _inbox.pop();
00237 lock.unlock();
00238 Deliver(next.msg, next.level, next.t);
00239 }
00240 }
00241
00242 #else
00243 void MessageHandler::Post(std::ostringstream* msg, MESSAGE_LEVEL level)
00244 {
00245 Deliver(msg, level);
00246 }
00247 #endif