Socket: Fix handle.state() on invalid handles
[senf.git] / PPI / Connectors.cc
index 4c5a3ea..ce44e0d 100644 (file)
@@ -30,6 +30,7 @@
 #include "Route.hh"
 #include "Module.hh"
 #include "ModuleManager.hh"
+#include "../Utils/Console/Console.hh"
 
 //#include "Connectors.mpp"
 #define prefix_
@@ -74,6 +75,91 @@ prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
         peer().enqueueInitializable();
 }
 
+senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::traceState_ (
+    senf::ppi::connector::Connector::NO_TRACING);
+
+prefix_ void senf::ppi::connector::Connector::trace(Packet const & p, char const * label)
+{
+    if (traceState_ ==  NO_TRACING)
+        return;
+    SENF_LOG_BLOCK(({
+                std::string type (prettyName(p.typeId().id()));
+                log << "PPI packet trace: " << label << " 0x" << std::hex << p.id() << " " 
+                    << type.substr(21, type.size()-22) << " on " << & module() << " " 
+                    << prettyName(typeid(module())) << " connector 0x" << this << "\n";
+                if (traceState_ == TRACE_CONTENTS)
+                    p.dump(log);
+            }));
+}
+
+prefix_ void senf::ppi::connector::Connector::throttleTrace(char const * label,
+                                                            char const * type)
+{
+    if (traceState_ == NO_TRACING)
+        return;
+    SENF_LOG_BLOCK(({
+                log << "PPI throttling trace: " << label << " " << type << " on " << & module() 
+                    << " " << prettyName(typeid(module())) << " connector 0x" << this << "\n";
+            }));
+}
+
+namespace senf { namespace ppi { namespace connector {
+
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER( 
+        Connector, TraceState, (NO_TRACING)(TRACE_IDS)(TRACE_CONTENTS) );
+
+}}}
+
+namespace {
+
+    struct ConsoleRegister
+    {
+        ConsoleRegister();
+    };
+
+    ConsoleRegister::ConsoleRegister()
+    {
+        senf::ppi::ModuleManager::instance().consoleDir()
+            .add("tracing", SENF_FNP(senf::ppi::connector::Connector::TraceState,
+                                     senf::ppi::connector::Connector::tracing, ()))
+            .doc("Log every packet sent or received by any module.\n"
+                 "There are three different tracing levels:\n"
+                 "\n"
+                 "    NO_TRACING      don't output any tracing information\n"
+                 "    TRACE_IDS       trace packet id's but do not show packet contents\n"
+                 "    TRACE_CONTENTS  trace complete packet contents\n"
+                 "\n"
+                 "A log message is generated whenever the packet traverses a connector. The\n"
+                 "TRACE_IDS log message has the following format:\n"
+                 "\n"
+                 "    PPI packet trace: <direction> <packet-id> <packet-type>\n"
+                 "                      on <module-id> <module-type> connector <connector-id>\n"
+                 "    PPI throttling trace: <direction> <throttle-msg>\n"
+                 "                      on <module-id> <module-type> connector <connector-id>\n"
+                 "\n"
+                 "The fields are:\n"
+                 "\n"
+                 "    direction       'IN' for packets/throttle notifications entering the module,\n"
+                 "                    'OUT' for packets/throttle notifications leaving it\n"
+                 "    packet-id       Numeric unique packet id. This value is unique for packets\n"
+                 "                    alive at the same time, packets at different times may (and\n"
+                 "                    will) share id's\n"
+                 "    packet-type     The type of the packet header\n"
+                 "    module-id       Unique module id\n"
+                 "    module-type     Type of the module the packet is sent to/from\n"
+                 "    connector-id    Unique connector id\n"
+                 "    throttle-msg    Type of throttling event\n");
+
+        senf::ppi::ModuleManager::instance().consoleDir()
+            .add("tracing", SENF_FNP(void, senf::ppi::connector::Connector::tracing,
+                                     (senf::ppi::connector::Connector::TraceState)))
+            .arg("state", "new tracing state");
+    }
+
+    ConsoleRegister consoleRegister;
+
+}
+
 prefix_ void senf::ppi::connector::Connector::disconnect()
 {
     // Cannot disconnected a non-connected connector
@@ -120,19 +206,13 @@ prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent()
 
 prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
 {
-    if (throttled() && !nativeThrottled_) {
-        Routes::const_iterator i (routes_.begin());
-        Routes::const_iterator const i_end (routes_.end());
-        for (; i != i_end; ++i)
-            if ((*i)->throttled())
-                break;
-        if (i == i_end) {
-            remoteThrottled_ = false;
-            emitUnthrottle();
-        }
-    } 
-    else
+    if (std::find_if(routes_.begin(), routes_.end(), 
+                     boost::bind(&ForwardingRoute::throttled, _1)) == routes_.end()) {
         remoteThrottled_ = false;
+        if (!nativeThrottled_)
+            emitUnthrottle();
+    } else
+        throttleTrace("OUT", "not forwarding unthrottle event");
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -149,6 +229,7 @@ prefix_ void senf::ppi::connector::ActiveConnector::v_init()
 
 prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
 {
+    throttleTrace("IN ", "throttle");
     if (! throttled_) {
         throttled_ = true;
         if (throttleCallback_)
@@ -162,6 +243,7 @@ prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
 
 prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle()
 {
+    throttleTrace("IN ", "unthrottle");
     if (throttled_) {
         throttled_ = false;
         if (unthrottleCallback_)
@@ -191,6 +273,7 @@ prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()()
         queue_.pop_back();
         v_dequeueEvent();
     }
+    trace(p, "IN ");
     return p;
 }