Socket/Protocols/INet: Implement address input streaming
g0dil [Sat, 7 Feb 2009 19:00:49 +0000 (19:00 +0000)]
Utils/Logger: Implement dynmaic targets

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

18 files changed:
Socket/Protocols/INet/INet4Address.cc
Socket/Protocols/INet/INet4Address.hh
Socket/Protocols/INet/INet6Address.cc
Socket/Protocols/INet/INet6Address.hh
Socket/Protocols/INet/INetAddressing.cc
Socket/Protocols/INet/INetAddressing.cci
Socket/Protocols/INet/INetAddressing.hh
Utils/Console/Executor.cc
Utils/Logger/FileTarget.cc
Utils/Logger/FileTarget.hh
Utils/Logger/SyslogTarget.cc
Utils/Logger/SyslogTarget.hh
Utils/Logger/SyslogUDPTarget.cc
Utils/Logger/SyslogUDPTarget.hh
Utils/Logger/Target.cc
Utils/Logger/Target.cci
Utils/Logger/Target.ih
Utils/Termlib/Editor.cc

index 0c100fb..d83c034 100644 (file)
@@ -161,6 +161,20 @@ prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Address const &
     return os;
 }
 
+prefix_ std::istream & senf::operator>>(std::istream & is, INet4Address & addr)
+{
+    std::string s;
+    if (!(is >> s))
+        return is;
+    try {
+        addr = INet4Address::from_string(s);
+    }
+    catch (AddressException &) {
+        is.setstate(std::ios::failbit);
+    }
+    return is;
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "INet4Address.mpp"
index e11982d..e69c224 100644 (file)
@@ -175,6 +175,7 @@ namespace senf {
         \related INet4Address
      */
     std::ostream & operator<<(std::ostream & os, INet4Address const & addr);
+    std::istream & operator>>(std::istream & os, INet4Address & addr);
 
     /** \brief CHeck INet4Address against a fixed network prefix
 
index 6c76f77..9aa5238 100644 (file)
@@ -105,6 +105,19 @@ prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Address const &
     return os;
 }
 
+prefix_ std::istream & senf::operator>>(std::istream & is, INet6Address & addr)
+{
+    std::string s;
+    if (!(is >> s))
+        return is;
+    try {
+        addr = INet6Address::from_string(s);
+    }
+    catch (AddressException &) {
+        is.setstate(std::ios::failbit);
+    }
+    return is;
+}
 
 senf::INet6Address const senf::INet6Address::None;
 senf::INet6Address const senf::INet6Address::Loopback   (0u,0u,0u,0u,0u,0u,0u,1u);
index 98fb726..600ed57 100644 (file)
@@ -283,6 +283,7 @@ namespace senf {
         \related INet6Address
      */
     std::ostream & operator<<(std::ostream & os, INet6Address const & addr);
+    std::istream & operator>>(std::istream & is, INet6Address & addr);
 
     /** \brief Check INet6Address against a fixed network prefix
 
index fdb4ee1..e224408 100644 (file)
@@ -71,6 +71,26 @@ prefix_ senf::INet4SocketAddress::INet4SocketAddress(unsigned p)
     port(p);
 }
 
+prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress const & addr)
+{
+    os << addr.address() << ":" << addr.port();
+    return os;
+}
+
+prefix_ std::istream & senf::operator>>(std::istream & is, INet4SocketAddress & addr)
+{
+    std::string s;
+    if (!(is >> s))
+        return is;
+    try {
+        addr = INet4SocketAddress(s);
+    }
+    catch (AddressException &) {
+        is.setstate(std::ios::failbit);
+    }
+    return is;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::INet6SocketAddress
 
@@ -131,6 +151,30 @@ prefix_ void senf::INet6SocketAddress::assignIface(std::string const & iface)
     }
 }
 
+prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr)
+{
+    os << '[' << addr.address();
+    std::string iface (addr.iface());
+    if (! iface.empty())
+        os << '%' << iface;
+    os << "]:" << addr.port();
+    return os;
+}
+
+prefix_ std::istream & senf::operator>>(std::istream & is, INet6SocketAddress & addr)
+{
+    std::string s;
+    if (!(is >> s))
+        return is;
+    try {
+        addr = INet6SocketAddress(s);
+    }
+    catch (AddressException &) {
+        is.setstate(std::ios::failbit);
+    }
+    return is;
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "INetAddressing.mpp"
index dc6bd0c..5561938 100644 (file)
@@ -70,12 +70,6 @@ prefix_ void senf::INet4SocketAddress::port(unsigned p)
     addr_.sin_port = htons(p);
 }
 
-prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4SocketAddress const & addr)
-{
-    os << addr.address() << ":" << addr.port();
-    return os;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // senf::INet6SocketAddress
 
@@ -143,16 +137,6 @@ prefix_ void senf::INet6SocketAddress::iface(std::string const & iface)
     assignIface(iface);
 }
 
-prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6SocketAddress const & addr)
-{
-    os << '[' << addr.address();
-    std::string iface (addr.iface());
-    if (! iface.empty())
-        os << '%' << iface;
-    os << "]:" << addr.port();
-    return os;
-}
-
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index f9327b5..a54b95e 100644 (file)
@@ -109,6 +109,7 @@ namespace senf {
         \related INet4SocketAddress
      */
     std::ostream & operator<<(std::ostream & os, INet4SocketAddress const & addr);
+    std::istream & operator>>(std::istream & is, INet4SocketAddress & addr);
 
     /** \brief IPv6 socket address
 
@@ -202,6 +203,7 @@ namespace senf {
         \related INet6SocketAddress
      */
     std::ostream & operator<<(std::ostream & os, INet6SocketAddress const & addr);
+    std::istream & operator>>(std::istream & is, INet6SocketAddress & addr);
 
     /// \addtogroup policy_impl_group
     /// @{
index 04cb751..a228c33 100644 (file)
@@ -67,6 +67,7 @@ prefix_ std::string senf::console::Executor::cwdPath()
 {
     if (skipping())
         return "";
+    (void) cwd(); // ensure, cwd is live.
     return "/" + senf::stringJoin(
         senf::make_transform_range(
             boost::make_iterator_range(boost::next(cwd_.begin()), cwd_.end()),
index 2baff33..7cc2ad0 100644 (file)
 //#include "FileTarget.ih"
 
 // Custom includes
+#include "../Console/Console.hh"
 
 //#include "FileTarget.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_ senf::log::FileTarget::FileTarget(std::string file)
+prefix_ senf::log::FileTarget::FileTarget(std::string const & file)
     : ofstream_t(file.c_str(), std::ofstream::app), IOStreamTarget(file, ofstream_t::member), 
       file_(file)
-{}
+{
+    consoleDir().add( "reopen", senf::membind(
+                          static_cast<void (FileTarget::*)()>(&FileTarget::reopen),
+                          this))
+        .doc("Reopen logfile");
+    consoleDir().add("reopen", senf::membind(
+                         static_cast<void (FileTarget::*)(std::string const &)>(&FileTarget::reopen),
+                         this))
+        .arg("filename","new filename")
+        .overloadDoc("Reopen logfile under new name");
+}
 
 prefix_ void senf::log::FileTarget::reopen()
 {
@@ -43,10 +54,27 @@ prefix_ void senf::log::FileTarget::reopen()
     ofstream_t::member.open(file_.c_str(), std::ofstream::app);
 }
 
-prefix_ void senf::log::FileTarget::reopen(std::string file)
+prefix_ void senf::log::FileTarget::reopen(std::string const & file)
 {
     file_ = file;
     reopen();
+    // Rename console directory
+    console::DirectoryNode::ptr parent (consoleDir().node().parent());
+    if (parent)
+        parent->add(file, consoleDir().node().unlink());
+}
+
+prefix_ senf::log::FileTarget::RegisterConsole::RegisterConsole()
+{
+    detail::TargetRegistry::instance().consoleDir().add("file-target",&RegisterConsole::create)
+        .arg("filename", "name of logfile")
+        .doc("Create new file target.");
+}
+
+prefix_ void senf::log::FileTarget::RegisterConsole::create(std::string const & filename)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new FileTarget(filename)));
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 5c4cc34..ccd78fc 100644 (file)
@@ -65,16 +65,23 @@ namespace log {
         ///\name Structors and default members
         ///@{
 
-        explicit FileTarget(std::string file); ///< Construct FileTarget writing to \a file
+        explicit FileTarget(std::string const & filename); 
+                                        ///< 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
+        void reopen(std::string const & file);  ///< Reopen %log under a new name
 
     private:
         std::string file_;
+
+        struct RegisterConsole {
+            RegisterConsole();
+            static void create(std::string const & filename);
+            static RegisterConsole instance;
+        };
     };
 
 }}
index 6b175c6..7c85321 100644 (file)
@@ -27,6 +27,7 @@
 //#include "SyslogTarget.ih"
 
 // Custom includes
+#include "../Console/Console.hh"
 
 //#include "SyslogTarget.mpp"
 #define prefix_
@@ -45,6 +46,34 @@ prefix_ void senf::log::SyslogTarget::v_write(time_type timestamp, std::string c
         syslog(facility_ | LEVELMAP[level], "%s", message.c_str());
 }
 
+namespace senf {
+namespace log {
+
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER(SyslogTarget, LogFacility,
+                                      (AUTHPRIV)(CRON)(DAEMON)(FTP)(KERN)(LPR)(MAIL)(NEWS)(SYSLOG)
+                                      (USER)(UUCP)(LOCAL0)(LOCAL1)(LOCAL2)(LOCAL3)(LOCAL4)(LOCAL5)
+                                      (LOCAL6)(LOCAL7));
+
+}}
+
+prefix_ senf::log::SyslogTarget::RegisterConsole::RegisterConsole()
+{
+    namespace kw = senf::console::kw;
+
+    detail::TargetRegistry::instance().consoleDir().add("syslog-target",&RegisterConsole::create)
+        .arg("facility", "syslog facility to send messages to. One of\n"
+             "                  AUTHPRIV, CRON, DAEMON, FTP, KERN, LPR, MAIL, NEWS, SYSLOG, USER,\n"
+             "                  UUCP, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7",
+             kw::default_value = USER)
+        .doc("Create new syslog target.");
+}
+
+prefix_ void senf::log::SyslogTarget::RegisterConsole::create(LogFacility facility)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new SyslogTarget(facility)));
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "SyslogTarget.mpp"
index d11e448..0049f59 100644 (file)
@@ -92,6 +92,35 @@ namespace log {
 
     public:
         static int const LEVELMAP[8];
+        
+        enum LogFacility { 
+            AUTHPRIV = LOG_AUTHPRIV,
+            CRON = LOG_CRON,
+            DAEMON = LOG_DAEMON,
+            FTP = LOG_FTP,
+            KERN = LOG_KERN,
+            LOCAL0 = LOG_LOCAL0,
+            LOCAL1 = LOG_LOCAL1,
+            LOCAL2 = LOG_LOCAL2,
+            LOCAL3 = LOG_LOCAL3,
+            LOCAL4 = LOG_LOCAL4,
+            LOCAL5 = LOG_LOCAL5,
+            LOCAL6 = LOG_LOCAL6,
+            LOCAL7 = LOG_LOCAL7,
+            LPR = LOG_LPR,
+            MAIL = LOG_MAIL,
+            NEWS = LOG_NEWS,
+            SYSLOG = LOG_SYSLOG,
+            USER = LOG_USER,
+            UUCP = LOG_UUCP
+        };
+
+    private:
+        struct RegisterConsole {
+            RegisterConsole();
+            static void create(LogFacility facility);
+            static RegisterConsole instance;
+        };
     };
 
 }}
