4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Connectors non-inline non-template implementation */
26 #include "Connectors.hh"
27 #include "Connectors.ih"
30 #include "ModuleManager.hh"
31 #include <senf/Utils/Console/ParsedCommand.hh>
33 //#include "Connectors.mpp"
35 //-/////////////////////////////////////////////////////////////////////////////////////////////////
37 //-/////////////////////////////////////////////////////////////////////////////////////////////////
38 // senf::ppi::connector::Connector
40 prefix_ senf::ppi::connector::Connector::~Connector()
43 Connector & peer (*peer_);
45 if (! peer.initializationScheduled())
46 peer.enqueueInitializable();
47 peer.v_disconnected();
51 prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
53 // The connector is not registered -> route() or noroute() statement missing
55 "senf::ppi::connector::Connector::connect(): (source) "
56 "Missing route() or noroute()" );
57 // The connector is already connected
59 "senf::ppi::connector::Connector::connect(): (source) "
60 "duplicate connection" );
61 // The target connector is not registered -> route() or noroute() statement missing
62 SENF_ASSERT( target.module_,
63 "senf::ppi::connector::Connector::connect(): (target) "
64 "Missing route() or noroute()" );
65 // The target connector is already connected
66 SENF_ASSERT( ! target.peer_,
67 "senf::ppi::connector::Connector::connect(): (target) "
68 "duplicate connection" );
70 if (! (packetTypeID() == typeid(void) ||
71 target.packetTypeID() == typeid(void) ||
72 packetTypeID() == target.packetTypeID()) )
73 throw IncompatibleConnectorsException()
74 << ": " << prettyName(packetTypeID())
75 << " [in module " << prettyName(typeid(*module_)) << "] "
76 << ", " << prettyName(target.packetTypeID())
77 << " [in module " << prettyName(typeid(*target.module_)) << "]";
82 if (! initializationScheduled())
83 enqueueInitializable();
84 if (! peer().initializationScheduled())
85 peer().enqueueInitializable();
92 senf::ppi::connector::Connector::TraceState senf::ppi::connector::Connector::traceState_ (
93 senf::ppi::connector::Connector::NO_TRACING);
95 prefix_ void senf::ppi::connector::Connector::trace(Packet const & p, char const * label)
97 if (traceState_ == NO_TRACING)
100 std::string type (prettyName(p.typeId().id()));
101 log << "PPI packet trace: " << label << " 0x" << std::hex << p.id() << " "
102 << type.substr(21, type.size()-22) << " on " << & module() << " "
103 << prettyName(typeid(module())) << " connector 0x" << this << "\n";
104 if (traceState_ == TRACE_CONTENTS)
109 prefix_ void senf::ppi::connector::Connector::throttleTrace(char const * label,
112 if (traceState_ == NO_TRACING)
115 log << "PPI throttling trace: " << label << " " << type << " on " << & module()
116 << " " << prettyName(typeid(module())) << " connector 0x" << this << "\n";
120 namespace senf { namespace ppi { namespace connector {
122 SENF_CONSOLE_REGISTER_ENUM_MEMBER(
123 Connector, TraceState, (NO_TRACING)(TRACE_IDS)(TRACE_CONTENTS) );
129 struct ConsoleRegister
134 ConsoleRegister::ConsoleRegister()
136 #ifndef SENF_PPI_NOTRACE
137 senf::ppi::ModuleManager::instance().consoleDir()
138 .add("tracing", senf::console::factory::Command(
139 SENF_FNP(senf::ppi::connector::Connector::TraceState,
140 senf::ppi::connector::Connector::tracing, ()))
141 .doc("Log every packet sent or received by any module.\n"
142 "There are three different tracing levels:\n"
144 " NO_TRACING don't output any tracing information\n"
145 " TRACE_IDS trace packet id's but do not show packet contents\n"
146 " TRACE_CONTENTS trace complete packet contents\n"
148 "A log message is generated whenever the packet traverses a connector. The\n"
149 "TRACE_IDS log message has the following format:\n"
151 " PPI packet trace: <direction> <packet-id> <packet-type>\n"
152 " on <module-id> <module-type> connector <connector-id>\n"
153 " PPI throttling trace: <direction> <throttle-msg>\n"
154 " on <module-id> <module-type> connector <connector-id>\n"
158 " direction 'IN' for packets/throttle notifications entering the module,\n"
159 " 'OUT' for packets/throttle notifications leaving it\n"
160 " packet-id Numeric unique packet id. This value is unique for packets\n"
161 " alive at the same time, packets at different times may (and\n"
162 " will) share id's\n"
163 " packet-type The type of the packet header\n"
164 " module-id Unique module id\n"
165 " module-type Type of the module the packet is sent to/from\n"
166 " connector-id Unique connector id\n"
167 " throttle-msg Type of throttling event\n")
170 senf::ppi::ModuleManager::instance().consoleDir()
171 .add("tracing", senf::console::factory::Command(
172 SENF_FNP(void, senf::ppi::connector::Connector::tracing,
173 (senf::ppi::connector::Connector::TraceState)))
174 .arg("state", "new tracing state")
179 ConsoleRegister consoleRegister;
183 prefix_ void senf::ppi::connector::Connector::disconnect()
185 // Cannot disconnected a non-connected connector
187 "senf::ppi::connector::Connector::disconnect(): Not connected" );
189 Connector & peer (*peer_);
193 if (! initializationScheduled())
194 enqueueInitializable();
195 if (! peer.initializationScheduled())
196 peer.enqueueInitializable();
199 peer.v_disconnected();
202 prefix_ std::type_info const & senf::ppi::connector::Connector::packetTypeID()
207 prefix_ void senf::ppi::connector::Connector::unregisterConnector()
210 module_->unregisterConnector(*this);
213 prefix_ void senf::ppi::connector::Connector::setModule(module::Module & module)
218 prefix_ void senf::ppi::connector::Connector::v_disconnected()
221 prefix_ void senf::ppi::connector::Connector::v_connected()
224 //-/////////////////////////////////////////////////////////////////////////////////////////////////
225 // senf::ppi::connector::PassiveConnector
227 prefix_ senf::ppi::connector::PassiveConnector::~PassiveConnector()
229 // Must be here and NOT in base so it is called before destructing the routes_ member
230 unregisterConnector();
233 prefix_ void senf::ppi::connector::PassiveConnector::v_disconnected()
235 Connector::v_disconnected();
239 prefix_ void senf::ppi::connector::PassiveConnector::v_connected()
241 Connector::v_connected();
242 peer_ = & dynamic_cast<ActiveConnector&>(Connector::peer());
245 //-/////////////////////////////////////////////////////////////////////////////////////////////////
248 prefix_ void senf::ppi::connector::PassiveConnector::v_init()
250 Routes::const_iterator i (routes_.begin());
251 Routes::const_iterator const i_end (routes_.end());
252 for (; i != i_end; ++i)
253 if ((*i)->throttled())
256 remoteThrottled_ = false;
263 prefix_ void senf::ppi::connector::PassiveConnector::registerRoute(ForwardingRoute & route)
265 routes_.push_back(&route);
268 prefix_ void senf::ppi::connector::PassiveConnector::unregisterRoute(ForwardingRoute & route)
270 Routes::iterator i (std::find(routes_.begin(), routes_.end(), &route));
271 if (i != routes_.end())
275 prefix_ void senf::ppi::connector::PassiveConnector::v_unthrottleEvent()
278 prefix_ void senf::ppi::connector::PassiveConnector::notifyUnthrottle()
280 if (std::find_if(routes_.begin(), routes_.end(),
281 boost::bind(&ForwardingRoute::throttled, _1)) == routes_.end()) {
282 remoteThrottled_ = false;
283 if (!nativeThrottled_)
286 SENF_PPI_THROTTLE_TRACE("OUT", "not forwarding unthrottle event");
289 //-/////////////////////////////////////////////////////////////////////////////////////////////////
290 // senf::ppi::connector::ActiveConnector
292 prefix_ senf::ppi::connector::ActiveConnector::~ActiveConnector()
294 // Must be here and NOT in base so it is called before destructing the routes_ member
295 unregisterConnector();
298 prefix_ void senf::ppi::connector::ActiveConnector::v_disconnected()
300 Connector::v_disconnected();
304 prefix_ void senf::ppi::connector::ActiveConnector::v_connected()
306 Connector::v_connected();
307 peer_ = & dynamic_cast<PassiveConnector&>(Connector::peer());
310 //-/////////////////////////////////////////////////////////////////////////////////////////////////
313 prefix_ void senf::ppi::connector::ActiveConnector::v_init()
319 prefix_ void senf::ppi::connector::ActiveConnector::notifyThrottle()
321 SENF_PPI_THROTTLE_TRACE("IN ", "throttle");
324 if (throttleCallback_)
326 NotifyRoutes::const_iterator i (notifyRoutes_.begin());
327 NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
328 for (; i != i_end; ++i)
329 (*i)->notifyThrottle();
333 prefix_ void senf::ppi::connector::ActiveConnector::notifyUnthrottle()
335 SENF_PPI_THROTTLE_TRACE("IN ", "unthrottle");
338 if (unthrottleCallback_)
339 unthrottleCallback_();
340 NotifyRoutes::const_iterator i (notifyRoutes_.begin());
341 NotifyRoutes::const_iterator const i_end (notifyRoutes_.end());
342 for (; i != i_end; ++i)
343 (*i)->notifyUnthrottle();
347 prefix_ void senf::ppi::connector::ActiveConnector::registerRoute(ForwardingRoute & route)
349 notifyRoutes_.push_back(&route);
352 prefix_ void senf::ppi::connector::ActiveConnector::unregisterRoute(ForwardingRoute & route)
354 NotifyRoutes::iterator i (std::find(notifyRoutes_.begin(), notifyRoutes_.end(), &route));
355 if (i != notifyRoutes_.end())
356 notifyRoutes_.erase(i);
359 //-/////////////////////////////////////////////////////////////////////////////////////////////////
360 // senf::ppi::connector::InputConnector
362 prefix_ senf::Packet senf::ppi::connector::InputConnector::operator()()
367 Packet p ( queue_.back());
370 SENF_PPI_TRACE(p, "IN ");
373 SENF_PPI_TRACE(Packet(), "IN ");
378 prefix_ void senf::ppi::connector::InputConnector::v_disconnected()
380 Connector::v_disconnected();
384 prefix_ void senf::ppi::connector::InputConnector::v_connected()
386 Connector::v_connected();
387 peer_ = & dynamic_cast<OutputConnector&>(Connector::peer());
390 //-/////////////////////////////////////////////////////////////////////////////////////////////////
393 prefix_ void senf::ppi::connector::InputConnector::v_requestEvent()
396 prefix_ void senf::ppi::connector::InputConnector::v_enqueueEvent()
399 prefix_ void senf::ppi::connector::InputConnector::v_dequeueEvent()
402 //-/////////////////////////////////////////////////////////////////////////////////////////////////
403 // senf::ppi::connector::OutputConnector
405 prefix_ void senf::ppi::connector::OutputConnector::v_disconnected()
407 Connector::v_disconnected();
411 prefix_ void senf::ppi::connector::OutputConnector::v_connected()
413 Connector::v_connected();
414 peer_ = & dynamic_cast<InputConnector&>(Connector::peer());
417 //-/////////////////////////////////////////////////////////////////////////////////////////////////
418 // senf::ppi::connector::GenericActiveInput
420 //-/////////////////////////////////////////////////////////////////////////////////////////////////
423 prefix_ void senf::ppi::connector::GenericActiveInput::v_requestEvent()
428 //-/////////////////////////////////////////////////////////////////////////////////////////////////
429 // senf::ppi::connector::GenericPassiveInput
431 prefix_ void senf::ppi::connector::GenericPassiveInput::v_disconnected()
433 PassiveConnector::v_disconnected();
434 InputConnector::v_disconnected();
438 prefix_ void senf::ppi::connector::GenericPassiveInput::v_connected()
440 PassiveConnector::v_connected();
441 InputConnector::v_connected();
442 peer_ = & dynamic_cast<GenericActiveOutput&>(Connector::peer());
445 //-/////////////////////////////////////////////////////////////////////////////////////////////////
448 prefix_ void senf::ppi::connector::GenericPassiveInput::v_enqueueEvent()
452 qdisc_->update(*this, QueueingDiscipline::ENQUEUE);
455 prefix_ void senf::ppi::connector::GenericPassiveInput::v_dequeueEvent()
458 qdisc_->update(*this, QueueingDiscipline::DEQUEUE);
461 prefix_ void senf::ppi::connector::GenericPassiveInput::qdisc(QueueingDiscipline::None_t)
466 prefix_ void senf::ppi::connector::GenericPassiveInput::v_unthrottleEvent()
468 size_type n (queueSize());
471 size_type nn (queueSize());
478 //-/////////////////////////////////////////////////////////////////////////////////////////////////
479 // senf::ppi::connector::GenericPassiveOutput
481 prefix_ void senf::ppi::connector::GenericPassiveOutput::v_disconnected()
483 PassiveConnector::v_disconnected();
484 OutputConnector::v_disconnected();
488 prefix_ void senf::ppi::connector::GenericPassiveOutput::v_connected()
490 PassiveConnector::v_connected();
491 OutputConnector::v_connected();
492 peer_ = & dynamic_cast<GenericActiveInput&>(Connector::peer());
495 //-/////////////////////////////////////////////////////////////////////////////////////////////////
496 // senf::ppi::connector::GenericActiveInput
498 prefix_ void senf::ppi::connector::GenericActiveInput::v_disconnected()
500 ActiveConnector::v_disconnected();
501 InputConnector::v_disconnected();
505 prefix_ void senf::ppi::connector::GenericActiveInput::v_connected()
507 ActiveConnector::v_connected();
508 InputConnector::v_connected();
509 peer_ = & dynamic_cast<GenericPassiveOutput&>(Connector::peer());
512 //-/////////////////////////////////////////////////////////////////////////////////////////////////
513 // senf::ppi::connector::GenericActiveOutput
515 prefix_ void senf::ppi::connector::GenericActiveOutput::v_disconnected()
517 ActiveConnector::v_disconnected();
518 OutputConnector::v_disconnected();
522 prefix_ void senf::ppi::connector::GenericActiveOutput::v_connected()
524 ActiveConnector::v_connected();
525 OutputConnector::v_connected();
526 peer_ = & dynamic_cast<GenericPassiveInput&>(Connector::peer());
530 //-/////////////////////////////////////////////////////////////////////////////////////////////////
532 //#include "Connectors.mpp"
538 // comment-column: 40
539 // c-file-style: "senf"
540 // indent-tabs-mode: nil
541 // ispell-local-dictionary: "american"
542 // compile-command: "scons -u test"