From: g0dil Date: Mon, 29 Oct 2007 17:24:57 +0000 (+0000) Subject: Utils/Logger: Complete route caching X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=f6f670f2dbc82b77db29df6cd452f2b351b9662a;p=senf.git Utils/Logger: Complete route caching git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@478 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Logger/AreaRegistry.cc b/Utils/Logger/AreaRegistry.cc new file mode 100644 index 0000000..48c9eaa --- /dev/null +++ b/Utils/Logger/AreaRegistry.cc @@ -0,0 +1,113 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer NETwork research (NET) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU 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 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. + +/** \file + \brief AreaRegistry non-inline non-template implementation */ + +#include "AreaRegistry.hh" +#include "AreaRegistry.ih" + +// Custom includes +#include "Target.hh" + +//#include "AreaRegistry.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::log::detail::AreaBase + +prefix_ void senf::log::detail::AreaBase::updateRoutingCache(Target & target, + StreamBase const & stream, + unsigned limit) + const +{ + if (stream.index >= routingCache_.size()) + routingCache_.resize(stream.index+1); + unsigned l (limit); + Routes::iterator i (routingCache_[stream.index].routes.begin()); + Routes::iterator const i_end (routingCache_[stream.index].routes.end()); + for (; i != i_end; ++i) { + if (i->target == &target) { + i->limit = limit; + break; + } + if (i->limit < l) + l = i->limit; + } + if (i == i_end) + routingCache_[stream.index].routes.push_back(RouteEntry(limit, &target)); + else + for (; i != i_end; ++i) + if (i->limit < l) + l = i->limit; + routingCache_[stream.index].limit = l; +} + +prefix_ void senf::log::detail::AreaBase::removeRoutingCache(Target & target, + StreamBase const & stream) + const +{ + if (stream.index >= routingCache_.size()) + return; + unsigned l (DISABLED::value); + Routes::iterator i (routingCache_[stream.index].routes.begin()); + Routes::iterator const i_end (routingCache_[stream.index].routes.end()); + while (i != i_end) { + if (i->target == &target) + i = routingCache_[stream.index].routes.erase(i); + else { + if (i->limit < l) + l = i->limit; + ++i; + } + } + routingCache_[stream.index].limit = l; +} + +prefix_ void senf::log::detail::AreaBase::write(boost::posix_time::ptime timestamp, + StreamBase const & stream, unsigned level, + std::string msg) + const +{ + if (stream.index >= routingCache_.size()) + return; + Routes::iterator i (routingCache_[stream.index].routes.begin()); + Routes::iterator const i_end (routingCache_[stream.index].routes.end()); + for (; i != i_end; ++i) + i->target->write(timestamp, stream, *this, level, msg); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "AreaRegistry.mpp" + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/Utils/Logger/AreaRegistry.cci b/Utils/Logger/AreaRegistry.cci index fa19ed5..0d9eb37 100644 --- a/Utils/Logger/AreaRegistry.cci +++ b/Utils/Logger/AreaRegistry.cci @@ -61,6 +61,13 @@ prefix_ void senf::log::AreaRegistry::registerArea(detail::AreaBase const & area registry_.insert( std::make_pair(area.v_name(), &area) ); } +prefix_ senf::log::detail::AreaBase const * +senf::log::AreaRegistry::lookup(std::string const & name) +{ + Registry::iterator i (registry_.find(name)); + return i == registry_.end() ? 0 : i->second; +} + /////////////////////////////////////////////////////////////////////////// // senf::log::detail::AreaBase @@ -81,18 +88,11 @@ prefix_ void senf::log::detail::AreaBase::init() senf::log::AreaRegistry::instance().registerArea(*this); } -prefix_ unsigned senf::log::detail::AreaBase::streamLimit(StreamBase const & stream) - const -{ - return stream.index >= streamLimits_.size() ? DISABLED::value : streamLimits_[stream.index]; -} - -prefix_ void senf::log::detail::AreaBase::setStreamLimit(StreamBase const & stream, unsigned value) +prefix_ unsigned senf::log::detail::AreaBase::limit(StreamBase const & stream) const { - if (stream.index >= streamLimits_.size()) - streamLimits_.resize(stream.index+1,0u); - streamLimits_[stream.index] = value; + return stream.index >= routingCache_.size() ? + DISABLED::value : routingCache_[stream.index].limit; } ///////////////////////////////cci.e/////////////////////////////////////// diff --git a/Utils/Logger/AreaRegistry.hh b/Utils/Logger/AreaRegistry.hh index 6dd3d30..8decd55 100644 --- a/Utils/Logger/AreaRegistry.hh +++ b/Utils/Logger/AreaRegistry.hh @@ -78,6 +78,7 @@ namespace log { AreaRegistry(); void registerArea(detail::AreaBase const & area); + detail::AreaBase const * lookup(std::string const & name); Registry registry_; diff --git a/Utils/Logger/AreaRegistry.ih b/Utils/Logger/AreaRegistry.ih index 362c3f6..e8773fe 100644 --- a/Utils/Logger/AreaRegistry.ih +++ b/Utils/Logger/AreaRegistry.ih @@ -29,11 +29,17 @@ // Custom includes #include #include +#include +#include +#include "Levels.hh" ///////////////////////////////ih.p//////////////////////////////////////// namespace senf { namespace log { + + class Target; + namespace detail { class StreamBase; @@ -48,13 +54,26 @@ namespace detail { void init(); - unsigned streamLimit(StreamBase const & stream) const; - void setStreamLimit(StreamBase const & stream, unsigned value) const; + unsigned limit(StreamBase const & stream) const; + void updateRoutingCache(Target & target, StreamBase const & stream, unsigned limit) const; + void removeRoutingCache(Target & target, StreamBase const & stream) const; + void write(boost::posix_time::ptime timestamp, StreamBase const & stream, unsigned level, + std::string msg) const; private: - typedef std::vector StreamLimits; - // mutable since this is a cache and may therefore change at unexpected places ... - mutable StreamLimits streamLimits_; + struct RouteEntry { + RouteEntry(unsigned limit_, Target * target_) : limit(limit_), target(target_) {} + unsigned limit; + Target * target; + }; + typedef std::list Routes; + struct CacheEntry { + CacheEntry() : limit (DISABLED::value), routes() {} + unsigned limit; + Routes routes; + }; + typedef std::vector RoutingCache; + mutable RoutingCache routingCache_; }; }}} diff --git a/Utils/Logger/Config.hh b/Utils/Logger/Config.hh index 27a9af8..cd0186a 100644 --- a/Utils/Logger/Config.hh +++ b/Utils/Logger/Config.hh @@ -46,12 +46,6 @@ Runtime configuration on the other hand deals with routing all those messages, which are enabled at compile time to the logging targets. If a message is not routed, it will be discarded. This allows to additionally disable messages at run-time. - - \fixme Restructure compile-time configuration: Only allow stream based configuration using - SENF_LOG_CONF. For more complex configuration, accept a macro SENF_LOG_CONFFILE which, if - defined, must define the path of a file to be included. Area specific configuration must be - done in this include file. The area must be complete (not only a predeclaration) at that - point. */ namespace senf { diff --git a/Utils/Logger/Config.ih b/Utils/Logger/Config.ih index 6fec502..f8ed4f7 100644 --- a/Utils/Logger/Config.ih +++ b/Utils/Logger/Config.ih @@ -94,7 +94,6 @@ namespace detail { # define SLC_elt(r, data, elt) \ SENF_LOG_CONF_DEFINE elt - // Need to use fold here to not exhaust the maximum FOR nesting depth ... BOOST_PP_SEQ_FOR_EACH(SLC_elt, none, SENF_LOG_CONF) # undef SLC_elt diff --git a/Utils/Logger/Definitions.hh b/Utils/Logger/Definitions.hh index ecf05b5..0429267 100644 --- a/Utils/Logger/Definitions.hh +++ b/Utils/Logger/Definitions.hh @@ -77,8 +77,8 @@ namespace log { /** \brief Define new default log area for the class - This command declares the containing class to be it's own default log area. It is such like a - combination of \ref SENF_LOG_DEF_AREA and \ref SENF_LOG_DEFAULT_AREA with a twist. + This command declares the containing class to be it's own default log area. It is such like + a combination of \ref SENF_LOG_DEF_AREA and \ref SENF_LOG_DEFAULT_AREA with a twist. \hideinitializer */ diff --git a/Utils/Logger/Log.test.cc b/Utils/Logger/Log.test.cc index b4a1cbd..0bec6da 100644 --- a/Utils/Logger/Log.test.cc +++ b/Utils/Logger/Log.test.cc @@ -28,7 +28,8 @@ // We need to put all tests into this single file to not violate the ODR -#define SENF_LOG_CONF (( (senf)(log)(Debug), (_), NOTICE )) +#define SENF_LOG_CONF (( (senf)(log)(Debug), (_), NOTICE )) \ + (( (not_anonymous)(myStream), (not_anonymous)(Foo), VERBOSE )) // Custom includes #include "Logger.hh" @@ -61,6 +62,7 @@ BOOST_AUTO_UNIT_TEST(logger) senf::log::StringTarget target; target.route(); + target.route("not_anonymous::myStream", "not_anonymous::Foo"); // We cannot easily check the exact log string since that includes the current date/time diff --git a/Utils/Logger/Mainpage.dox b/Utils/Logger/Mainpage.dox index 8eab9f3..5905c89 100644 --- a/Utils/Logger/Mainpage.dox +++ b/Utils/Logger/Mainpage.dox @@ -51,8 +51,7 @@ // This is a combination of SENF_LOG_DEF_AREA and SENF_LOG_DEFAULT_AREA. SENF_LOG_CLASS_AREA(); - // Set default log parameters for this scope. The values here are not really - // necessary since these are the global default values + // Set default log parameters for this scope. SENF_LOG_DEFAULT_STREAM(foo::UserLog); SENF_LOG_DEFAULT_LEVEL(senf::log::NOTICE); @@ -89,9 +88,11 @@ design goals \li Flexible configuration at compile and runtime \li Concise usage and simple interface - \li Zero overhead for compile-time disabled log messages I did not find any non-mcaro - implementation which was not either completely convoluted, unusable or slow. So I turned to - a macro based implementation which can provide all the design goals stated above. + \li Zero overhead for compile-time disabled log messages + + I did not find any non-mcaro implementation which was not either completely convoluted, + unusable or slow. So I turned to a macro based implementation which can provide all the + design goals stated above. */ diff --git a/Utils/Logger/Parameters.ih b/Utils/Logger/Parameters.ih index 9c6529c..2c17541 100644 --- a/Utils/Logger/Parameters.ih +++ b/Utils/Logger/Parameters.ih @@ -67,7 +67,7 @@ namespace detail { senf::mpl::rv<2> Parameters_select_(AreaBase *); template struct Parameters_ : public Base - { typedef Param area; }; + { typedef Param area; typedef Param area_base; }; senf::mpl::rv<3> Parameters_select_(LevelBase *); template @@ -96,7 +96,7 @@ namespace detail { typename boost::disable_if< boost::is_convertible >::type * = 0); template struct Parameters_ : public Base - { typedef typename Param::SENFLogArea area; }; + { typedef typename Param::SENFLogArea area; typedef Param area_base; }; #endif @@ -110,13 +110,12 @@ namespace detail { static bool const compileEnabled = senf::log::Enabled< typename Base::stream, - typename Base::area, + typename Base::area_base, level>::value; static bool enabled() { return compileEnabled - && Base::area::instance().streamLimit(Base::stream::instance()) - <= Base::level::value; + && Base::area::instance().limit(Base::stream::instance()) <= level::value; } }; diff --git a/Utils/Logger/StreamRegistry.cci b/Utils/Logger/StreamRegistry.cci index 5bb5b74..aba62ca 100644 --- a/Utils/Logger/StreamRegistry.cci +++ b/Utils/Logger/StreamRegistry.cci @@ -59,6 +59,13 @@ prefix_ void senf::log::StreamRegistry::registerStream(detail::StreamBase const registry_.insert( std::make_pair(stream.v_name(), &stream) ); } +prefix_ senf::log::detail::StreamBase const * +senf::log::StreamRegistry::lookup(std::string const & name) +{ + Registry::iterator i (registry_.find(name)); + return i == registry_.end() ? 0 : i->second; +} + /////////////////////////////////////////////////////////////////////////// // senf::log::detail::StreamBase diff --git a/Utils/Logger/StreamRegistry.hh b/Utils/Logger/StreamRegistry.hh index 6fd6dcd..a47e836 100644 --- a/Utils/Logger/StreamRegistry.hh +++ b/Utils/Logger/StreamRegistry.hh @@ -65,7 +65,7 @@ namespace log { typedef boost::transform_iterator iterator; # ifdef DOXYGEN - // Hmm ... doxygen does not understand using declarations ... + // Hmm ... doxygen does not understand 'using declarations' ... /// Access stream registry singleton instance static AreaRegistry & instance(); # endif @@ -79,6 +79,7 @@ namespace log { StreamRegistry(); void registerStream(detail::StreamBase const & stream); + detail::StreamBase const * lookup(std::string const & name); Registry registry_; diff --git a/Utils/Logger/Target.cc b/Utils/Logger/Target.cc index 997696a..11142a7 100644 --- a/Utils/Logger/Target.cc +++ b/Utils/Logger/Target.cc @@ -43,14 +43,48 @@ prefix_ senf::log::Target::Target() prefix_ senf::log::Target::~Target() { while( ! rib_.empty()) { - // This is slower but simplifies the area cache handling and removing a target - // should be quite seldom + // This is terribly slow but simplifies the area cache handling and removing a target should + // be quite seldom RIB::reverse_iterator i (rib_.rbegin()); - unroute(i->stream, i->area, i->level); + unroute(i->stream, i->area, i->level, i->action); } TargetRegistry::instance().unregisterTarget(this); } +prefix_ void senf::log::Target::updateRoutingCache(detail::StreamBase const * stream, + detail::AreaBase const * area) +{ + if (! stream) { + StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin()); + StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end()); + for (; i != i_end ; ++i) + updateRoutingCache(i->second, area); + return; + } + if (! area) { + AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin()); + AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end()); + for (; i != i_end ; ++i) + updateRoutingCache(stream, i->second); + return; + } + unsigned limit (DISABLED::value); + RIB::iterator i (rib_.begin()); + RIB::iterator const i_end (rib_.end()); + for(; i != i_end; ++i) + if ( (! i->stream || i->stream == stream) && + (! i->area || i->area == area) && + i->action == ACCEPT ) { + unsigned l (i->level == NONE::value ? i->stream->defaultRuntimeLimit() : i->level); + if (l < limit) + limit = l; + } + if (limit == DISABLED::value) + area->removeRoutingCache(*this, *stream); + else + area->updateRoutingCache(*this, *stream, limit); +} + prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream, detail::AreaBase const & area, unsigned level, @@ -59,10 +93,11 @@ prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp, RIB::iterator i (rib_.begin()); RIB::iterator const i_end (rib_.end()); for (; i != i_end; ++i) - if ( ( ! i->stream || i->stream == &stream ) && - ( ! i->area || i->area == &area ) && + if ( (! i->stream || i->stream == &stream) && + (! i->area || i->area == &area) && (i->level == NONE::value ? i->stream->defaultRuntimeLimit() : i->level) <= level ) { - v_write(timestamp, stream.v_name(), area.v_name(), level, message); + if (i->action == ACCEPT) + v_write(timestamp, stream.v_name(), area.v_name(), level, message); return; } } @@ -75,10 +110,7 @@ prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream, std::string msg) { boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time()); - Targets::iterator i (targets_.begin()); - Targets::iterator i_end (targets_.end()); - for(; i != i_end; ++i) - (*i)->write(timestamp, stream, area, level, msg); + area.write(timestamp, stream, level, msg); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Utils/Logger/Target.cci b/Utils/Logger/Target.cci index 129bef5..f58865e 100644 --- a/Utils/Logger/Target.cci +++ b/Utils/Logger/Target.cci @@ -34,48 +34,88 @@ /////////////////////////////////////////////////////////////////////////// // senf::log::Target -prefix_ void senf::log::Target::route(detail::StreamBase const * stream, - detail::AreaBase const * area, unsigned level) +prefix_ void senf::log::Target::route(std::string const & stream, action_t action) { - rib_.push_back(RoutingEntry(stream, area, level)); - - // Update the area/stream routing cache - if (area) - updateAreaCache(*area, stream, level); - else { - AreaRegistry::Registry::iterator i (AreaRegistry::instance().registry_.begin()); - AreaRegistry::Registry::iterator const i_end (AreaRegistry::instance().registry_.end()); - for (; i != i_end; ++i) - updateAreaCache(*(i->second), stream, level); - } - + detail::StreamBase const * s (StreamRegistry::instance().lookup(stream)); + if (!s) + throw InvalidStreamException(); + route(s, 0, NONE::value, action); } -prefix_ void -senf::log::Target::updateAreaCache(detail::AreaBase const & area, - detail::StreamBase const * stream, unsigned level) +prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area, + action_t action) { - if (stream) { - if (level < area.streamLimit(*stream)) - area.setStreamLimit(*stream, level); - } else { - StreamRegistry::Registry::iterator i (StreamRegistry::instance().registry_.begin()); - StreamRegistry::Registry::iterator const i_end (StreamRegistry::instance().registry_.end()); - for(; i != i_end; ++i) - if (level < area.streamLimit(*(i->second))) - area.setStreamLimit(*(i->second),level); - } + detail::StreamBase const * s (StreamRegistry::instance().lookup(stream)); + if (!s) + throw InvalidStreamException(); + detail::AreaBase const * a (AreaRegistry::instance().lookup(area)); + if (!a) + throw InvalidAreaException(); + route(s, a, NONE::value, action); +} + +prefix_ void senf::log::Target::route(std::string const & stream, unsigned level, action_t action) +{ + detail::StreamBase const * s (StreamRegistry::instance().lookup(stream)); + if (!s) + throw InvalidStreamException(); + route(s, 0, level, action); +} + +prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area, + unsigned level, action_t action) +{ + detail::StreamBase const * s (StreamRegistry::instance().lookup(stream)); + if (!s) + throw InvalidStreamException(); + detail::AreaBase const * a (AreaRegistry::instance().lookup(area)); + if (!a) + throw InvalidAreaException(); + route(s, a, level, action); +} + +//////////////////////////////////////// +// private members + +prefix_ void senf::log::Target::route(detail::StreamBase const * stream, + detail::AreaBase const * area, unsigned level, + action_t action) +{ + rib_.push_back(RoutingEntry(stream, area, level, action)); + if (action == ACCEPT) + updateRoutingCache(stream, area); } prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream, - detail::AreaBase const * area, unsigned level) + detail::AreaBase const * area, unsigned level, + action_t action) { - rib_.erase(std::remove(rib_.begin(), rib_.end(), RoutingEntry(stream, area, level)), + rib_.erase(std::remove(rib_.begin(), rib_.end(), RoutingEntry(stream, area, level, action)), rib_.end()); + if (action == ACCEPT) + updateRoutingCache(stream, area); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::log::Target::RoutingEntry + +prefix_ senf::log::Target::RoutingEntry::RoutingEntry(detail::StreamBase const * stream_, + detail::AreaBase const * area_, + unsigned level_, action_t action_) + : stream(stream_), area(area_), level(level_), action(action_) +{} + +prefix_ senf::log::Target::RoutingEntry::RoutingEntry() + : stream(0), area(0), level(0), action(ACCEPT) +{} - ///\fixme Update area/stream routing cache - // Not doing anything here does not produce incorrect behavior, since removing a route - // can never lower the logging limit. Not updating the cache just reduces the performance. +prefix_ bool senf::log::Target::RoutingEntry::operator==(RoutingEntry const & other) +{ + return + stream == other.stream && + area == other.area && + level == other.level && + action == other.action; } /////////////////////////////////////////////////////////////////////////// diff --git a/Utils/Logger/Target.cti b/Utils/Logger/Target.cti index ea7f5e2..a61c703 100644 --- a/Utils/Logger/Target.cti +++ b/Utils/Logger/Target.cti @@ -35,21 +35,21 @@ // senf::log::Target template -prefix_ void senf::log::Target::route() +prefix_ void senf::log::Target::route(action_t action) { - route(&Stream::instance(), 0, NONE::value); + route(&Stream::instance(), 0, NONE::value, action); } -template -prefix_ void senf::log::Target::route() +template +prefix_ void senf::log::Target::route(action_t action) { - route(&Stream::instance(), static_cast(0)); + route(&Stream::instance(), static_cast(0), action); } template -prefix_ void senf::log::Target::route() +prefix_ void senf::log::Target::route(action_t action) { - route(&Stream::instance(), &Area::instance(), Level::value); + route(&Stream::instance(), &Area::instance(), Level::value, action); } //////////////////////////////////////// @@ -57,16 +57,16 @@ prefix_ void senf::log::Target::route() template prefix_ void senf::log::Target::route(detail::StreamBase const * stream, - detail::AreaBase const *) + detail::AreaBase const *, action_t action) { - route(stream, &Area::instance(), NONE::value); + route(stream, &Area::instance(), NONE::value, action); } template prefix_ void senf::log::Target::route(detail::StreamBase const * stream, - detail::LevelBase const *) + detail::LevelBase const *, action_t action) { - route(stream, 0, Level::value); + route(stream, 0, Level::value, action); } /////////////////////////////////////////////////////////////////////////// diff --git a/Utils/Logger/Target.hh b/Utils/Logger/Target.hh index 24b6ea3..56cf519 100644 --- a/Utils/Logger/Target.hh +++ b/Utils/Logger/Target.hh @@ -60,6 +60,8 @@ namespace log { /////////////////////////////////////////////////////////////////////////// // Types + enum action_t { ACCEPT, REJECT }; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ @@ -70,14 +72,28 @@ namespace log { ///@} template - void route(); + void route(action_t action=ACCEPT); - template - void route(); + template + void route(action_t action=ACCEPT); template - void route(); + void route(action_t action=ACCEPT); + + void route(std::string const & stream, action_t action=ACCEPT); + void route(std::string const & stream, std::string const & area, action_t action=ACCEPT); + void route(std::string const & stream, unsigned level, action_t action=ACCEPT); + void route(std::string const & stream, std::string const & area, unsigned level, + action_t action=ACCEPT); + + struct InvalidStreamException : public std::exception + { virtual char const * what() const throw() + { return "senf::log::Target::InvalidStreamException"; } }; + struct InvalidAreaException : public std::exception + { virtual char const * what() const throw() + { return "senf::log::Target::InvalidAreaException"; } }; + protected: std::string timestamp(); @@ -85,18 +101,17 @@ namespace log { private: void route(detail::StreamBase const * stream, detail::AreaBase const * area, - unsigned level); + unsigned level, action_t action); void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, - unsigned level); + unsigned level, action_t action); template - void route(detail::StreamBase const * stream, detail::AreaBase const *); + void route(detail::StreamBase const * stream, detail::AreaBase const *, action_t action); template - void route(detail::StreamBase const * stream, detail::LevelBase const *); - - void updateAreaCache(detail::AreaBase const & area, detail::StreamBase const * stream, - unsigned level); + void route(detail::StreamBase const * stream, detail::LevelBase const *, action_t action); + + void updateRoutingCache(detail::StreamBase const * stream, detail::AreaBase const * area); void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream, detail::AreaBase const & area, unsigned level, std::string const & message); @@ -116,24 +131,21 @@ namespace log { struct RoutingEntry { RoutingEntry(detail::StreamBase const * stream_, detail::AreaBase const * area_, - unsigned level_) - : stream(stream_), area(area_), level(level_) {} - RoutingEntry() - : stream(0), area(0), level(0) {} + unsigned level_, action_t action_); + RoutingEntry(); - bool operator==(RoutingEntry const & other) - { return stream == other.stream && area == other.area && level == other.level; } + bool operator==(RoutingEntry const & other); detail::StreamBase const * stream; detail::AreaBase const * area; - unsigned level; + unsigned level; action_t action; }; typedef std::vector RIB; RIB rib_; - friend class TargetRegistry; + friend class detail::AreaBase; }; /** \brief Target registry