index 03a055f..af8da40 100644 (file)
@@ -30,6 +30,7 @@
 #include <sstream>
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/tokenizer.hpp>
+#include "../Console/Console.hh"
 
 //#include "SyslogUDPTarget.mpp"
 #define prefix_
@@ -68,6 +69,79 @@ prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::strin
         }
 }
 
+namespace senf {
+namespace log {
+
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER(SyslogUDPTarget, LogFacility,
+                                      (AUTHPRIV)(CRON)(DAEMON)(FTP)(KERN)(LPR)(MAIL)(NEWS)(SYSLOG)
+                                      (USER)(UUCP)(LOCAL0)(LOCAL1)(LOCAL2)(LOCAL3)(LOCAL4)(LOCAL5)
+                                      (LOCAL6)(LOCAL7));
+
+}}
+
+prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
+{
+    namespace kw = senf::console::kw;
+
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", static_cast<void (*)(INet4SocketAddress const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address", "target address to send log messages to")
+        .arg("facility", "syslog facility to send messages to. One of\n"
+             "                  AUTHPRIV, CRON, DAEMON, FTP, KERN, LPR, MAIL, NEWS, SYSLOG, USER,\n"
+             "                  UUCP, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7",
+             kw::default_value = USER)
+        .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
+             "number is omitted, it defaults to the default syslog port 514.");
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", static_cast<void (*)(INet4Address const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", static_cast<void (*)(INet6SocketAddress const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+    detail::TargetRegistry::instance().consoleDir().add(
+        "udp-target", static_cast<void (*)(INet6Address const &, LogFacility)>(
+            &RegisterConsole::create))
+        .arg("address")
+        .arg("facility", kw::default_value = USER);
+}
+
+prefix_ void
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4SocketAddress const & target,
+                                                    LogFacility facility)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+}
+
+prefix_ void
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet4Address const & target,
+                                                    LogFacility facility)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+}
+
+prefix_ void
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6SocketAddress const & target,
+                                                    LogFacility facility)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+}
+
+prefix_ void
+senf::log::SyslogUDPTarget::RegisterConsole::create(senf::INet6Address const & target,
+                                                    LogFacility facility)
+{
+    detail::TargetRegistry::instance().dynamicTarget(
+        std::auto_ptr<Target>(new SyslogUDPTarget(target, facility)));
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "SyslogUDPTarget.mpp"
index c3d8b15..e6f35ff 100644 (file)
@@ -86,6 +86,8 @@ namespace log {
             include the \c PRI part but skip the \c HEADER part (which includes the timestamp and
             hostname) for better performance. We add a space after the \c PRI to force the syslog
             daemon to skip the \c HEADER part.
+
+        \ingroup targets
      */
     class SyslogUDPTarget
         : public Target, private detail::LogFormat
@@ -124,6 +126,44 @@ namespace log {
             senf::ConnectedCommunicationPolicy,
             senf::WriteablePolicy>::policy > Handle;
         Handle handle_;
+
+    public:
+        enum LogFacility { 
+            AUTHPRIV = LOG_AUTHPRIV,
+            CRON = LOG_CRON,
+            DAEMON = LOG_DAEMON,
+            FTP = LOG_FTP,
+            KERN = LOG_KERN,
+            LOCAL0 = LOG_LOCAL0,
+            LOCAL1 = LOG_LOCAL1,
+            LOCAL2 = LOG_LOCAL2,
+            LOCAL3 = LOG_LOCAL3,
+            LOCAL4 = LOG_LOCAL4,
+            LOCAL5 = LOG_LOCAL5,
+            LOCAL6 = LOG_LOCAL6,
+            LOCAL7 = LOG_LOCAL7,
+            LPR = LOG_LPR,
+            MAIL = LOG_MAIL,
+            NEWS = LOG_NEWS,
+            SYSLOG = LOG_SYSLOG,
+            USER = LOG_USER,
+            UUCP = LOG_UUCP
+        };
+
+    private:
+
+        struct RegisterConsole {
+            RegisterConsole();
+            static void create(senf::INet4SocketAddress const & target, 
+                               LogFacility facility = USER);
+            static void create(senf::INet4Address const & target,
+                               LogFacility facility = USER);
+            static void create(senf::INet6SocketAddress const & target,
+                               LogFacility facility = USER);
+            static void create(senf::INet6Address const & target,
+                               LogFacility facility = USER);
+            static RegisterConsole instance;
+        };
     };
 
 }}
