X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=PPI%2FConnectors.cc;h=ce44e0d23784c73237c77ee2ba399303fb61d9a6;hb=d5a72d0b3f6fee56dba6de1c54cafb448ebe3457;hp=224eab2ae8c1c0045007903f0e78ab192939cd71;hpb=f73fa16ed5abdce272ac77f8b8b9ef2b9922c266;p=senf.git diff --git a/PPI/Connectors.cc b/PPI/Connectors.cc index 224eab2..ce44e0d 100644 --- a/PPI/Connectors.cc +++ b/PPI/Connectors.cc @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institute for Open Communication Systems (FOKUS) -// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -24,36 +24,195 @@ \brief Connectors non-inline non-template implementation */ #include "Connectors.hh" -//#include "Connectors.ih" +#include "Connectors.ih" // Custom includes #include "Route.hh" +#include "Module.hh" +#include "ModuleManager.hh" +#include "../Utils/Console/Console.hh" //#include "Connectors.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// +// senf::ppi::connector::Connector + +prefix_ void senf::ppi::connector::Connector::connect(Connector & target) +{ + // The connector is not registered -> route() or noroute() statement missing + SENF_ASSERT( module_ && + "senf::ppi::connector::Connector::connect(): (source) " + "Missing route() or noroute()" ); + // The connector is already connected + 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::ppi::connector::Connector::connect(): (target) " + "Missing route() or noroute()" ); + // The target connector is already connected + SENF_ASSERT( ! target.peer_ && + "senf::ppi::connector::Connector::connect(): (target) " + "duplicate connection" ); + if (! (packetTypeID() == typeid(void) || + target.packetTypeID() == typeid(void) || + packetTypeID() == target.packetTypeID()) ) + throw IncompatibleConnectorsException() + << ": " << prettyName(packetTypeID()) + << " [in module " << prettyName(typeid(*module_)) << "] " + << ", " << prettyName(target.packetTypeID()) + << " [in module " << prettyName(typeid(*target.module_)) << "]"; + + peer_ = & target; + target.peer_ = this; + + if (! initializationScheduled()) + enqueueInitializable(); + if (! peer().initializationScheduled()) + 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: \n" + " on connector \n" + " PPI throttling trace: \n" + " on connector \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::ppi::connector::Connector::disconnect(): Not connected" ); + Connector & peer (*peer_); + peer_ = 0; + peer.peer_ = 0; + + if (! initializationScheduled()) + enqueueInitializable(); + if (! peer.initializationScheduled()) + peer.enqueueInitializable(); +} + +prefix_ std::type_info const & senf::ppi::connector::Connector::packetTypeID() +{ + return typeid(void); +} + +/////////////////////////////////////////////////////////////////////////// // senf::ppi::connector::PassiveConnector //////////////////////////////////////// // private members -prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle() +prefix_ void senf::ppi::connector::PassiveConnector::v_init() { - 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(); - } - } + 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; + if (throttled()) + emitThrottle(); else + emitUnthrottle(); +} + +prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent() +{} + +prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle() +{ + 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"); } /////////////////////////////////////////////////////////////////////////// @@ -62,24 +221,38 @@ prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle() //////////////////////////////////////// // private members +prefix_ void senf::ppi::connector::ActiveConnector::v_init() +{ + if (! connected()) + notifyThrottle(); +} + prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle() { - if (throttleCallback_) - throttleCallback_(); - NotifyRoutes::const_iterator i (notifyRoutes_.begin()); - NotifyRoutes::const_iterator const i_end (notifyRoutes_.end()); - for (; i != i_end; ++i) - (*i)->notifyThrottle(); + throttleTrace("IN ", "throttle"); + if (! throttled_) { + throttled_ = true; + if (throttleCallback_) + throttleCallback_(); + NotifyRoutes::const_iterator i (notifyRoutes_.begin()); + NotifyRoutes::const_iterator const i_end (notifyRoutes_.end()); + for (; i != i_end; ++i) + (*i)->notifyThrottle(); + } } prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle() { - if (unthrottleCallback_) - unthrottleCallback_(); - NotifyRoutes::const_iterator i (notifyRoutes_.begin()); - NotifyRoutes::const_iterator const i_end (notifyRoutes_.end()); - for (; i != i_end; ++i) - (*i)->notifyUnthrottle(); + throttleTrace("IN ", "unthrottle"); + if (throttled_) { + throttled_ = false; + if (unthrottleCallback_) + unthrottleCallback_(); + NotifyRoutes::const_iterator i (notifyRoutes_.begin()); + NotifyRoutes::const_iterator const i_end (notifyRoutes_.end()); + for (; i != i_end; ++i) + (*i)->notifyUnthrottle(); + } } prefix_ void senf::ppi::connector::ActiveConnector::registerRoute(ForwardingRoute & route) @@ -100,6 +273,7 @@ prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()() queue_.pop_back(); v_dequeueEvent(); } + trace(p, "IN "); return p; } @@ -116,34 +290,34 @@ prefix_ void senf::ppi::connector::InputConnector::v_dequeueEvent() {} /////////////////////////////////////////////////////////////////////////// -// senf::ppi::connector::ActiveInput +// senf::ppi::connector::GenericActiveInput //////////////////////////////////////// // private members -prefix_ void senf::ppi::connector::ActiveInput::v_requestEvent() +prefix_ void senf::ppi::connector::GenericActiveInput::v_requestEvent() { request(); } /////////////////////////////////////////////////////////////////////////// -// senf::ppi::connector::PassiveInput +// senf::ppi::connector::GenericPassiveInput //////////////////////////////////////// // private members -prefix_ void senf::ppi::connector::PassiveInput::v_enqueueEvent() +prefix_ void senf::ppi::connector::GenericPassiveInput::v_enqueueEvent() { emit(); qdisc_->update(*this, QueueingDiscipline::ENQUEUE); } -prefix_ void senf::ppi::connector::PassiveInput::v_dequeueEvent() +prefix_ void senf::ppi::connector::GenericPassiveInput::v_dequeueEvent() { qdisc_->update(*this, QueueingDiscipline::DEQUEUE); } -prefix_ void senf::ppi::connector::PassiveInput::v_unthrottleEvent() +prefix_ void senf::ppi::connector::GenericPassiveInput::v_unthrottleEvent() { size_type n (queueSize()); while (n) {