*/
struct Parse_GREPacket : public PacketParserBase
{
-
-#include SENF_PARSER()
+# include SENF_PARSER()
+
SENF_PARSER_BITFIELD ( checksum_present, 1, bool );
SENF_PARSER_PRIVATE_BITFIELD ( reserved0_, 12, unsigned ); // TODO: SKIP !!
SENF_PARSER_BITFIELD_RO ( version_number, 3, unsigned ); // TODO: Always Zero !!
(VoidPacketParser) (Parse_UInt16) );
SENF_PARSER_PRIVATE_VARIANT ( reserved1_, checksum_present,
(VoidPacketParser) (Parse_UInt16) );
+
SENF_PARSER_FINALIZE( Parse_GREPacket );
private:
env.Clean('all', '.prepare-stamp')
+# Not nice, but until we get to fixing the dependency jungle
+# concerning generated sources ...
scripts = []
dependencies = []
decide a log messages fate for that target.
\see
- \ref SENF_LOG_CONF: compile time configuration \n
- \ref senf::log::Target: runtime configuration
+ \ref SENF_LOG_CONF compile time configuration \n
+ \ref senf::log::Target runtime configuration
*/
namespace senf {
/** \brief Write log messages to std::cout
IOStreamTarget writing to std::cout
+
+ \ingroup targets
*/
class ConsoleTarget : public IOStreamTarget
{
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 FileTarget non-inline non-template implementation */
+
+#include "FileTarget.hh"
+//#include "FileTarget.ih"
+
+// Custom includes
+
+//#include "FileTarget.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ senf::log::FileTarget::FileTarget(std::string file)
+ : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(ofstream_t::member), file_(file)
+{}
+
+prefix_ void senf::log::FileTarget::reopen()
+{
+ ofstream_t::member.close();
+ ofstream_t::member.open(file_.c_str(), std::ofstream::app);
+}
+
+prefix_ void senf::log::FileTarget::reopen(std::string file)
+{
+ file_ = file;
+ reopen();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "FileTarget.mpp"
+
+\f
+// 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:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 FileTarget public header */
+
+#ifndef HH_FileTarget_
+#define HH_FileTarget_ 1
+
+// Custom includes
+#include <boost/utility.hpp>
+#include <fstream>
+#include "IOStreamTarget.hh"
+
+//#include "FileTarget.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+
+ /** \brief Log target writing to a log file.
+
+ The FileTarget will save all log messages in the given file. Messages will be appended at
+ the end of the file.
+
+ After log files have been rotated, the reopen() member should be called to create a new log
+ file.
+
+ \ingroup targets
+ */
+ class FileTarget
+ : private boost::base_from_member<std::ofstream>,
+ public IOStreamTarget
+ {
+ typedef boost::base_from_member<std::ofstream> ofstream_t;
+
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ explicit FileTarget(std::string file); ///< Construct FileTarget writing to \a file
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ void reopen(); ///< Reopen log after log-file rotation
+ void reopen(std::string file); ///< Reopen log under a new name
+
+ private:
+ std::string file_;
+ };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "FileTarget.cci"
+//#include "FileTarget.ct"
+//#include "FileTarget.cti"
+#endif
+
+\f
+// 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:
\warning The class keeps a reference to the passed stream.
\note This class will permanently and globally change the date formating of the given
- stream.
+ stream if no \c boost::posix_time::time_facet has been set.
+
+ \ingroup targets
*/
class IOStreamTarget
: public Target
#define SENF_LOG_BLOCK_(parameters, block) \
do { \
- if (parameters::compileEnabled && parameters::enabled()) { \
+ typedef parameters SENFLogParameters; \
+ if (SENFLogParameters::compileEnabled && SENFLogParameters::enabled()) { \
std::stringstream log; \
do block while(0); \
- senf::log::write<parameters::stream, parameters::area, parameters::level>(log.str()); \
+ senf::log::detail::write< SENFLogParameters::stream, \
+ SENFLogParameters::area, \
+ SENFLogParameters::level >(log.str()); \
} \
} while(0)
#define SENF_LOG_BLOCK_TPL_(parameters, block) \
do { \
- if (parameters::compileEnabled && parameters::enabled()) { \
+ typedef parameters SENFLogParameters; \
+ if (SENFLogParameters::compileEnabled && SENFLogParameters::enabled()) { \
std::stringstream log; \
do block while(0); \
- senf::log::write<typename parameters::stream, \
- typename parameters::area, \
- typename parameters::level>(log.str()); \
+ senf::log::detail::write<typename SENFLogParameters::stream, \
+ typename SENFLogParameters::area, \
+ typename SENFLogParameters::level>(log.str()); \
} \
} while(0)
\section logging_concepts Concepts
- The log messages are devided along several categories: \e streams, \e areas and log \e levels.
-
- A \e stream combines log messages with a single purpose. There is one default stream, called \c
- senf::log::Debug. New streams are defined with \ref SENF_LOG_DEF_STREAM.
-
- An \e area labels a log message with the source location of the message. An area is an arbitrary
- tag which may be added to the message. There is one default area called \c
- senf::log::DefaultArea. New areas are defined either with \ref SENF_LOG_DEF_AREA or \ref
- SENF_LOG_CLASS_AREA, the latter being the more typical. The area will normally indicate the
- class or subsystem from which the message was generated.
-
- The log \e level gives information on the importance of the message. The list lof \ref loglevels
- is fixed.
-
- After log messages have been created, they have to be placed somewhere. This is the
- responsibility of the \e target. A target is an arbitrary sink for log messages. The target
- manages message routing and will pass the message on to it's destination, be it the system
- console, some log file or some other place (e.g. an SQL database). The target is responsible for
- formating the message.
+ Log messages are arbitrarily created throughout the code using simple log statements (which are
+ macros). Besides the log message itself, every log message is labeled with additional
+ information: The \e stream, the \e area and a log \e level. If the message is not compile-time
+ disabled, the message is then directed to one of several log \e targets.
+
+ A \e stream combines log messages with a single purpose: Debug messages, access logging and so
+ on. Any number of streams may be defined. There is one predefined default stream called \c
+ senf::log::Debug. (see: \ref SENF_LOG_DEF_STREAM)
+
+ The \e area gives information about the source location of the message. Areas may be defined and
+ assigned arbitrarily but should be used to label messages from a single class or subsystem. It
+ is possible to reuse a class as it's own area tag, which is often desireable. (see: \ref
+ SENF_LOG_DEF_AREA, \ref SENF_LOG_CLASS_AREA)
+
+ The log \e level gives information on the importance of the message. The list of log-levels is
+ fixed. (see: \ref loglevels)
+
+ Depending on their the \e stream, \e area and \e level information, log messages can be enabled
+ or disabled at \e compile time. Messages disabled at compile time should not generate any
+ code. (see: \ref SENF_LOG_CONF)
+
+ To be of any use, the log messages have to be written somewhere. This is the responsibility of
+ any number of \e targets. A \e target receives messages and using it's routing information
+ decides, wether the message is output or not. A message may be routed to multiple targets
+ simultaneously or may not be output by any target at all. (see: \ref targets)
\section logging_tutorial Tutorial introduction
SENF_LOG(("Log to UserLog stream in Froblizer area however at VERBOSE level"));
}
+
+ int main(int, char **)
+ {
+ // Set up the routing targets
+ senf::log::ConsoleTarget console;
+ senf::log::FileTarget logfile ("my.log");
+
+ // Debug messages go to the console
+ console.route<senf::log::Debug>();
+ // Important user message are written to the log file
+ logfile.route<foo::UserLog, senf::log::IMPORTANT>();
+ }
\endcode
\implementation I would have much preferred a more C++ like implementation. However given the
namespace log {
/** \brief Store log messages in a string buffer
+
+ This target is mostly useful for debug purposes.
+
+ \ingroup targets
*/
class StringTarget
: private boost::base_from_member<std::stringstream>,
///@}
///////////////////////////////////////////////////////////////////////////
- std::string str() const;
- void clear();
+ std::string str() const; ///< Get log messages accumulated so far
+ void clear(); ///< Clear buffer
protected:
\brief Target non-inline non-template implementation */
#include "Target.hh"
-//#include "Target.ih"
+#include "Target.ih"
// Custom includes
#include <algorithm>
prefix_ senf::log::Target::Target()
{
- TargetRegistry::instance().registerTarget(this);
+ detail::TargetRegistry::instance().registerTarget(this);
}
prefix_ senf::log::Target::~Target()
RIB::reverse_iterator i (rib_.rbegin());
unroute(i->stream_, i->area_, i->level_, i->action_);
}
- TargetRegistry::instance().unregisterTarget(this);
+ detail::TargetRegistry::instance().unregisterTarget(this);
}
prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area,
i = rib_.begin();
else {
i = rib_.end();
- std::advance(i, -index);
+ std::advance(i, index);
}
} else {
if (RIB::size_type(index+1) >= rib_.size()) {
std::advance(i, index);
}
}
+ if (i == rib_.end())
+ return;
RoutingEntry entry (*i);
rib_.erase(i);
if (entry.action_ == ACCEPT)
///////////////////////////////////////////////////////////////////////////
// senf::log::TargetRegistry
-prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream,
- detail::AreaBase const & area, unsigned level,
- std::string msg)
+prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
+ AreaBase const & area, unsigned level,
+ std::string msg)
{
boost::posix_time::ptime timestamp (boost::posix_time::microsec_clock::universal_time());
area.write(timestamp, stream, level, msg);
/** \file
\brief Target inline non-template implementation */
-//#include "Target.ih"
+#include "Target.ih"
// Custom includes
}
///////////////////////////////////////////////////////////////////////////
-// senf::log::TargetRegistry
+// senf::log::detail::TargetRegistry
-prefix_ void senf::log::TargetRegistry::registerTarget(Target * target)
+prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target)
{
targets_.insert(target);
}
-prefix_ void senf::log::TargetRegistry::unregisterTarget(Target * target)
+prefix_ void senf::log::detail::TargetRegistry::unregisterTarget(Target * target)
{
targets_.erase(target);
}
/** \file
\brief Target inline template implementation */
-//#include "Target.ih"
+#include "Target.ih"
// Custom includes
#include "Levels.hh"
// senf::log::Target::route
+#ifndef DOXYGEN
+
template <class Stream>
prefix_ void senf::log::Target::route(action_t action, int index)
{
unroute(&Stream::instance(), &AreaClass::SENFLogArea::instance(), Level::value, action);
}
+#endif
+
///////////////////////////////////////////////////////////////////////////
-// namespace senf::log members
+// namespace senf::log::detail members
template <class Stream, class Area, class Level>
-prefix_ void senf::log::write(std::string msg)
+prefix_ void senf::log::detail::write(std::string msg)
{
TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg);
}
//#include "Target.mpp"
///////////////////////////////hh.p////////////////////////////////////////
+/** \defgroup targets Targets
+
+ Targets receive log messages and write them to some destination: The console, a log file, an SQL
+ DB and so on. Every target is derived from the \ref senf::log::Target base class. This base
+ class provides the target with the necessary routing infrastructure. The different targets only
+ differ in the way, they write the data.
+
+ \see senf::log::Target
+ */
+
namespace senf {
namespace log {
class TargetRegistry;
/** \brief Logging target base class
-
- All enabled log messages are eventually routed to one or more logging targets. It is the
- responsibility of the logging target to write the log messages somewhere: onto the console,
- to a file, to mail them to the administrator or whatever. To this end, the logging target is
- passed the log message and a complete set of logging parameters (\e stream, \e area and \e
- level).
+
+ Targets are the final destination of log messages. Every message is eventually routed to one
+ or several targets.
+
+ \section target_routing Routing
+
+ Each target manages a routing table. The message meta-data (stream, area and level) is
+ matched against this table. If an entry matches, the action associated with this entry is
+ taken (either \c ACCEPT or \c REJECT).
+
+ Every target manages it's own routing table. Conceptually, every routing message will be
+ routed to every target where it will then be matched against each targets routing table (the
+ implementation is more efficient and utilizes a routing cache).
+
+ Each routing entry consists of the following parameters
+ \li (mandatory) \e stream. The entry will match only messages directed at that stream
+ \li (optional) \e area. If the area is specified, only messages directed at that area are
+ matched, otherwise any area will be allowed
+ \li (optional) \e level. If the log level is specified, messages will be accepted if their
+ level is at least that value. If the value is not specified, the limit will be taken
+ from the stream's default value.
+
+ Each parameter (stream, area and level) has two representations: A static (compile time
+ constant) representation, which is the representation also used in the log statements, and a
+ dynamic representation, which may be used for manipulating the routing table.
+
+ The static representation is used, when passing routing parameters via template arguments:
+ \code
+ target.route<foo::SomeStream, senf::log::NOTICE>(senf::log::Target::REJECT);
+ target.route<foo::SomeStream>();
+ \endcode
+ The identical routing statements may be expressed using dynamic routing via:
+ \code
+ target.route("foo::SomeStream", "", senf::log::NOTICE::value, senf::log::Target::REJECT);
+ target.route("foo::SomeStream");
+ \endcode
+ The static representation has the benefit of being compile-time type checked: Invalid
+ routing parameters will be caught while compiling the code. The dynamic representation is
+ more flexible as it allows to adjust routing from user input (e.g. configuration files).
+
+ The different object representations are:
+ \li The \e streams is statically represented by it's name, which is the name of a class
+ defined with \ref SENF_LOG_DEF_STREAM. The dynamic representation is a string
+ representation of this name.
+ \li The \e area is statically represented by it's name, which again is the name of a class
+ defined with \ref SENF_LOG_DEF_STREAM. The dynamic representation again is a string
+ representation of this class's name. The dynamic representation represents an absent
+ area with the empty string.
+ \li The \e level is statically represented by a level class from \ref
+ loglevels. Dynamically, it is represented by an unsigned integer number, the \c value
+ member of that class.
+
+ \section target_impl Implementing new targets
+
+ To implement a new target type, you need to derive from senf::log::Target and implement the
+ single \c v_write member. This member will be called whenever a message should be output.
+
+ The target may process in any arbitrary way: reformat, writing it into an SQL DB, whatever
+ can be envisioned. However, there is one important limitation: The \c v_write call must not
+ block. So for more complex scenarios, additional measures must be taken (e.g. writing a log
+ backend daemon which receives the messages via UDP and processes them). Of course, in rare
+ cases messages might be lost but this cannot be avoided.
+
+ \see \ref targets
\fixme optionally Integrate with Scheduler / ClockService to reduce number of gettimeofday()
calls.
///////////////////////////////////////////////////////////////////////////
// Types
- enum action_t { ACCEPT, REJECT };
+ /** \brief Routing action
+ Every routing entry is associated with a routing action. This action is final (for this
+ target. Each target is processed independently).
+ */
+ enum action_t {
+ ACCEPT /** Output message */
+ , REJECT /** Suppress message output */
+ };
+
+ /** \brief Target routing entry
+
+ A single routing entry matches messages against their \e stream, \e area and \e
+ level. If the entry matches, the given \e action is performed.
+
+ \see senf::log::Target
+ */
struct RoutingEntry
{
+ std::string stream() const; ///< Stream to match
+ std::string area() const; ///< Area to match (empty of unspecified)
+ unsigned level() const; ///< Level to match (senf::log::NONE::value if unspecified)
+ action_t action() const; ///< Action to take
+
+# ifdef DOXYGEN
+ private:
+# endif
+
RoutingEntry();
bool operator==(RoutingEntry const & other);
- std::string stream() const;
- std::string area() const;
- unsigned level() const;
- action_t action() const;
-
private:
RoutingEntry(detail::StreamBase const * stream, detail::AreaBase const * area,
unsigned level, action_t action);
typedef std::vector<RoutingEntry> RIB;
public:
- typedef RIB::const_iterator iterator;
+ typedef RIB::const_iterator iterator; ///< Routing table iterator
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
virtual ~Target();
///@}
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Routing
+ ///\{
+
+# ifdef DOXYGEN
+
+ template <class Stream, class Area, class Level> void route(
+ action_t action = ACCEPT, int index = -1); ///< Add route (static)
+ /**< Add a route for the given combination of \a Stream, \a
+ Area and \a Level. The \a Stream parameter is mandatory
+ while either \a Area or \a Level are optional (the
+ template signature is shown simplified here):
+ \code
+ target.route<SomeStream>();
+ target.route<SomeStream, SomeLevel>();
+ target.route<SomeStream, SomeArea>();
+ target.route<SomeStream, SomeArea, SomeLevel>();
+ \endcode
+
+ See the class description for information on the \a
+ action and \a index parameters
+
+ \param[in] Stream mandatory stream to match
+ \param[in] Area optional area to match
+ \param[in] Level optional level, matches messages with
+ at least the given level.
+ \param[in] action routing action to take
+ \param[in] index position of new route in the routing
+ table */
+
+# endif
+
+ void route(std::string const & stream, std::string const & area = "",
+ unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
+ ///< Add route (dynamic)
+ /**< Add a route for the given combination of \a stream, \a
+ area and \a level. The \a stream parameter is mandatory
+ while either \a area or \a level may be left
+ unspecified by setting them to the empty string or
+ senf::log::NONE::value respectively.
+
+ See the class description for information on the \a
+ action and \a index parameters
+
+ \throws InvalidStreamException if the given \a stream
+ is not found in the StreamRegistry
+ \throws InvalidAreaException if the given \a area is
+ not found in the AreaRegistry
+
+ \param[in] stream mandatory stream to match
+ \param[in] area optional area to match
+ \param[in] level optional level, matches messages with
+ at least the given level.
+ \param[in] action routing action to take
+ \param[in] index position of new route in the routing
+ table */
+
+# ifdef DOXYGEN
+
+ template <class Stream, class Area, class Level>
+ void unroute(action_t action = ACCEPT);
+ ///< Remove route (static)
+ /**< This member removes an arbitrary routing entry. The
+ template parameters are the same as for the
+ corresponding \ref route() call.
+
+ The routing table is searched for a route exactly
+ matching the given specification. If such a route is
+ found, it will be removed, otherwise the call will be
+ ignored
+
+ \param[in] Stream mandatory stream to match
+ \param[in] Area optional area to match
+ \param[in] Level optional level, matches messages with
+ at least the given level.
+ \param[in] action routing action to take */
+
+# endif
+
+ void unroute(std::string const & stream, std::string const & area = "",
+ unsigned level = NONE::value, action_t action = ACCEPT);
+ ///< Remove route (dynamic)
+ /**< This member removes an arbitrary routing entry. The \a
+ stream parameter is mandatory while either \a area or
+ \a level may be left unspecified by setting them to the
+ empty string or senf::log::NONE::value respectively.
+
+ The routing table is searched for a route exactly
+ matching the given specification. If such a route is
+ found, it will be removed, otherwise the call will be
+ ignored
+
+ \param[in] stream mandatory stream to match
+ \param[in] area optional area to match
+ \param[in] level optional level, matches messages with
+ at least the given level.
+ \param[in] action routing action to take */
+ void unroute(int index=-1); ///< Remove route (indexed)
+ /**< This call will remove the route with the given index.
+
+ See the class documentation for more information on
+ indexing.
+
+ \param[in] index index of routing entry to remove */
+
+# ifndef DOXYGEN
template <class Stream> void route(
action_t action = ACCEPT, int index = -1);
typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
detail::AreaBase *> >::type * = 0);
- void route(std::string const & stream, std::string const & area = "",
- unsigned level = NONE::value, action_t action = ACCEPT, int index = -1);
-
template <class Stream> void unroute(
action_t action = ACCEPT);
template <class Stream, class Level> void unroute(
typename boost::enable_if< boost::is_convertible<typename AreaClass::SENFLogArea *,
detail::AreaBase *> >::type * = 0);
- void unroute(std::string const & stream, std::string const & area = "",
- unsigned level = NONE::value, action_t action = ACCEPT);
- void unroute(int index);
+# endif
+
+ ///\}
+ /** \brief Exception: Invalid stream */
struct InvalidStreamException : public std::exception
{ virtual char const * what() const throw()
{ return "senf::log::Target::InvalidStreamException"; } };
+ /** \brief Exception: Invalid area */
struct InvalidAreaException : public std::exception
{ virtual char const * what() const throw()
{ return "senf::log::Target::InvalidAreaException"; } };
- iterator begin() const;
- iterator end() const;
+ iterator begin() const; ///< Iterator to beginning of routing table
+ iterator end() const; ///< Iterator past the end of routing table
private:
void route(detail::StreamBase const * stream, detail::AreaBase const * area,
protected:
# endif
- virtual void v_write(boost::posix_time::ptime, std::string const & stream,
+ virtual void v_write(boost::posix_time::ptime timestamp, std::string const & stream,
std::string const & area, unsigned level,
std::string const & message) = 0;
+ ///< Called to write out the routing message
+ /**< This member must be defined in the derived class to
+ somehow format and write the log message.
+
+ Every log message always possesses a complete set of
+ meta information (\a stream, \a area and \a level). The
+ \a area may be an empty string if the message was
+ written from the senf::log::DefaultArea.
+
+ \note This member must \e not block since it may be
+ called from any unknown context. This prohibits
+ simple logging over NFS or many other network
+ protocols.
+
+ \param[in] timestamp log message timing information
+ \param[in] stream message stream
+ \param[in] area message area
+ \param[in] level message level
+ \param[in] message the message string */
# ifdef DOXYGEN
private:
friend class detail::AreaBase;
};
- /** \brief Target registry
-
- The TargetRegistry keeps a record of all existing targets.
- */
- class TargetRegistry
- : public senf::singleton<TargetRegistry>
- {
- public:
- using senf::singleton<TargetRegistry>::instance;
-
- void write(detail::StreamBase const & stream, detail::AreaBase const & area,
- unsigned level, std::string msg);
-
- private:
- void registerTarget(Target * target);
- void unregisterTarget(Target * target);
-
- typedef std::set<Target *> Targets;
- Targets targets_;
-
- friend class Target;
- };
-
-
- template <class Stream, class Area, class Level>
- void write(std::string msg);
-
}}
///////////////////////////////hh.e////////////////////////////////////////
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer NETwork research (NET)
+// Stefan Bund <g0dil@berlios.de>
+//
+// 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 Target internal header */
+
+#ifndef IH_Target_
+#define IH_Target_ 1
+
+// Custom includes
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+namespace detail {
+
+ /** \brief Internal: Target registry */
+ class TargetRegistry
+ : public senf::singleton<TargetRegistry>
+ {
+ public:
+ using senf::singleton<TargetRegistry>::instance;
+
+ void write(StreamBase const & stream, AreaBase const & area, unsigned level,
+ std::string msg);
+
+ private:
+ void registerTarget(Target * target);
+ void unregisterTarget(Target * target);
+
+ typedef std::set<Target *> Targets;
+ Targets targets_;
+
+ friend class senf::log::Target;
+ };
+
+ /** \brief Internal: Write log message */
+ template <class Stream, class Area, class Level>
+ void write(std::string msg);
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// 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: