Utils/Logger: Add console directory to target
g0dil [Fri, 6 Feb 2009 00:03:23 +0000 (00:03 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1100 270642c3-0616-0410-b53a-bc976706d245

18 files changed:
Socket/ServerSocketHandle.cti
Utils/Console/Parse.test.cc
Utils/Console/Server.cc
Utils/Console/Server.ih
Utils/Logger/ConsoleTarget.cci
Utils/Logger/FileTarget.cc
Utils/Logger/IOStreamTarget.cci
Utils/Logger/IOStreamTarget.hh
Utils/Logger/StringTarget.cti
Utils/Logger/SyslogTarget.cci
Utils/Logger/SyslogUDPTarget.cc
Utils/Logger/SyslogUDPTarget.cci
Utils/Logger/Target.cc
Utils/Logger/Target.cci
Utils/Logger/Target.hh
Utils/Logger/Target.ih
Utils/String.cti [new file with mode: 0644]
Utils/String.hh

index 4044b1e..132625d 100644 (file)
@@ -114,8 +114,8 @@ template <class SPolicy>
 prefix_ typename senf::ServerSocketHandle<SPolicy>::ClientHandle
 senf::ServerSocketHandle<SPolicy>::acceptfrom(Address & addr)
 {
-    return ClienttHandle(this->protocol().clone(),
-                         SPolicy::CommunicationPolicy::accept(*this,addr));
+    return ClientHandle(this->body().clone(
+                            SPolicy::CommunicationPolicy::accept(*this,addr), false));
 }
 
 ///////////////////////////////////////////////////////////////////////////
index 5a2295f..4570fb0 100644 (file)
@@ -227,28 +227,28 @@ BOOST_AUTO_UNIT_TEST(commandParser)
         
         ++ args;
         BOOST_REQUIRE( args != info.arguments().end() );
-        BOOST_REQUIRE_EQUAL( args->size(), 1 );
+        BOOST_REQUIRE_EQUAL( args->size(), 1u );
         BOOST_CHECK_EQUAL( args->begin()->value(), tokens[1] );
         
         ++ args;
         BOOST_REQUIRE( args != info.arguments().end() );
-        BOOST_REQUIRE_EQUAL( args->size(), 1 );
+        BOOST_REQUIRE_EQUAL( args->size(), 1u );
         BOOST_CHECK_EQUAL( args->begin()->value(), tokens[2] );
         
         ++ args;
         BOOST_REQUIRE( args != info.arguments().end() );
-        BOOST_REQUIRE_EQUAL( args->size(), 8 );
+        BOOST_REQUIRE_EQUAL( args->size(), 8u );
         for (unsigned i (0); i<8; ++i)
             BOOST_CHECK_EQUAL( args->begin()[i].value(), tokens[4+i] );
         
         ++ args;
         BOOST_REQUIRE( args != info.arguments().end() );
-        BOOST_REQUIRE_EQUAL( args->size(), 1 );
+        BOOST_REQUIRE_EQUAL( args->size(), 1u );
         BOOST_CHECK_EQUAL( args->begin()->value(), tokens[13] );
         
         ++ args;
         BOOST_REQUIRE( args != info.arguments().end() );
-        BOOST_REQUIRE_EQUAL( args->size(), 1 );
+        BOOST_REQUIRE_EQUAL( args->size(), 1u );
         BOOST_CHECK_EQUAL( args->begin()->value(), tokens[14] );
         
         ++ args;
index 719f527..41475c2 100644 (file)
@@ -106,12 +106,12 @@ prefix_ void senf::console::Server::newClient(int event)
     ServerHandle::ClientHandle client (handle_.accept());
     boost::intrusive_ptr<Client> p (new Client(*this, client));
     clients_.insert( p );
-    SENF_LOG(( "Registered new client " << p.get() ));
+    SENF_LOG(( "Registered new client " << client.peer() ));
 }
 
 prefix_ void senf::console::Server::removeClient(Client & client)
 {
-    SENF_LOG(( "Disposing client " << & client ));
+    SENF_LOG(( "Disposing client " << client.handle().peer() ));
     // THIS DELETES THE CLIENT INSTANCE !!
     clients_.erase(boost::intrusive_ptr<Client>(&client));
 }
@@ -224,8 +224,9 @@ senf::console::detail::NoninteractiveClientReader::newData(int event)
 // senf::console::Client
 
 prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
-    : out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server),
-      handle_ (handle), 
+    : out_t(boost::ref(*this)), 
+      senf::log::IOStreamTarget("client-" + senf::str(handle.peer()), out_t::member), 
+      server_ (server), handle_ (handle), 
       readevent_ ("senf::console::Client::interactive_check", 
                   boost::bind(&Client::setNoninteractive,this), 
                   handle, scheduler::FdEvent::EV_READ, false),
