Utils/Logger: Implement targets
g0dil [Fri, 26 Oct 2007 15:00:30 +0000 (15:00 +0000)]
Utils/Logger: Implement message routing -> logging library is working now
Move 'nil' class into Utils/mpl.hh

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@476 270642c3-0616-0410-b53a-bc976706d245

21 files changed:
Socket/SocketPolicy.ih
Utils/Logger/Config.hh
Utils/Logger/ConsoleTarget.cc [new file with mode: 0644]
Utils/Logger/ConsoleTarget.hh [new file with mode: 0644]
Utils/Logger/Definitions.hh
Utils/Logger/Definitions.ih
Utils/Logger/IOStreamTarget.cc [new file with mode: 0644]
Utils/Logger/IOStreamTarget.hh [new file with mode: 0644]
Utils/Logger/Log.hh
Utils/Logger/Log.ih
Utils/Logger/Log.test.cc
Utils/Logger/Mainpage.dox
Utils/Logger/Parameters.ih
Utils/Logger/StreamRegistry.ih
Utils/Logger/StringTarget.cti [new file with mode: 0644]
Utils/Logger/StringTarget.hh [new file with mode: 0644]
Utils/Logger/Target.cc
Utils/Logger/Target.cci
Utils/Logger/Target.cti [new file with mode: 0644]
Utils/Logger/Target.hh
Utils/mpl.hh

