|
From: Christian P. <cp...@us...> - 2005-01-10 02:39:06
|
Update of /cvsroot/pclasses/pclasses2/src/App In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21795/src/App Added Files: LogChannel.cpp LogManager.cpp LogMessage.cpp LogTarget.cpp Makefile.am Log Message: Added Logging framework --- NEW FILE: LogMessage.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/App/LogMessage.h" #include "pclasses/Util/StringTool.h" namespace P { namespace App { LogMessage::LogMessage(const DateTime& when, Level l, const Unicode::String& msg) : _when(when), _level(l), _msg(msg) { } LogMessage::~LogMessage() throw() { } const DateTime& LogMessage::when() const throw() { return _when; } LogMessage::Level LogMessage::level() const throw() { return _level; } const Unicode::String& LogMessage::msg() const throw() { return _msg; } std::string LogMessage::level2Str(Level l) { std::string str = "Unknown"; switch(l) { case Debug: str = "Debug"; break; case Info: str = "Info"; break; case Notice: str = "Notice"; break; case Warning: str = "Warning"; break; case Error: str = "Error"; break; case Critical: str = "Critical"; break; } return str; } LogMessage::Level LogMessage::str2Level(const std::string& sl) { std::string str = StringTool::upperCase(sl); Level l = Info; if(str == "DEBUG") l = Debug; else if(str == "INFO") l = Info; else if(str == "NOTICE") l = Notice; else if(str == "WARNING") l = Warning; else if(str == "ERROR") l = Error; else if(str == "CRITICAL") l = Critical; return l; } } // !namespace App } // !namespace P --- NEW FILE: LogTarget.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/App/LogTarget.h" namespace P { namespace App { LogTarget::LogTarget() { } LogTarget::~LogTarget() throw() { } LogMessage::Level LogTarget::logLevel() const throw() { return _logLevel; } void LogTarget::setLogLevel(LogMessage::Level l) throw() { _logLevel = l; } } // !namespace App } // !namespace P --- NEW FILE: LogManager.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/Phoenix.h" #include "pclasses/App/LogTarget.h" #include "pclasses/App/LogChannel.h" #include "pclasses/App/LogManager.h" namespace P { namespace App { LogManager::LogManager() { } LogManager::~LogManager() throw() { // delete our LogTargets ... TargetMap::iterator ti = _targets.begin(); while(ti != _targets.end()) { delete ti->second; TargetMap::iterator del = ti; ++ti; _targets.erase(del); } // delete our LogChannels ... ChannelMap::iterator ci = _channels.begin(); while(ci != _channels.end()) { delete ci->second; ChannelMap::iterator del = ci; ++ci; _channels.erase(del); } } void LogManager::reload() throw() { for(ChannelMap::const_iterator i = _channels.begin(); i != _channels.end(); ++i) { LogChannel* channel = i->second; channel->reload(); } } LogChannel* LogManager::addChannel(const std::string& name) { LogChannel* chan = channel(name); if(!chan) { chan = new LogChannel(); _channels[name] = chan; } return chan; } bool LogManager::removeChannel(const std::string& name) { ChannelMap::iterator i = _channels.find(name); if(i != _channels.end()) { LogChannel* chan = i->second; // delete all our LogTargets for this channel ... TargetMap::iterator ti = _targets.begin(); while(ti != _targets.end()) { if(ti->first.first == chan) { delete ti->second; TargetMap::iterator del = ti; ++ti; _targets.erase(del); } else { ++ti; } } _channels.erase(i); delete chan; return true; } return false; } LogTarget* LogManager::addTarget(LogChannel* channel, const std::string& name, const std::string& type) { LogTarget* target = LogTargetFactory::instance().create(type); if(target) { if(!channel->addTarget(name, target)) { delete target; target = 0; } _targets[make_pair(channel, name)] = target; } return target; } bool LogManager::removeTarget(LogChannel* channel, const std::string& name) { TargetMap::iterator i = _targets.find(make_pair(channel, name)); if(i != _targets.end()) { LogTarget* target = channel->removeTarget(name); delete target; _targets.erase(i); return true; } return false; } LogChannel* LogManager::channel(const std::string& name) const { LogChannel* chan = 0; ChannelMap::const_iterator i = _channels.find(name); if(i != _channels.end()) chan = i->second; return chan; } LogChannel& LogManager::operator()(const std::string& chanName) { LogChannel* chan = channel(chanName); if(!chan) chan = addChannel(chanName); return *chan; } struct LogManagerContext { }; LogManager& LogManager::instance() { return Phoenix<LogManager,LogManagerContext>::instance(); } } // !namespace App } // !namespace P --- NEW FILE: Makefile.am --- INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include $(all_includes) METASOURCES = AUTO lib_LTLIBRARIES = libpclasses_app.la libpclasses_app_la_SOURCES = AppDetails.cpp LogMessage.cpp LogTarget.cpp LogChannel.cpp LogManager.cpp libpclasses_app_la_LIBADD = $(top_builddir)/src/libpclasses.la \ $(top_builddir)/src/Unicode/libpclasses_unicode.la \ $(top_builddir)/src/IO/libpclasses_io.la \ $(top_builddir)/src/System/libpclasses_system.la \ $(top_builddir)/src/Util/libpclasses_util.la --- NEW FILE: LogChannel.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/System/SystemClock.h" #include "pclasses/App/LogTarget.h" #include "pclasses/App/LogChannel.h" #include "pclasses/App/LogMessage.h" #include <sstream> namespace P { namespace App { // LogStream buffer state (kept per thread) struct LogStreamState { DateTime when; LogMessage::Level level; std::ostringstream msg; bool empty; }; class LogStreamBuffer: public std::streambuf { public: LogStreamBuffer(LogChannel& chan); ~LogStreamBuffer(); void setMessageLevel(LogMessage::Level l); // streambuf related ... int overflow(int ch); int sync(); private: LogStreamState* state(); LogChannel& _channel; LogStreamState* _state; //@fixme _state must be a thread-local variable! }; LogStreamBuffer::LogStreamBuffer(LogChannel& chan) : _channel(chan), _state(0) { } LogStreamBuffer::~LogStreamBuffer() { sync(); } LogStreamState* LogStreamBuffer::state() { if(!_state) { _state = new LogStreamState; _state->empty = true; _state->level = LogMessage::Info; } return _state; } void LogStreamBuffer::setMessageLevel(LogMessage::Level l) { LogStreamState* s = state(); if(s->level != l) { overflow(traits_type::eof()); s->level = l; } } int LogStreamBuffer::sync() { return overflow(traits_type::eof()); } int LogStreamBuffer::overflow(int ch) { // get thread-local stream state ... LogStreamState* s = state(); if(ch == traits_type::eof() || ch == '\n') { if(!s->empty) { LogMessage msg(s->when, s->level, s->msg.str()); _channel.output(msg); s->msg.str(""); s->empty = true; } } else { if(s->empty) { s->when = System::SystemClock::now(); s->empty = false; } s->msg << (char)ch; } return ch; } LogChannel::LogChannel() : std::ostream(new LogStreamBuffer(*this)) { } LogChannel::~LogChannel() throw() { _targets.clear(); delete rdbuf(); } bool LogChannel::addTarget(const std::string& name, LogTarget* target) { TargetMap::const_iterator i = _targets.find(name); if(i != _targets.end()) return false; _targets[name] = target; return true; } LogTarget* LogChannel::removeTarget(const std::string& name) throw() { LogTarget* target = 0; TargetMap::iterator i = _targets.find(name); if(i != _targets.end()) { target = i->second; _targets.erase(i); } return target; } bool LogChannel::removeTarget(LogTarget* target) throw() { for(TargetMap::iterator i = _targets.begin(); i != _targets.end(); ++i) { if(i->second == target) { _targets.erase(i); return true; } } return false; } void LogChannel::reload() const throw() { for(TargetMap::const_iterator i = _targets.begin(); i != _targets.end(); ++i) { LogTarget* target = i->second; try { target->reload(); } catch(IO::IOError& err) { } } } void LogChannel::output(const LogMessage& msg) const throw() { if(msg.level() >= _logLevel) { // output to all registered LogTargets ... for(TargetMap::const_iterator i = _targets.begin(); i != _targets.end(); ++i) { LogTarget* target = i->second; try { if(target->valid()) target->output(msg); } // close target if output() did throw catch(IO::IOError& err) { try { target->close(); } catch(...) { } } } } } LogMessage::Level LogChannel::logLevel() const throw() { return _logLevel; } void LogChannel::setLogLevel(LogMessage::Level l) throw() { _logLevel = l; } LogChannel& LogChannel::operator()(LogMessage::Level l) throw() { static_cast<LogStreamBuffer*>(rdbuf())->setMessageLevel(l); return *this; } } // !namespace App } // !namespace P |