index a35fca6..7218a24 100644 (file)
@@ -241,12 +241,21 @@ prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
              kw::default_value = "senf::log::Debug")
         .arg("area","area to write message to",
              kw::default_value = "senf::log::DefaultArea")
-        .arg("level", "log level",
+        .arg("level", "log level, one of:\n"
+             "                  VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL, FATAL",
              kw::default_value = MESSAGE)
         .arg("message", "message to write")
         .doc("Write log message");
 }
 
+prefix_ senf::log::detail::TargetRegistry::~TargetRegistry()
+{
+    Targets::iterator i (dynamicTargets_.begin());
+    Targets::iterator const i_end (dynamicTargets_.end());
+    for (; i != i_end; ++i)
+        delete *i;
+}
+
 prefix_ void senf::log::detail::TargetRegistry::consoleAreas(std::ostream & os)
 {
     AreaRegistry::iterator i (AreaRegistry::instance().begin());
@@ -404,6 +413,15 @@ prefix_ void senf::log::Target::consoleList(std::ostream & os)
 ///////////////////////////////////////////////////////////////////////////
 // senf::log::detail::TargetRegistry
 
+prefix_ void senf::log::detail::TargetRegistry::dynamicTarget(std::auto_ptr<Target> target)
+{
+    target->consoleDir().add("remove", boost::function<void ()>(
+                                 boost::bind(
+                                     &TargetRegistry::consoleRemoveTarget, this, target.get())))
+        .doc("Remove target.");
+    dynamicTargets_.insert(target.release());
+}
+
 prefix_ void senf::log::detail::TargetRegistry::registerTarget(Target * target,
                                                                std::string const & name)
 {
@@ -423,6 +441,13 @@ prefix_ void senf::log::detail::TargetRegistry::write(StreamBase const & stream,
     else
         area.write( TimeSource::now(), stream, level, msg );
 }
+
+prefix_ void senf::log::detail::TargetRegistry::consoleRemoveTarget(Target * target)
+{
+    dynamicTargets_.erase(target);
+    delete target;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // namespace members
 
@@ -434,6 +459,13 @@ prefix_ std::ostream & senf::log::operator<<(std::ostream & os, senf::log::Targe
     return os;
 }
 
+//////////////////////////////////////////////////////////////////////////
+// I need to put this here, otherwise the file target will not be registered
+// if it is not used ... :-(
+
+senf::log::FileTarget::RegisterConsole senf::log::FileTarget::RegisterConsole::instance;
+senf::log::SyslogTarget::RegisterConsole senf::log::SyslogTarget::RegisterConsole::instance;
+senf::log::SyslogUDPTarget::RegisterConsole senf::log::SyslogUDPTarget::RegisterConsole::instance;
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index 09c5706..7e02f91 100644 (file)
@@ -134,6 +134,11 @@ prefix_ bool senf::log::detail::TargetRegistry::fallbackRouting()
     return fallbackRouting_;
 }
 
+prefix_ senf::console::ScopedDirectory<> & senf::log::detail::TargetRegistry::consoleDir()
+{
+    return consoleDir_();
+}
+
 ////////////////////////////////////////
 // private members
 
index bc48061..f926f87 100644 (file)
@@ -60,8 +60,13 @@ namespace detail {
         void routed();
         bool fallbackRouting();
 
+        senf::console::ScopedDirectory<> & consoleDir();
+
+        void dynamicTarget(std::auto_ptr<Target> target);
+
     private:
         TargetRegistry();
+        ~TargetRegistry();
         
         void registerTarget(Target * target, std::string const & name);
         void unregisterTarget(Target * target);
@@ -70,6 +75,7 @@ namespace detail {
         void consoleStreams(std::ostream & os);
         void consoleWrite(std::string const & stream, std::string const & area, Level level,
                           std::string const & msg);
+        void consoleRemoveTarget(Target * target);
 
         typedef std::set<Target *> Targets;
         Targets targets_;
@@ -77,6 +83,8 @@ namespace detail {
         bool fallbackRouting_;
 
         console::LazyDirectory consoleDir_;
+
+        Targets dynamicTargets_;
         
         friend class senf::log::Target;
         friend class senf::singleton<TargetRegistry>;
index f3a0c19..8f434a6 100644 (file)
@@ -433,7 +433,6 @@ prefix_ void senf::term::LineEditor::insert(std::string const & text)
 prefix_ void senf::term::LineEditor::pushHistory(std::string const & text)
 {
     if (! text.empty()
-        && (historyPoint_ == history_.size() || history_[historyPoint_] != text)
         && (history_.empty() || history_.back() != text)) {
         history_.push_back(text);
         while (history_.size() > MAX_HISTORY_SIZE)