index ccc0371..413635b 100644 (file)
@@ -111,8 +111,6 @@ namespace senf {
 
 namespace impl {
 
-    struct nil {};
-
     template <class Base, class Policy, int _>
     struct MakeSocketPolicy_merge
     {};
@@ -150,7 +148,7 @@ namespace impl {
         {};
 
         template <class Base>
-        struct apply<Base,nil>
+        struct apply<Base,mpl::nil>
         {
             typedef Base type;
         };
@@ -201,7 +199,7 @@ namespace impl {
 
     template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( SENF_SOCKET_POLICIES_N, 
                                                     class T, 
-                                                    senf::impl::nil ) >
+                                                    mpl::nil ) >
     class MakeSocketPolicy
         : public boost::mpl::if_< boost::is_convertible< T0*, SocketPolicyBase* >,
                                   impl::MakeSocketPolicy_impl< 
index a9bf7c7..27a9af8 100644 (file)
     <em>Runtime</em> 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 {
@@ -118,7 +124,7 @@ namespace log {
     struct Enabled
     {
         static const bool value = (
-            (Level::value == senf::log::NONE::value ? Stream::defaultLevel::value : Level::value)
+            (Level::value == NONE::value ? Stream::defaultLevel::value : Level::value)
                 >= detail::Config<Stream,Area>::compileLimit::value );
     };
 
diff --git a/Utils/Logger/ConsoleTarget.cc b/Utils/Logger/ConsoleTarget.cc
new file mode 100644 (file)
index 0000000..411b2e4
--- /dev/null
@@ -0,0 +1,56 @@
+// $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 ConsoleTarget non-inline non-template implementation */
+
+#include "ConsoleTarget.hh"
+//#include "ConsoleTarget.ih"
+
+// Custom includes
+#include <iostream>
+
+//#include "ConsoleTarget.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::ConsoleTarget
+
+prefix_ senf::log::ConsoleTarget::ConsoleTarget()
+    : IOStreamTarget(std::cout)
+{}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "ConsoleTarget.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:
diff --git a/Utils/Logger/ConsoleTarget.hh b/Utils/Logger/ConsoleTarget.hh
new file mode 100644 (file)
index 0000000..b345ef7
--- /dev/null
@@ -0,0 +1,72 @@
+// $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 ConsoleTarget public header */
+
+#ifndef HH_ConsoleTarget_
+#define HH_ConsoleTarget_ 1
+
+// Custom includes
+#include "IOStreamTarget.hh"
+
+//#include "ConsoleTarget.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf { 
+namespace log {
+
+    /** \brief Write log messages to std::cout
+
+        IOStreamTarget writing to std::cout
+     */
+    class ConsoleTarget : public IOStreamTarget
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        ConsoleTarget();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "ConsoleTarget.cci"
+//#include "ConsoleTarget.ct"
+//#include "ConsoleTarget.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:
index 5e9d5cc..ecf05b5 100644 (file)
@@ -60,6 +60,8 @@ namespace log {
             typedef runtimeLimit_ runtimeLimit;                                                   \
             typedef compileLimit_ compileLimit;                                                   \
             static std::string name() { return instance().v_name(); }                             \
+            unsigned defaultRuntimeLimit() const { return runtimeLimit::value; }                  \
+            using senf::singleton<stream>::instance;                                              \
         private:                                                                                  \
             stream() { init(); }                                                                  \
             friend class senf::singleton<stream>;                                                 \
@@ -70,7 +72,6 @@ namespace log {
         Defines a new log area named \a area. The area is defined as a symbol in the current scope.
 
         \hideinitializer
-        \ingroup logging
      */
 #   define SENF_LOG_DEF_AREA(area) SENF_LOG_DEF_AREA_I(area, ; )
 
@@ -78,6 +79,8 @@ namespace log {
 
         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
      */
 #   define SENF_LOG_CLASS_AREA()                                                                  \
         SENF_LOG_DEF_AREA_I(                                                                      \
@@ -105,7 +108,7 @@ namespace log {
         }
 
         /** \brief Default global log stream */
-        SENF_LOG_DEF_STREAM(Debug, MESSAGE, DISABLED, DISABLED);
+        SENF_LOG_DEF_STREAM(Debug, MESSAGE, MESSAGE, MESSAGE);
 
         /** \brief Default global log area */
         SENF_LOG_DEF_AREA_I(DefaultArea,
index 7e97381..ae3639c 100644 (file)
@@ -35,6 +35,7 @@
         : public senf::log::detail::AreaBase, public senf::singleton<area>                        \
     {                                                                                             \
         static std::string name() { return instance().v_name(); }                                 \
+        using senf::singleton<area>::instance;                                                    \
         decls                                                                                     \
     private:                                                                                      \
         area() { init(); }                                                                        \
diff --git a/Utils/Logger/IOStreamTarget.cc b/Utils/Logger/IOStreamTarget.cc
new file mode 100644 (file)
index 0000000..f70fdd7
--- /dev/null
@@ -0,0 +1,74 @@
+// $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 IOStreamTarget non-inline non-template implementation */
+
+#include "IOStreamTarget.hh"
+//#include "IOStreamTarget.ih"
+
+// Custom includes
+#include <locale>
+
+//#include "IOStreamTarget.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::IOStreamTarget
+
+prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::ostream & os)
+    : stream_(os)
+{
+    std::locale const & loc (stream_.getloc());
+    if (!std::has_facet<boost::posix_time::time_facet>(loc))
+        stream_.imbue( std::locale(loc, new boost::posix_time::time_facet("%Y-%m-%d %H:%M:%S.%f-0000")) );
+}
+
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::log::IOStreamTarget::v_write(boost::posix_time::ptime timestamp,
+                                                std::string const & stream,
+                                                std::string const & area, unsigned level,
+                                                std::string const & message)
+{
+    stream_ << timestamp << " ";
+    if (! area.empty())
+        stream_ << "[" << area << "] ";
+    stream_ << message << std::endl;
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "IOStreamTarget.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:
diff --git a/Utils/Logger/IOStreamTarget.hh b/Utils/Logger/IOStreamTarget.hh
new file mode 100644 (file)
index 0000000..94f9999
--- /dev/null
@@ -0,0 +1,101 @@
+// $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 IOStreamTarget public header */
+
+#ifndef HH_IOStreamTarget_
+#define HH_IOStreamTarget_ 1
+
+// Custom includes
+#include <boost/utility.hpp>
+#include <boost/scoped_ptr.hpp>
+#include "Target.hh"
+
+//#include "IOStreamTarget.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+
+    /** \brief Write log messages to arbitrary std::ostream
+
+        This target will write log messages to an arbitrary std::ostream in the format
+        <pre>
+        <date> [<area>] <message>
+        </pre>
+        
+        The date formatting is set using the Boost.DateTime date_facet, e.g.:
+        \code
+        stream.imbue( std::locale(stream.getloc(), 
+                                  new boost::posix_time::time_facet("%Y%m%d %H:%M:%S")) );
+        \endcode
+
+        By default, the date-time will be written in extended ISO format.
+
+        \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.
+      */
+    class IOStreamTarget
+        : public Target
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        explicit IOStreamTarget(std::ostream & os);
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+    protected:
+
+    private:
+        void v_write(boost::posix_time::ptime timestamp, std::string const & stream, 
+                     std::string const & area, unsigned level, 
+                     std::string const & message);
+
+        std::ostream & stream_;
+    };
+
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "IOStreamTarget.cci"
+//#include "IOStreamTarget.ct"
+//#include "IOStreamTarget.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:
index 81b7703..53f0629 100644 (file)
     be \c senf::log::Debug (\e stream), senf::log::DefaultArea (\e area), and senf::log::NONE (\e
     level).
 
-    There is one special log level, senf::log::NONE. If the log level is set to this value, the log
-    level will be set from the stream provided default value.
+    The log level senf::log::NONE is special. If the log level is set to this value, the log level
+    will be set from the stream provided default value.
     
-
     All these parameters must be <em>compile time constants</em> (they are all types, so it's
     difficult form them to be something else).
  */
index d669ff5..9e259c2 100644 (file)
 #define IH_Log_ 1
 
 // Custom includes
+#include <sstream>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
 #define SENF_LOG_BLOCK_(parameters, block)                                                        \
     do {                                                                                          \
-        if (parameters::compile_enabled && parameters::enabled()) {                               \
-            std::ostream & log (parameters::log_stream());                                        \
+        if (parameters::compileEnabled && parameters::enabled()) {                                \
+            std::stringstream log;                                                                \
             do block while(0);                                                                    \
-            log << std::endl;                                                                     \
+            senf::log::write<parameters::stream, parameters::area, parameters::level>(log.str()); \
         }                                                                                         \
     } while(0) 
 
index 000164e..b4a1cbd 100644 (file)
 //#include "Log.test.hh"
 //#include "Log.test.ih"
 
-// Custom includes
-#include <sstream>
-
 // We need to put all tests into this single file to not violate the ODR
 
-#define _senf_LOG_STREAM logstream
-namespace {
-    std::stringstream logstream;
-}
-
 #define SENF_LOG_CONF (( (senf)(log)(Debug), (_), NOTICE ))
 
+// Custom includes
 #include "Logger.hh"
-
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
 
@@ -66,30 +58,46 @@ using namespace not_anonymous;
 
 BOOST_AUTO_UNIT_TEST(logger)
 {
+    senf::log::StringTarget target;
+
+    target.route<senf::log::Debug>();
+
+    // We cannot easily check the exact log string since that includes the current date/time
+    
     SENF_LOG_DEFAULT_STREAM(senf::log::Debug);
     SENF_LOG_DEFAULT_AREA(senf::log::DefaultArea);
     SENF_LOG_DEFAULT_LEVEL(senf::log::VERBOSE);
 
-    // should be disabled
     SENF_LOG(("Log message"));
+    BOOST_CHECK( target.str().empty() );
+    target.clear();
+
     SENF_LOG((senf::log::VERBOSE)("Log message 2"));
-    // should be enabled
+    BOOST_CHECK( target.str().empty() );
+    target.clear();
+    
     SENF_LOG((senf::log::IMPORTANT)("Important message"));
+    BOOST_CHECK( ! target.str().empty() );
+    target.clear();
+
     SENF_LOG((LogCritical) ("Another log message: " << 10));
+    BOOST_CHECK( ! target.str().empty() );
+    target.clear();
 
     SENF_LOG_BLOCK((senf::log::Debug) (senf::log::IMPORTANT) ({
         log << "Last message";
         log << " continued here";
     }));
+    BOOST_CHECK( ! target.str().empty() );
+    target.clear();
 
     Foo::log();
-    SENF_LOG((Foo)("Foo area"));
+    BOOST_CHECK( ! target.str().empty() );
+    target.clear();
 
-    BOOST_CHECK_EQUAL( logstream.str(), 
-                       "Important message\n"
-                       "Another log message: 10\n"
-                       "Last message continued here\n"
-                       "Foo::log\n" );
+    SENF_LOG((Foo)("Foo area"));
+    BOOST_CHECK( target.str().empty() );
+    target.clear();
 }
 
 BOOST_AUTO_UNIT_TEST(streamRegistry)
index f30c1fb..8eab9f3 100644 (file)
@@ -43,7 +43,7 @@
 
         // Define a new log stream with default level, runtime limit and compile time limit 
         // set to senf::log::MESSAGE
-        SENF_LOG_DEF_STREAM( UserLog, senf::log::MESSAAGE, senf::log::MESSAGE, senf::log::MESSAGE );
+        SENF_LOG_DEF_STREAM( UserLog, senf::log::MESSAGE, senf::log::MESSAGE, senf::log::MESSAGE );
 
         class Froblizer
         {
index d323241..9c6529c 100644 (file)
 #include <boost/preprocessor/punctuation/comma_if.hpp>
 #include <boost/mpl/vector.hpp>
 #include <boost/mpl/fold.hpp>
+#include <boost/mpl/if.hpp>
 #include "../mpl.hh"
 #include "Config.hh"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
-#ifndef _senf_LOG_STREAM
-#   define _senf_LOG_STREAM std::cerr
-#endif
-
 namespace senf {
 namespace log {
     
@@ -107,13 +104,20 @@ namespace detail {
     template <class Base>
     struct Parameters : public Base
     {
-        static bool const compile_enabled = senf::log::Enabled<
+        typedef typename boost::mpl::if_c< Base::level::value == NONE::value, 
+                                           typename Base::stream::defaultLevel, 
+                                           typename Base::level >::type level;
+
+        static bool const compileEnabled = senf::log::Enabled<
             typename Base::stream, 
             typename Base::area, 
-            typename Base::level>::value;
+            level>::value;
 
-        static bool enabled() { return compile_enabled; }
-        static std::ostream & log_stream() { return _senf_LOG_STREAM; }
+        static bool enabled() { 
+            return compileEnabled
+                && Base::area::instance().streamLimit(Base::stream::instance()) 
+                <= Base::level::value;
+        }
     };
 
     /// Internal: Empty base class
index 5eae6c2..13b8f68 100644 (file)
@@ -43,6 +43,7 @@ namespace detail {
         
         std::string fullName() const;
         virtual std::string v_name() const;
+        virtual unsigned defaultRuntimeLimit() const = 0;
 
         void init();
 
diff --git a/Utils/Logger/StringTarget.cti b/Utils/Logger/StringTarget.cti
new file mode 100644 (file)
index 0000000..fc9880b
--- /dev/null
@@ -0,0 +1,64 @@
+// $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 StringTarget inline template implementation */
+
+//#include "StringTarget.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::StringTarget
+
+prefix_ senf::log::StringTarget::StringTarget()
+    : IOStreamTarget(stream_base::member)
+{}
+
+prefix_ std::string senf::log::StringTarget::str()
+    const
+{
+    return stream_base::member.str();
+}
+
+prefix_ void senf::log::StringTarget::clear()
+{
+    stream_base::member.str("");
+}
+
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\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:
diff --git a/Utils/Logger/StringTarget.hh b/Utils/Logger/StringTarget.hh
new file mode 100644 (file)
index 0000000..6aa740b
--- /dev/null
@@ -0,0 +1,85 @@
+// $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 StringTarget public header */
+
+#ifndef HH_StringTarget_
+#define HH_StringTarget_ 1
+
+// Custom includes
+#include <sstream>
+#include "IOStreamTarget.hh"
+
+//#include "StringTarget.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+  
+    /** \brief Store log messages in a string buffer
+      */
+    class StringTarget 
+        : private boost::base_from_member<std::stringstream>,
+          public IOStreamTarget
+    {
+        typedef boost::base_from_member<std::stringstream> stream_base;
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        StringTarget();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        std::string str() const;
+        void clear();
+
+    protected:
+
+    private:
+
+    };
+
+}}        
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "StringTarget.cci"
+//#include "StringTarget.ct"
+#include "StringTarget.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:
index 651671e..997696a 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // senf::log::Target
 
+prefix_ senf::log::Target::Target()
+{
+    TargetRegistry::instance().registerTarget(this);
+}
+
 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
+        RIB::reverse_iterator i (rib_.rbegin());
+        unroute(i->stream, i->area, i->level);
+    }
+    TargetRegistry::instance().unregisterTarget(this);
+}
 
-prefix_ void senf::log::Target::write(detail::StreamBase const & stream, 
-                                      detail::AreaBase const & area,
-                                      unsigned level, std::string const & message)
+prefix_ void senf::log::Target::write(boost::posix_time::ptime timestamp,
+                                      detail::StreamBase const & stream,
+                                      detail::AreaBase const & area, unsigned level,
+                                      std::string const & message)
 {
     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->level <= level ) {
-            v_write(stream.v_name(), area.v_name(), level, message);
+             (i->level == NONE::value ? i->stream->defaultRuntimeLimit() : i->level) <= level ) {
+            v_write(timestamp, stream.v_name(), area.v_name(), level, message);
             return;
         }
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::log::TargetRegistry
+
+prefix_ void senf::log::TargetRegistry::write(detail::StreamBase const & stream,
+                                              detail::AreaBase const & area, unsigned level,
+                                              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);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Target.mpp"
index 07db6d6..129bef5 100644 (file)
@@ -78,6 +78,19 @@ prefix_ void senf::log::Target::unroute(detail::StreamBase const * stream,
     // can never lower the logging limit. Not updating the cache just reduces the performance.
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::log::TargetRegistry
+
+prefix_ void senf::log::TargetRegistry::registerTarget(Target * target)
+{
+    targets_.insert(target);
+}
+
+prefix_ void senf::log::TargetRegistry::unregisterTarget(Target * target)
+{
+    targets_.erase(target);
+}
+
 /////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
diff --git a/Utils/Logger/Target.cti b/Utils/Logger/Target.cti
new file mode 100644 (file)
index 0000000..ea7f5e2
--- /dev/null
@@ -0,0 +1,93 @@
+// $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 inline template implementation */
+
+//#include "Target.ih"
+
+// Custom includes
+#include "Levels.hh"
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::log::Target
+
+template <class Stream>
+prefix_ void senf::log::Target::route()
+{
+    route(&Stream::instance(), 0, NONE::value);
+}
+
+template <class Stream, class Arg0>
+prefix_ void senf::log::Target::route()
+{
+    route<Arg0>(&Stream::instance(), static_cast<Arg0*>(0));
+}
+
+template <class Stream, class Area, class Level>
+prefix_ void senf::log::Target::route()
+{
+    route(&Stream::instance(), &Area::instance(), Level::value);
+}
+
+////////////////////////////////////////
+// private members
+
+template <class Area>
+prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
+                                      detail::AreaBase const *)
+{
+    route(stream, &Area::instance(), NONE::value);
+}
+
+template <class Level>
+prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
+                                      detail::LevelBase const *)
+{
+    route(stream, 0, Level::value);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// namespace senf::log members
+
+template <class Stream, class Area, class Level>
+prefix_ void senf::log::write(std::string msg)
+{
+    TargetRegistry::instance().write(Stream::instance(), Area::instance(), Level::value, msg);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\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:
index 6298800..9a47194 100644 (file)
 #define HH_Target_ 1
 
 // Custom includes
+#include <set>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/utility.hpp>
 #include "../singleton.hh"
+#include "../mpl.hh"
 #include "StreamRegistry.hh"
 #include "AreaRegistry.hh"
 
@@ -37,6 +41,8 @@
 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
@@ -45,8 +51,7 @@ namespace log {
         passed the log message and a complete set of logging parameters (\e stream, \e area and \e
         level).
       */
-    class Target
-        : public senf::singleton<Target>
+    class Target : private boost::noncopyable
     {
     public:
         ///////////////////////////////////////////////////////////////////////////
@@ -56,19 +61,24 @@ namespace log {
         ///\name Structors and default members
         ///@{
 
+        Target();
         virtual ~Target();
 
-        // default default constructor
-        // default copy constructor
-        // default copy assignment
-        // default destructor
+        ///@}
+
+        template <class Stream>
+        void route();
 
-        // no conversion constructors
+        template <class Stream, class Arg0>
+        void route();
 
-        ///@}
+        template <class Stream, class Area, class Level>
+        void route();
 
     protected:
 
+        std::string timestamp();
+
     private:
 
         void route(detail::StreamBase const * stream, detail::AreaBase const * area, 
@@ -76,15 +86,30 @@ namespace log {
         void unroute(detail::StreamBase const * stream, detail::AreaBase const * area, 
                      unsigned level);
 
+        template <class Area>
+        void route(detail::StreamBase const * stream, detail::AreaBase const *);
+
+        template <class Level>
+        void route(detail::StreamBase const * stream, detail::LevelBase const *);
+
         void updateAreaCache(detail::AreaBase const & area, detail::StreamBase const * stream,
                              unsigned level);
 
-        void write(detail::StreamBase const & stream, detail::AreaBase const & area, 
-                   unsigned level, std::string const & message);
-        
-        virtual void v_write(std::string const & stream, std::string const & area, unsigned level,
+        void write(boost::posix_time::ptime timestamp, detail::StreamBase const & stream,
+                   detail::AreaBase const & area, unsigned level, std::string const & message);
+
+#   ifdef DOXYGEN
+    protected:
+#   endif
+
+        virtual void v_write(boost::posix_time::ptime, std::string const & stream, 
+                             std::string const & area, unsigned level, 
                              std::string const & message) = 0;
 
+#   ifdef DOXYGEN
+    private:
+#   endif
+
         struct RoutingEntry 
         {
             RoutingEntry(detail::StreamBase const * stream_, detail::AreaBase const * area_, 
@@ -104,14 +129,43 @@ namespace log {
         typedef std::vector<RoutingEntry> RIB;
 
         RIB rib_;
+        
+        friend class TargetRegistry;
     };
 
+    /** \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////////////////////////////////////////
 #include "Target.cci"
 //#include "Target.ct"
-//#include "Target.cti"
+#include "Target.cti"
 #endif
 
 \f
index bb9115e..761ebf4 100644 (file)
@@ -39,6 +39,15 @@ namespace mpl {
     /** \defgroup senfmpl Low-level template meta programming helpers
      */
 
+    /** \brief Marker class for empty default values etc.
+
+        This is like Boosts \c boost::mpl::na just an empty class used as template default argument
+        to mark missing arguments 
+        
+        \note Don't use this as an empty base class. We may add some informative members to this.
+     */
+    struct nil {};
+
     /** \brief Return-value type used to implement overload selection
 
         The senf::mpl::rv type is used together with \ref SENF_MPL_RV() to select template