#include "Route.hh"
#include "Module.hh"
#include "ModuleManager.hh"
+#include "../Utils/Console/Console.hh"
//#include "Connectors.mpp"
#define prefix_
prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
{
// The connector is not registered -> route() or noroute() statement missing
- SENF_ASSERT( module_ );
+ SENF_ASSERT( module_ &&
+ "senf::ppi::connector::Connector::connect(): (source) "
+ "Missing route() or noroute()" );
// The connector is already connected
- SENF_ASSERT( ! peer_ );
+ SENF_ASSERT( ! peer_ &&
+ "senf::ppi::connector::Connector::connect(): (source) "
+ "duplicate connection" );
// The target connector is not registered -> route() or noroute() statement missing
- SENF_ASSERT( target.module_ );
+ SENF_ASSERT( target.module_ &&
+ "senf::ppi::connector::Connector::connect(): (target) "
+ "Missing route() or noroute()" );
// The target connector is already connected
- SENF_ASSERT( ! target.peer_ );
+ SENF_ASSERT( ! target.peer_ &&
+ "senf::ppi::connector::Connector::connect(): (target) "
+ "duplicate connection" );
if (! (packetTypeID() == typeid(void) ||
target.packetTypeID() == typeid(void) ||
packetTypeID() == target.packetTypeID()) )
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
- SENF_ASSERT( peer_ );
+ SENF_ASSERT( peer_ &&
+ "senf::ppi::connector::Connector::disconnect(): Not connected" );
Connector & peer (*peer_);
peer_ = 0;
peer.peer_ = 0;
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");
}
///////////////////////////////////////////////////////////////////////////
prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
{
+ throttleTrace("IN ", "throttle");
if (! throttled_) {
throttled_ = true;
if (throttleCallback_)
prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle()
{
+ throttleTrace("IN ", "unthrottle");
if (throttled_) {
throttled_ = false;
if (unthrottleCallback_)
queue_.pop_back();
v_dequeueEvent();
}
+ trace(p, "IN ");
return p;
}