@@ -322,33 +323,6 @@ prefix_ void senf::console::Client::v_write(senf::log::time_type timestamp,
     reader_->enablePrompt();
 }
 
-prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client const & client)
-{
-    typedef ClientSocketHandle< MakeSocketPolicy<
-        INet4AddressingPolicy,ConnectedCommunicationPolicy>::policy > V4Socket;
-    typedef ClientSocketHandle< MakeSocketPolicy<
-        INet6AddressingPolicy,ConnectedCommunicationPolicy>::policy > V6Socket;
-
-    try {
-        if (check_socket_cast<V4Socket>(client.handle()))
-            os << dynamic_socket_cast<V4Socket>(client.handle()).peer();
-        else if (check_socket_cast<V6Socket>(client.handle()))
-            os << dynamic_socket_cast<V6Socket>(client.handle()).peer();
-        else
-            os << static_cast<void const *>(&client);
-    }
-    catch (SystemException &) {
-        os << "0.0.0.0:0";
-    }
-        
-    return os;
-}
-
-prefix_ std::ostream & senf::console::operator<<(std::ostream & os, Client * client)
-{
-    return os << *client;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::Client::SysBacktrace
 
index d7b73e7..5e110fa 100644 (file)
@@ -88,7 +88,7 @@ namespace detail {
 
     typedef senf::ServerSocketHandle<
         senf::MakeSocketPolicy< senf::TCPv4SocketProtocol::Policy, 
-                                senf::UnspecifiedAddressingPolicy>::policy > ServerHandle;
+                                senf::BSDAddressingPolicy>::policy > ServerHandle;
 
     /** \brief Internal: Generic client interface
 
index d1ff8e5..5fc13c1 100644 (file)
@@ -40,7 +40,7 @@ prefix_ senf::log::ConsoleTarget & senf::log::ConsoleTarget::instance()
 }
 
 prefix_ senf::log::ConsoleTarget::ConsoleTarget()
-    : IOStreamTarget(std::cout)
+    : IOStreamTarget("console", std::cout)
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
index 0467573..2baff33 100644 (file)
@@ -33,7 +33,8 @@
 ///////////////////////////////cc.p////////////////////////////////////////
 
 prefix_ senf::log::FileTarget::FileTarget(std::string file)
-    : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(ofstream_t::member), file_(file)
+    : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(file, ofstream_t::member), 
+      file_(file)
 {}
 
 prefix_ void senf::log::FileTarget::reopen()
index 8e55b74..e4f7968 100644 (file)
@@ -30,8 +30,8 @@
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::ostream & os)
-    : stream_ (os)
+prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::string const & name, std::ostream & os)
+    : Target(name), stream_ (os)
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
index bb1c0d5..229ab63 100644 (file)
@@ -57,7 +57,7 @@ namespace log {
         ///\name Structors and default members
         ///@{
 
-        explicit IOStreamTarget(std::ostream & os);
+        IOStreamTarget(std::string const & name, std::ostream & os);
 
         ///@}
         ///////////////////////////////////////////////////////////////////////////
index 1157206..a1e6a37 100644 (file)
@@ -34,7 +34,7 @@
 // senf::log::StringTarget
 
 prefix_ senf::log::StringTarget::StringTarget()
-    : IOStreamTarget(stream_base::member)
+    : IOStreamTarget("membuffer", stream_base::member)
 {}
 
 prefix_ std::string senf::log::StringTarget::str()
index fe71ce3..f9c6271 100644 (file)
@@ -31,7 +31,7 @@
 ///////////////////////////////cci.p///////////////////////////////////////
 
 prefix_ senf::log::SyslogTarget::SyslogTarget(int facility)
-    : facility_ (facility)
+    : Target("syslog"), facility_ (facility)
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
index 0538fe0..03a055f 100644 (file)
@@ -44,6 +44,9 @@ prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::strin
     detail::quoteNonPrintable(m);
 
     std::stringstream prfstream;
+    // The space after the '>' is there on purpose: It ensures, that the prefix (which may be empty)
+    // or message will not inadvertently be interpreted as date or hostname by a receiving syslog
+    // daemon or proxy
     prfstream << '<' << (facility_ | senf::log::SyslogTarget::LEVELMAP[level]) << "> "
               << prefix(timestamp, stream, area, level);
     std::string const & prf (prfstream.str());
index 4078e3d..52a5055 100644 (file)
 
 // Custom includes
 #include "../../Socket/Protocols/INet/ConnectedUDPSocketHandle.hh"
+#include "../String.hh"
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4Address const & target,
                                                     int facility)
-    : facility_ (facility),
+    : Target("udp-" + senf::str(target)), facility_ (facility),
       handle_ ( senf::ConnectedUDPv4ClientSocketHandle(senf::INet4SocketAddress(target, 514u)) )
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4SocketAddress const & target,
                                                     int facility)
-    : facility_ (facility),
+    : Target("udp-" + senf::str(target)), facility_ (facility),
       handle_ ( senf::ConnectedUDPv4ClientSocketHandle(target) )
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6Address const & target,
                                                     int facility)
-    : facility_ (facility),
+    : Target("udp-" + senf::str(target)), facility_ (facility),
       handle_ ( senf::ConnectedUDPv6ClientSocketHandle(senf::INet6SocketAddress(target, 514u)) )
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6SocketAddress const & target,
                                                     int facility)
-    : facility_ (facility),
+    : Target("udp-" + senf::str(target)), facility_ (facility),
       handle_ ( senf::ConnectedUDPv6ClientSocketHandle(target) )
 {}
 
index 068631c..22d5823 100644 (file)
 
 // Custom includes
 #include <algorithm>
+#include <boost/format.hpp>
 #include "ConsoleTarget.hh"
+#include "../Console/Console.hh"
+#include "../Console/Sysdir.hh"
+#include "../membind.hh"
 
 //#include "Target.mpp"
 #define prefix_
 ///////////////////////////////////////////////////////////////////////////
 // senf::log::Target
 
-prefix_ senf::log::Target::Target()
+namespace senf {
+namespace log {
+
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER( Target, action_t, (ACCEPT)(REJECT) );
+
+}}
+
+namespace {
+namespace local {
+
+    enum Level { 
+        VERBOSE = senf::log::VERBOSE::value, 
+        NOTICE = senf::log::NOTICE::value, 
+        MESSAGE = senf::log::MESSAGE::value, 
+        IMPORTANT = senf::log::IMPORTANT::value, 
+        CRITICAL = senf::log::CRITICAL::value, 
+        FATAL = senf::log::FATAL::value
+    };
+    SENF_CONSOLE_REGISTER_ENUM( Level, 
+                                (VERBOSE)(NOTICE)(MESSAGE)(IMPORTANT)(CRITICAL)(FATAL) );
+    
+}}
+
+prefix_ senf::log::Target::Target(std::string const & name)
 {
-    detail::TargetRegistry::instance().registerTarget(this);
+    namespace kw = senf::console::kw;
+
+    detail::TargetRegistry::instance().registerTarget(this, name);
+    consoleDir_().add("list", senf::membind(&Target::consoleList, this))
+        .doc("Show routing table\n"
+             "\n"
+             "Columns:\n"
+             "    #       rule index\n"
+             "    STREAM  stream to match, empty to match all streams\n"
+             "    AREA    area to match, empty to match all targets\n"
+             "    LEVEL   match messages with level above this. Log levels in increasing order\n"
+             "            are:\n"
+             "                verbose, notice, message, important, critical, fatal\n"
+             "    ACTION  action to take: accept or reject");
+    consoleDir_().add("route", 
+                      boost::function<void (std::string const &, std::string const &,
+                                            local::Level, action_t, int)>(
+                                                senf::membind(
+                                                    static_cast<void (Target::*)(
+                                                        std::string const &, std::string const &,
+                                                        unsigned, action_t, int)>(&Target::route),
+                                                    this)))
+        .arg("stream", "stream to match or empty to match any stream",
+             kw::default_value="")
+        .arg("area", "area to match or empty to match any area",
+             kw::default_value="")
+        .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL",
+             kw::default_value=local::VERBOSE)
+        .arg("action", "routing action, one of: ACCEPT, REJECT",
+             kw::default_value=ACCEPT)
+        .arg("index", "index at which to insert new rule",
+             kw::default_value=-1)
+        .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
+             "with the first entry. The action of the first matching entry determines the\n"
+             "handling of the message.\n"
+             "\n"
+             "Examples:\n"
+             "\n"
+             "    route\n"
+             "        route all messages to this target.\n"
+             "\n"
+             "    route \"\" my::Class\n"
+             "        route all messages which are in the my::Class area.\n"
+             "\n"
+             "    route senf::log::Debug \"\" VERBOSE REJECT\n"
+             "    route \"\" \"\" VERBOSE\n"
+             "        route all messages not in the senf::log::Debug stream to the current area.\n"
+             "\n"
+             "The additional optional index argument identifies the position in the routing table\n"
+             "where the new routing entry will be added. Positive numbers count from the\n"
+             "beginning, 0 being the first routing entry. Negative values count from the end.\n");
+    consoleDir_().add("unroute",
+                      senf::membind(static_cast<void (Target::*)(int)>(&Target::unroute), this))
+        .arg("index", "index of routing entry to remove")
+        .overloadDoc("Remove routing entry with the given index");
+    consoleDir_().add("unroute", 
+                      boost::function<void (std::string const &, std::string const &,
+                                            local::Level, action_t)>(
+                                                senf::membind(
+                                                    static_cast<void (Target::*)(
+                                                        std::string const &, std::string const &,
+                                                        unsigned, action_t)>(&Target::unroute),
+                                                    this)))
+        .arg("stream", "stream to match or empty to match any stream",
+             kw::default_value="")
+        .arg("area", "area to match or empty to match any area",
+             kw::default_value="")
+        .arg("level", "log level, one of: VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL",
+             kw::default_value=local::VERBOSE)
+        .arg("action", "routing action, one of: ACCEPT, REJECT",
+             kw::default_value=ACCEPT)
+        .overloadDoc("Remove the routing entry matching the specified arguments.");
+    consoleDir_().add("flush", senf::membind(&Target::flush, this))
+        .doc("Remove all routing entries clearing the routing table. This will disable all\n"
+             "logging output on this target.");
 }
 
 prefix_ senf::log::Target::~Target()
@@ -56,9 +157,12 @@ prefix_ senf::log::Target::~Target()
 prefix_ void senf::log::Target::route(std::string const & stream, std::string const & area,
                                       unsigned level, action_t action, int index)
 {
-    detail::StreamBase const * s (StreamRegistry::instance().lookup(stream));
-    if (!s)
-        throw InvalidStreamException();
+    detail::StreamBase const * s (0);
+    if (! stream.empty()) {
+        s = StreamRegistry::instance().lookup(stream);
+        if (!s)
+            throw InvalidStreamException();
+    }
     detail::AreaBase const * a (0);
     if (! area.empty()) {
         a = AreaRegistry::instance().lookup(area);
@@ -71,9 +175,12 @@ prefix_ void senf::log::Target::route(std::string const & stream, std::string co
 prefix_ void senf::log::Target::unroute(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::StreamBase const * s (0);
+    if (! stream.empty()) {
+        s = StreamRegistry::instance().lookup(stream);
+        if (!s)
+            throw InvalidStreamException();
+    }
     detail::AreaBase const * a (0);
     if (! area.empty()) {
         a = AreaRegistry::instance().lookup(area);
@@ -124,6 +231,15 @@ prefix_ void senf::log::Target::flush()
 }
 
 ////////////////////////////////////////
+// protected members
+
+prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
+    : fallbackRouting_(true)
+{
+    console::sysdir().add("log", consoleDir_());
+}
+
+////////////////////////////////////////
 // private members
 
 prefix_ void senf::log::Target::route(detail::StreamBase const * stream,
@@ -214,9 +330,44 @@ prefix_ void senf::log::Target::write(time_type timestamp,
         }
 }
 
+namespace {
+    std::string formatLabel(std::string const & l)
+    {
+        if (l.empty())
+            return "-";
+        if (l.size() > 29)
+            return l.substr(l.size()-29);
+        return l;
+    }
+}
+
+prefix_ void senf::log::Target::consoleList(std::ostream & os)
+{
+    static char const * levels[] = { 
+        "none", "verbose", "notice", "message", "important", "critical", "fatal", "disabled" };
+
+    boost::format fmt ("%2d %-29s %-29s %-9s %-6s\n");
+    os << fmt % "#" % "STREAM" % "AREA" % "LEVEL" % "ACTION";
+    unsigned n (0);
+    for (iterator i (begin()); i != end(); ++i, ++n)
+        os << fmt 
+            % n 
+            % formatLabel(i->stream())
+            % formatLabel(i->area())
+            % levels[i->level()]
+            % (i->action() == ACCEPT ? "accept" : "reject");
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::log::detail::TargetRegistry
 
+prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target,
+                                                               std::string const & name)
+{
+    targets_.insert(target);
+    consoleDir_().add(name, target->consoleDir_());
+}
+
 prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
                                                       AreaBase const & area, unsigned level,
                                                       std::string const & msg)
index 10e58ab..09c5706 100644 (file)
@@ -137,15 +137,6 @@ prefix_ bool senf::log::detail::TargetRegistry::fallbackRouting()
 ////////////////////////////////////////
 // private members
 
-prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
-    : fallbackRouting_(true)
-{}
-
-prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target)
-{
-    targets_.insert(target);
-}
-
 prefix_ void senf::log::detail::TargetRegistry::unregisterTarget(Target * target)
 {
     targets_.erase(target);
index 9065ef4..69fd1d1 100644 (file)
@@ -36,6 +36,7 @@
 #include "StreamRegistry.hh"
 #include "../Exception.hh"
 #include "TimeSource.hh"
+#include "../Console/LazyDirectory.hh"
 
 //#include "Target.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -185,7 +186,7 @@ namespace log {
         ///\name Structors and default members
         ///@{
 
-        Target();
+        explicit Target(std::string const & name);
         virtual ~Target();
 
         ///@}
@@ -351,6 +352,8 @@ namespace log {
         void write(time_type timestamp, detail::StreamBase const & stream,
                    detail::AreaBase const & area, unsigned level, std::string const & message);
 
+        void consoleList(std::ostream & os);
+
 #   ifdef DOXYGEN
     protected:
 #   endif
@@ -382,6 +385,8 @@ namespace log {
 
         RIB rib_;
 
+        console::LazyDirectory consoleDir_;
+
         friend class detail::AreaBase;
         friend class detail::TargetRegistry;
     };
index a083871..c6d4efb 100644 (file)
@@ -30,6 +30,7 @@
 #include <memory>
 #include <boost/type_traits/is_same.hpp>
 #include <boost/static_assert.hpp>
+#include "../Console/LazyDirectory.hh"
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
@@ -53,13 +54,15 @@ namespace detail {
     private:
         TargetRegistry();
         
-        void registerTarget(Target * target);
+        void registerTarget(Target * target, std::string const & name);
         void unregisterTarget(Target * target);
 
         typedef std::set<Target *> Targets;
         Targets targets_;
 
         bool fallbackRouting_;
+
+        console::LazyDirectory consoleDir_;
         
         friend class senf::log::Target;
         friend class senf::singleton<TargetRegistry>;
diff --git a/Utils/String.cti b/Utils/String.cti
new file mode 100644 (file)
index 0000000..8d39ba9
--- /dev/null
@@ -0,0 +1,52 @@
+// $Id$
+//
+// Copyright (C) 2009 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     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 String inline template implementation */
+
+//#include "String.ih"
+
+// Custom includes
+#include <boost/lexical_cast.hpp>
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class T>
+prefix_ std::string senf::str(T const & t)
+{
+    return boost::lexical_cast<std::string>(t);
+}
+
+///////////////////////////////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 10f523e..623068b 100644 (file)
@@ -42,12 +42,15 @@ namespace senf {
     template <class ForwardReadableRange>
     std::string stringJoin(ForwardReadableRange const & range, std::string sep);
 
+    template <class T>
+    std::string str(T const & t);
+
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "String.cci"
 #include "String.ct"
-//#include "String.cti"
+#include "String.cti"
 #endif
 
 \f