From: g0dil Date: Mon, 10 Nov 2008 17:12:40 +0000 (+0000) Subject: PPI: Annotation router X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=2a7f04c6e922deb5beedc587133af5d836d5a8a9;p=senf.git PPI: Annotation router git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@954 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/PPI/AnnotationRouter.ct b/PPI/AnnotationRouter.ct new file mode 100644 index 0000000..e334214 --- /dev/null +++ b/PPI/AnnotationRouter.ct @@ -0,0 +1,75 @@ +// $Id$ +// +// Copyright (C) 2008 +// 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 +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AnnotationRouter non-inline template implementation */ + +//#include "AnnotationRouter.ih" + +// Custom includes + +#define prefix_ +///////////////////////////////ct.p//////////////////////////////////////// + +template +prefix_ senf::ppi::module::AnnotationRouter::AnnotationRouter() +{ + noroute(input); + noroute(defaultOutput); + input.onRequest(&AnnotationRouter::request); +} + +template +prefix_ senf::ppi::connector::ActiveOutput<> & +senf::ppi::module::AnnotationRouter::newOutput(AnnotationType const & key) +{ + if (outputs_.find(key) != outputs_.end()) + throw DuplicateKeyException(key); + // key must not be const ... has something to do with exception guarantees ?? + AnnotationType k (key); + return *outputs_.insert(k, new connector::ActiveOutput<>()).first; +} + +template +prefix_ void senf::ppi::module::AnnotationRouter::request() +{ + Packet p (input()); + typename Outputs::iterator i (outputs_.find(p.annotation())); + if (i == outputs_.end()) + defaultOutput(p); + else + (*i)(p); +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/AnnotationRouter.cti b/PPI/AnnotationRouter.cti new file mode 100644 index 0000000..d61468c --- /dev/null +++ b/PPI/AnnotationRouter.cti @@ -0,0 +1,70 @@ +// $Id$ +// +// Copyright (C) 2008 +// 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 +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AnnotationRouter inline template implementation */ + +//#include "AnnotationRouter.ih" + +// Custom includes +#include "Setup.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +template +template +prefix_ senf::ppi::connector::GenericActiveOutput & +senf::ppi::module::AnnotationRouter::connect(Target & target, + AnnotationType const & key) +{ + connector::GenericActiveOutput & output (newOutput(key)); + route(input, output); + ppi::connect(output, target); + return output; +} + +#ifndef DOXYGEN + +template +prefix_ senf::ppi::connector::GenericActiveOutput & +senf::ppi::connect(module::AnnotationRouter & source, Target & target, + ArgType const & key) +{ + return source.connect(target, AnnotationType(key)); +} + +#endif + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/AnnotationRouter.hh b/PPI/AnnotationRouter.hh new file mode 100644 index 0000000..6b98b15 --- /dev/null +++ b/PPI/AnnotationRouter.hh @@ -0,0 +1,151 @@ +// $Id$ +// +// Copyright (C) 2008 +// 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 +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AnnotationRouter public header */ + +#ifndef HH_AnnotationRouter_ +#define HH_AnnotationRouter_ 1 + +// Custom includes +#include +#include "Module.hh" +#include "Connectors.hh" + +//#include "AnnotationRouter.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace ppi { +namespace module { + + /** \brief Route packets to destination according to some annotation value + + This router takes packet on a single input and directs them to one of it outputs depending + on a packet annotation. Each output connected will be associated with a single annotation + value. Incoming packets for which no matching output is found are directed to a default + output. If this output is left unconnected, those packets will be dropped. + + The \a AnnotationType template parameter defines the routing key. This annotation must + support the following operations: + \li Comparison with '<' + \li Copy-construction + \li Output streaming to an ostream via '<<' + + The following annotation can be used to route the packets according to a mac address. + \code + struct TargetInterface + { + senf::MACAddress mac; + + bool operator< (TargetInterface const & other) + { return mac < other.mac; } + + TargetInterface(senf::MACAddress const & m) + : mac (m) {} + }; + + std::ostream & operator<<(std::ostream & os, TargetInterface const & v) + { os << v.mac; return os; } + \endcode + + The additional senf::MACAddress constructor allows to construct an instance directly from a + mac address and allows to pass a senf::MACAddress value as routing key directly: + + \code + senf::ppi::module::AnnotationRouter router; + + senf::ppi::connect(router, target1, senf::MACAddress::from_string("00:1a:2b:04:06:08")); + \endcode + + The special senf::ppi::connect() overload takes a third argument, the routing key. This must + be an AnnotationType value or must be (explicitly) convertible to AnnotationType. + + The input will be throttled whenever any of the outputs except \a defaultOutput are + throttled. + + \ingroup routing_modules + + \todo Call Module::v_init() on every connection change and remove disconnected connections + from the container + */ + template + class AnnotationRouter : public Module + { + SENF_PPI_MODULE(AnnotationRouter); + public: + connector::PassiveInput<> input; + connector::ActiveOutput<> defaultOutput; + + AnnotationRouter(); + + struct DuplicateKeyException : public senf::Exception + { DuplicateKeyException(AnnotationType const & key) + : senf::Exception("Duplicate senf::ppi::module::AnnotationRouter routing key") + { append(boost::lexical_cast(key)); } }; + + private: + connector::ActiveOutput<> & newOutput(AnnotationType const & key); + +#ifndef DOXYGEN + // I didn't get template friend functions to work ... + public: +#endif + template + connector::GenericActiveOutput & connect(Target & target, AnnotationType const & key); + + private: + void request(); + + typedef boost::ptr_map > Outputs; + Outputs outputs_; + }; + +} + +#ifndef DOXYGEN + + template + connector::GenericActiveOutput & connect( + module::AnnotationRouter & source, Target & target, + ArgType const & key); + +#endif + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "AnnotationRouter.cci" +#include "AnnotationRouter.ct" +#include "AnnotationRouter.cti" +#endif + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/AnnotationRouter.test.cc b/PPI/AnnotationRouter.test.cc new file mode 100644 index 0000000..8084a7a --- /dev/null +++ b/PPI/AnnotationRouter.test.cc @@ -0,0 +1,94 @@ +// $Id$ +// +// Copyright (C) 2008 +// 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 +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief AnnotationRouter.test unit tests */ + +//#include "AnnotationRouter.test.hh" +//#include "AnnotationRouter.test.ih" + +// Custom includes +#include "AnnotationRouter.hh" +#include "DebugModules.hh" + +#include "../Utils//auto_unit_test.hh" +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +namespace { + struct IntAnnotation { + int value; + bool operator<(IntAnnotation const & other) const { return value < other.value; } + bool operator==(IntAnnotation const & other) const { return value == other.value; } + IntAnnotation(int v) : value(v) {} + IntAnnotation & operator=(int v) { value=v; return *this; } + operator int () const { return value; } + }; + + std::ostream & operator<<(std::ostream & os, IntAnnotation const & value) + { os << value.value; return os; } +} + +BOOST_AUTO_UNIT_TEST(annotationRouter) +{ + senf::ppi::module::debug::ActiveSource source; + senf::ppi::module::debug::PassiveSink sink1; + senf::ppi::module::debug::PassiveSink sink2; + + senf::ppi::module::AnnotationRouter router; + + senf::ppi::connect(source, router); + senf::ppi::connect(router, sink1, 1); + senf::ppi::connect(router, sink2, 2); + + senf::ppi::init(); + + senf::Packet p1 (senf::DataPacket::create()); + p1.annotation() = 1; + senf::Packet p2 (senf::DataPacket::create()); + p2.annotation() = 2; + + source.submit(p1); + source.submit(p2); + source.submit(senf::DataPacket::create()); + + BOOST_CHECK_EQUAL( sink1.size(), 1u ); + BOOST_CHECK_EQUAL( sink2.size(), 1u ); + BOOST_CHECK( sink1.front() == p1 ); + BOOST_CHECK( sink2.front() == p2 ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/senf.dict b/senf.dict index 807bc7f..1851f05 100644 --- a/senf.dict +++ b/senf.dict @@ -17,6 +17,8 @@ addrs addtogroup aListCollection alloc +AnnotationRouter +AnnotationType anotherCallback api arg @@ -558,6 +560,7 @@ syslog SyslogTarget SystemException TapSocketHandle +TargetInterface td templated ThresholdQueueing