MIRA
FrameworkGraph.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_FRAMEWORKGRAPH_H_
48 #define _MIRA_FRAMEWORKGRAPH_H_
49 
50 #include <string>
51 
52 #include <serialization/adapters/std/list>
53 #include <serialization/adapters/boost/shared_ptr.hpp>
54 #include <geometry/Point.h>
55 
57 
58 #include <fw/Framework.h>
59 #include <fw/RemoteModule.h>
60 
61 namespace mira {
62 
64 
65 template <int C, typename T>
66 class FrameworkGraphMixin : public T {};
67 
68 template <int C> // note, the C helps us to generate different classes to avoid compiler warning concerning inaccessible base classes
69 class FrameworkGraphMixin<C,void> {};
70 
96 template <typename NodeMixin = void,
97  typename AuthorityNodeMixin=void,
98  typename ChannelNodeMixin=void,
99  typename NamespaceNodeMixin=void,
100  typename FrameworkNodeMixin=void>
101 class FrameworkGraph : boost::noncopyable
102 {
103  class EmptyMixin {};
104 
105 public:
106 
107  class Node;
108  typedef boost::shared_ptr<Node> NodePtr;
109 
110  class ChannelNode;
111  typedef boost::shared_ptr<ChannelNode> ChannelNodePtr;
112 
114  typedef boost::shared_ptr<AuthorityNode> AuthorityNodePtr;
115 
117  typedef boost::shared_ptr<NamespaceNode> NamespaceNodePtr;
118 
120  typedef boost::shared_ptr<FrameworkNode> FrameworkNodePtr;
121 
125  class Node : public FrameworkGraphMixin<0,NodeMixin>
126  {
127  public:
128  virtual ~Node() {}
129 
131  virtual std::set<NodePtr> getAdjacentNodes() = 0;
132  };
133 
137  class ChannelNode : public Node, public FrameworkGraphMixin<1,ChannelNodeMixin>
138  {
139  public:
140  ChannelNode(const std::string& iID) : id(iID) {}
141  bool operator==(const std::string& id) {
142  return id==this->id;
143  }
144 
145  virtual std::set<NodePtr> getAdjacentNodes()
146  {
147  std::set<NodePtr> nodes;
148  foreach(auto p, mSubscribedAuthorities)
149  nodes.insert(p);
150  foreach(auto p, mPublishingAuthorities)
151  nodes.insert(p);
152  return nodes;
153  }
154 
155  std::set<AuthorityNodePtr> getSubscribedAuthorities() {
156  return mSubscribedAuthorities;
157  }
158 
159  std::set<AuthorityNodePtr> getPublishingAuthorities() {
160  return mPublishingAuthorities;
161  }
162 
165  return mNamespace;
166  }
167 
168  public:
169 
171  std::string id;
172 
173  protected:
174  friend class FrameworkGraph;
175  std::set<AuthorityNodePtr> mSubscribedAuthorities;
176  std::set<AuthorityNodePtr> mPublishingAuthorities;
178  };
179 
183  class AuthorityNode : public Node, public FrameworkGraphMixin<2,AuthorityNodeMixin> {
184  public:
185  AuthorityNode(const AuthorityDescription& iDesc) : desc(iDesc) {}
186  bool operator==(const std::string& id) {
187  return id == (desc.ns / desc.id);
188  }
189 
190  public:
191 
192  virtual std::set<NodePtr> getAdjacentNodes()
193  {
194  std::set<NodePtr> nodes;
195  foreach(auto p, mSubscribedChannels)
196  nodes.insert(p);
197  foreach(auto p, mPublishedChannels)
198  nodes.insert(p);
199  return nodes;
200  }
201 
203  std::set<ChannelNodePtr> getPublishedChannels() {
204  return mPublishedChannels;
205  }
206 
208  std::set<ChannelNodePtr> getSubscribedChannels() {
209  return mSubscribedChannels;
210  }
211 
214  return mNamespace;
215  }
216 
219  return mFramework;
220  }
221 
227  std::map<AuthorityNodePtr, std::set<ChannelNodePtr>> getDependees() {
228  std::map<AuthorityNodePtr, std::set<ChannelNodePtr>> nodes;
229  foreach(auto c, mSubscribedChannels)
230  foreach(auto a, c->getPublishingAuthorities())
231  nodes[a].insert(c);
232  return nodes;
233  }
234 
240  std::map<AuthorityNodePtr, std::set<ChannelNodePtr>> getDependers() {
241  std::map<AuthorityNodePtr, std::set<ChannelNodePtr>> nodes;
242  foreach(auto c, mPublishedChannels)
243  foreach(auto a, c->getSubscribedAuthorities())
244  nodes[a].insert(c);
245  return nodes;
246  }
247 
248 
249  public:
250 
253 
254  protected:
255  friend class FrameworkGraph;
256  std::set<ChannelNodePtr> mSubscribedChannels;
257  std::set<ChannelNodePtr> mPublishedChannels;
260  };
261 
266  class NamespaceNode : public Node, public FrameworkGraphMixin<3,NamespaceNodeMixin> {
267  public:
268  NamespaceNode(const ResourceName& iNs) : ns(iNs) {}
269  bool operator==(const ResourceName& iNs) {
270  return iNs==ns;
271  }
272 
275  assert(parent && child);
276  parent->children.insert(child);
277  child->parent = parent;
278  }
279 
280  public:
281 
282  virtual std::set<NodePtr> getAdjacentNodes()
283  {
284  static std::set<NodePtr> empty;
285  return empty;
286  }
287 
288  public:
289 
292 
295 
297  std::set<NamespaceNodePtr> children;
298 
300  std::set<NodePtr> nodes;
301  };
302 
306  class FrameworkNode : public Node, public FrameworkGraphMixin<4,FrameworkNodeMixin> {
307  public:
308  FrameworkNode(const std::string& iName) : name(iName) {}
309  bool operator==(const std::string& iName) {
310  return iName==name;
311  }
312 
313  public:
314 
315  virtual std::set<NodePtr> getAdjacentNodes()
316  {
317  static std::set<NodePtr> empty;
318  return empty;
319  }
320 
321  public:
322 
324  std::string name;
325 
327  std::set<NodePtr> nodes;
328  };
329 
330 public:
331 
334  // create a root namespace node
335  mRootNamespace = getNamespaceNode(ResourceName("/"));
336  }
337 
338 
339  FrameworkGraph(FrameworkGraph&& other) noexcept {
340  swap(other);
341  }
342 
344  swap(other);
345  return *this;
346  }
347 
348  void swap(FrameworkGraph& other)
349  {
350  boost::swap(mMutex, other.mMutex);
351  std::swap(mAuthorities, other.mAuthorities);
352  std::swap(mChannels, other.mChannels);
353  std::swap(mNamespaces, other.mNamespaces);
354  std::swap(mFrameworks, other.mFrameworks);
355  std::swap(mRootNamespace, other.mRootNamespace);
356  std::swap(mGraphHasChanged, other.mGraphHasChanged);
357  }
358 
359  boost::mutex& mutex() { return mMutex; }
360 
369  bool discover(boost::function<void()> changeCb = boost::function<void()>())
370  {
371  mGraphHasChanged = false; // <this variable is reseted several times
372  bool graphHasChanged = false; // <this one holds whether the graph has any changes
373 
374  // Channels
375  foreach(const std::string& id, MIRA_FW.getChannelManager().getChannels())
376  {
377  ChannelNodePtr node = getChannelNode(id);
378  }
379 
380  graphHasChanged |= mGraphHasChanged;
381  if(mGraphHasChanged && changeCb)
382  changeCb();
383 
384  // Authorities
385  // discovery of authorities may be a little time consuming, if
386  // a lot of remote authorities and hence RPC calls are involved
387  auto authorities = MIRA_FW.getAuthorityManager().getAuthorities();
388  foreach(auto id, authorities)
389  {
390  mGraphHasChanged = false; // reset marker
391 
393  if(!node) {
394  AuthorityDescription d = MIRA_FW.getAuthorityManager().getDescription(id);
395 
396  boost::mutex::scoped_lock lock(mutex());
397  node.reset(new AuthorityNode(d));
398  mAuthorities.push_back(node);
399 
400  // Namespace
401  NamespaceNodePtr ns = getNamespaceNode(d.ns);
402  node->mNamespace = ns;
403  ns->nodes.insert(node);
404 
405  // Framework
406  std::string fwid = "local";
407  foreach(const auto& connection, *(MIRA_FW.getRemoteModule()->getConnections()))
408  {
409  if (connection.second->hasAuthority(id)) {
410  fwid = connection.second->getAddress().address;
411  break;
412  }
413  }
414  FrameworkNodePtr fw = getFrameworkNode(fwid);
415  node->mFramework = fw;
416  fw->nodes.insert(node);
417 
418  mGraphHasChanged = true;
419  }
420 
421  // connections: Authorities -> Channels:
422  auto publishedChannels = MIRA_FW.getAuthorityManager().getPublishedChannels(id);
423  foreach(const std::string& channel, publishedChannels)
424  {
425  boost::mutex::scoped_lock lock(mutex());
426  ChannelNodePtr channelNode = getChannelNode(channel);
427  mGraphHasChanged |= node->mPublishedChannels.insert(channelNode).second;
428  mGraphHasChanged |= channelNode->mPublishingAuthorities.insert(node).second;
429  }
430 
431  auto subscribedChannels = MIRA_FW.getAuthorityManager().getSubscribedChannels(id);
432  foreach(const std::string& channel, subscribedChannels)
433  {
434  boost::mutex::scoped_lock lock(mutex());
435  ChannelNodePtr channelNode = getChannelNode(channel);
436  mGraphHasChanged |= node->mSubscribedChannels.insert(channelNode).second;
437  mGraphHasChanged |= channelNode->mSubscribedAuthorities.insert(node).second;
438  }
439 
440  graphHasChanged |= mGraphHasChanged;
441  if(mGraphHasChanged && changeCb)
442  changeCb();
443  }
444  return graphHasChanged;
445  }
446 
447 private:
448 
449  ChannelNodePtr getChannelNode(const std::string& id)
450  {
451  ChannelNodePtr node = findPtr(mChannels, id);
452  if(!node) {
453  node.reset(new ChannelNode(id));
454  mChannels.push_back(node);
455  NamespaceNodePtr ns = getNamespaceNode(ResourceName(id).parent());
456  node->mNamespace = ns;
457  ns->nodes.insert(node);
458  mGraphHasChanged = true;
459  }
460  return node;
461  }
462 
463  NamespaceNodePtr getNamespaceNode(const ResourceName& ns)
464  {
466  if(!node) {
467  node.reset(new NamespaceNode(ns));
468  mNamespaces.push_back(node);
469  if(!node->ns.isRoot())
471  mGraphHasChanged = true;
472  }
473  return node;
474  }
475 
476  FrameworkNodePtr getFrameworkNode(const std::string& name)
477  {
478  FrameworkNodePtr node = findPtr(mFrameworks, name);
479  if(!node) {
480  node.reset(new FrameworkNode(name));
481  mFrameworks.push_back(node);
482  mGraphHasChanged = true;
483  }
484  return node;
485  }
486 
487 public:
488 
490  std::list<NodePtr> getNodes() {
491  std::list<NodePtr> nodes;
492  std::copy(getChannels().begin(),getChannels().end(),std::back_inserter(nodes));
493  std::copy(getAuthorities().begin(),getAuthorities().end(),std::back_inserter(nodes));
494  return nodes;
495  }
496 
498  std::list<ChannelNodePtr>& getChannels() {
499  return mChannels; }
500 
502  std::list<AuthorityNodePtr>& getAuthorities() {
503  return mAuthorities; }
504 
506  std::list<NamespaceNodePtr>& getNamespaces() {
507  return mNamespaces; }
508 
510  std::list<FrameworkNodePtr>& getFrameworks() {
511  return mFrameworks; }
512 
515  return mRootNamespace; }
516 
519  {
520  assert(mRootNamespace);
521 
522  // find direct ancestor node
523  NamespaceNodePtr ancestor = mRootNamespace;
524  bool abort;
525  do {
526  abort = true;
527  foreach(NamespaceNodePtr child, ancestor->children)
528  {
529  if(child->ns.isAncestorOf(node->ns)) {
530  ancestor = child;
531  abort = false;
532  break;
533  }
534  }
535  } while(!abort);
536 
537 
538  // now add all children from ancestor that are actually our children
539  // and remove them from ancestor
540  auto childrenSet = ancestor->children;
541  foreach(NamespaceNodePtr child, childrenSet)
542  {
543  if(child->ns.isChildOf(node->ns)) {
544  node->children.insert(child);
545  ancestor->children.erase(child);
546  child->parent = node;
547  }
548  }
549 
550  // add us as new child to the ancestor
551  ancestor->children.insert(node);
552  // which is our parent
553  node->parent = ancestor;
554 
555  // check if 'ancestor' is direct namespace parent of 'node'
556  // if not, add all missing namespaces between 'ancestor' and 'node' recursively,
557  // beginning with the direct parent of 'node'
558  auto parent_ns = node->ns.parent();
559  if (parent_ns != ancestor->ns)
560  {
561  NamespaceNodePtr n(new NamespaceNode(parent_ns));
562  mNamespaces.push_back(n);
564  }
565  }
566 
567  /*
568  2nd version of the above method, work in progress
569  void integrateNamespaceNode2(NamespaceNodePtr node)
570  {
571  assert(mRootNamespace);
572 
573  NamespaceNodePtr parent = getNamespaceNode(node->ns.parent());
574  parent->children.insert(node);
575  node->parent = parent;
576  }
577  */
578 
579 protected:
580 
581  boost::mutex mMutex;
582  std::list<AuthorityNodePtr> mAuthorities;
583  std::list<ChannelNodePtr> mChannels;
584  std::list<NamespaceNodePtr> mNamespaces;
585  std::list<FrameworkNodePtr> mFrameworks;
587 
589 
590 
591 
592  template <typename Container, typename Key>
593  typename Container::value_type findPtr(Container& c, const Key& key)
594  {
595  foreach(typename Container::value_type ptr, c)
596  if(*ptr == key)
597  return ptr;
598  return typename Container::value_type();
599  }
600 };
601 
603 
604 } // namespace
605 
606 #endif
bool operator==(const std::string &iName)
Definition: FrameworkGraph.h:309
NamespaceNodePtr mRootNamespace
Definition: FrameworkGraph.h:586
std::set< AuthorityNodePtr > getSubscribedAuthorities()
Definition: FrameworkGraph.h:155
std::set< NamespaceNodePtr > children
sub-namespaces that live in this namespace
Definition: FrameworkGraph.h:297
FrameworkNode(const std::string &iName)
Definition: FrameworkGraph.h:308
Base class for all nodes in the framework computation graph.
Definition: FrameworkGraph.h:125
std::string id
the authority id. will be generated for anonymous authorities
Definition: AuthorityDescription.h:96
ResourceName ns
the name of the namespace
Definition: FrameworkGraph.h:291
std::set< ChannelNodePtr > mPublishedChannels
Definition: FrameworkGraph.h:257
std::list< NamespaceNodePtr > mNamespaces
Definition: FrameworkGraph.h:584
boost::shared_ptr< Node > NodePtr
Definition: FrameworkGraph.h:107
std::set< ChannelNodePtr > mSubscribedChannels
Definition: FrameworkGraph.h:256
Container::value_type findPtr(Container &c, const Key &key)
Definition: FrameworkGraph.h:593
std::set< NodePtr > nodes
channel and authority nodes within this framework
Definition: FrameworkGraph.h:327
std::list< ChannelNodePtr > mChannels
Definition: FrameworkGraph.h:583
NamespaceNodePtr getRootNamespace()
Returns the root namespace node.
Definition: FrameworkGraph.h:514
std::list< FrameworkNodePtr > & getFrameworks()
Returns all framework nodes.
Definition: FrameworkGraph.h:510
bool operator==(const std::string &id)
Definition: FrameworkGraph.h:186
NamespaceNodePtr getNamespace()
Returns the namespace node where this channel lives in.
Definition: FrameworkGraph.h:164
boost::shared_ptr< ChannelNode > ChannelNodePtr
Definition: FrameworkGraph.h:110
Descriptive informations about an authority.
Definition: FrameworkGraph.h:66
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
ChannelNode(const std::string &iID)
Definition: FrameworkGraph.h:140
The framework module responsible for connections to remote frameworks.
Represents a single authority in the framwork computation graph.
Definition: FrameworkGraph.h:183
Class for 2D, 3D and N-dimensional points.
FrameworkNodePtr getFramework()
Returns the framework where this authority lives in.
Definition: FrameworkGraph.h:218
std::list< FrameworkNodePtr > mFrameworks
Definition: FrameworkGraph.h:585
virtual std::set< NodePtr > getAdjacentNodes()
Returns the adjacent (incoming and outgoing nodes)
Definition: FrameworkGraph.h:315
std::set< ChannelNodePtr > getPublishedChannels()
Returns all channel nodes with channels that are published by the authority.
Definition: FrameworkGraph.h:203
FrameworkGraph & operator=(FrameworkGraph &&other) noexcept
Definition: FrameworkGraph.h:343
std::set< AuthorityNodePtr > mSubscribedAuthorities
Definition: FrameworkGraph.h:175
boost::mutex mMutex
Definition: FrameworkGraph.h:581
NamespaceNodePtr mNamespace
Definition: FrameworkGraph.h:177
boost::shared_ptr< NamespaceNode > NamespaceNodePtr
Definition: FrameworkGraph.h:116
AuthorityNode(const AuthorityDescription &iDesc)
Definition: FrameworkGraph.h:185
FrameworkNodePtr mFramework
Definition: FrameworkGraph.h:259
#define MIRA_FW
Macro for accessing the framework instance.
Definition: Framework.h:73
void swap(FrameworkGraph &other)
Definition: FrameworkGraph.h:348
virtual std::set< NodePtr > getAdjacentNodes()
Returns the adjacent (incoming and outgoing nodes)
Definition: FrameworkGraph.h:145
std::set< NodePtr > nodes
channel and authority nodes within this namespace
Definition: FrameworkGraph.h:300
This is the descriptive part of an authority.
Definition: AuthorityDescription.h:61
std::set< ChannelNodePtr > getSubscribedChannels()
Returns all channel nodes with channels the authority is subscribed on.
Definition: FrameworkGraph.h:208
std::map< AuthorityNodePtr, std::set< ChannelNodePtr > > getDependers()
Returns all authority nodes that DEPEND on this authority.
Definition: FrameworkGraph.h:240
NamespaceNodePtr getNamespace()
Returns the namespace node where this authority lives in.
Definition: FrameworkGraph.h:213
virtual ~Node()
Definition: FrameworkGraph.h:128
Represents a namespace in the framework computation graph within the overall namespace hierarchy...
Definition: FrameworkGraph.h:266
Class for storing/combining/managing resource names consisting of namespaces and names separated by &#39;...
Definition: ResourceName.h:68
bool mGraphHasChanged
Definition: FrameworkGraph.h:588
std::string name
the name
Definition: FrameworkGraph.h:324
std::map< AuthorityNodePtr, std::set< ChannelNodePtr > > getDependees()
Returns all authority nodes that THIS authority depends on.
Definition: FrameworkGraph.h:227
boost::shared_ptr< AuthorityNode > AuthorityNodePtr
Definition: FrameworkGraph.h:113
bool operator==(const std::string &id)
Definition: FrameworkGraph.h:141
NamespaceNodePtr parent
the namespace parent node (if we are not the root node)
Definition: FrameworkGraph.h:294
Represents a framework in the framework computation graph.
Definition: FrameworkGraph.h:306
boost::mutex & mutex()
Definition: FrameworkGraph.h:359
std::string id
the fully qualified name of the node (the id)
Definition: FrameworkGraph.h:171
std::list< ChannelNodePtr > & getChannels()
Returns all channel nodes.
Definition: FrameworkGraph.h:498
bool discover(boost::function< void()> changeCb=boost::function< void()>())
Discovers the whole structure of all connected frameworks with its authorities, channels, services, etc.
Definition: FrameworkGraph.h:369
virtual std::set< NodePtr > getAdjacentNodes()
Returns the adjacent (incoming and outgoing nodes)
Definition: FrameworkGraph.h:192
static void setParent(NamespaceNodePtr child, NamespaceNodePtr parent)
workaround to avoid shared_from_this
Definition: FrameworkGraph.h:274
std::list< AuthorityNodePtr > & getAuthorities()
Returns all authority nodes.
Definition: FrameworkGraph.h:502
ResourceName ns
the full namespace (starting from root) of this authority
Definition: AuthorityDescription.h:95
std::list< NamespaceNodePtr > & getNamespaces()
Returns all namespace nodes.
Definition: FrameworkGraph.h:506
std::set< AuthorityNodePtr > getPublishingAuthorities()
Definition: FrameworkGraph.h:159
Represents the whole computation graph with all known units/authorities and channels within their nam...
Definition: FrameworkGraph.h:101
NamespaceNode(const ResourceName &iNs)
Definition: FrameworkGraph.h:268
virtual std::set< NodePtr > getAdjacentNodes()=0
Returns the adjacent (incoming and outgoing nodes)
void integrateNamespaceNode(NamespaceNodePtr node)
inserts a new namespace node and reparents the existing namespace nodes, if necessary.
Definition: FrameworkGraph.h:518
std::list< AuthorityNodePtr > mAuthorities
Definition: FrameworkGraph.h:582
AuthorityDescription desc
full information on the authority
Definition: FrameworkGraph.h:252
FrameworkGraph()
Creates an emtpy framework graph object.
Definition: FrameworkGraph.h:333
std::set< AuthorityNodePtr > mPublishingAuthorities
Definition: FrameworkGraph.h:176
FrameworkGraph(FrameworkGraph &&other) noexcept
Definition: FrameworkGraph.h:339
boost::shared_ptr< FrameworkNode > FrameworkNodePtr
Definition: FrameworkGraph.h:119
bool operator==(const ResourceName &iNs)
Definition: FrameworkGraph.h:269
The framework that holds all manager classes and provides startup and shutdown of all framework relat...
NamespaceNodePtr mNamespace
Definition: FrameworkGraph.h:258
Represents a single channel in the framwork computation graph.
Definition: FrameworkGraph.h:137
virtual std::set< NodePtr > getAdjacentNodes()
Returns the adjacent (incoming and outgoing nodes)
Definition: FrameworkGraph.h:282
std::list< NodePtr > getNodes()
Returns all channel and authority nodes.
Definition: FrameworkGraph.h:490