source: finroc_plugins_network_transport/runtime_info/tFrameworkElementInfo.h @ 21:f564c2b6f60b

17.03
Last change on this file since 21:f564c2b6f60b was 21:f564c2b6f60b, checked in by Max Reichardt <mreichardt@…>, 5 years ago

Adds options to tFrameworkElementInfo to also serialize owned connectors (required in TCP plugin)

File size: 11.9 KB
Line 
1//
2// You received this file as part of Finroc
3// A framework for intelligent robot control
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
18// with this program; if not, write to the Free Software Foundation, Inc.,
19// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20//
21//----------------------------------------------------------------------
22/*!\file    plugins/network_transport/runtime_info/tFrameworkElementInfo.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2013-01-12
27 *
28 * \brief   Contains tFrameworkElementInfo
29 *
30 * \b tFrameworkElementInfo
31 *
32 * Information on (shared) framework elements - as exchanged by peers.
33 *
34 */
35//----------------------------------------------------------------------
36#ifndef __plugins__network_transport__runtime_info__tFrameworkElementInfo_h__
37#define __plugins__network_transport__runtime_info__tFrameworkElementInfo_h__
38
39//----------------------------------------------------------------------
40// External includes (system with <>, local with "")
41//----------------------------------------------------------------------
42#include "plugins/data_ports/common/tAbstractDataPort.h"
43#include "plugins/data_ports/type_traits.h"
44#include "core/tFrameworkElementTags.h"
45#include "plugins/data_ports/common/tAbstractDataPort.h"
46
47//----------------------------------------------------------------------
48// Internal includes with ""
49//----------------------------------------------------------------------
50#include "plugins/network_transport/runtime_info/definitions.h"
51#include "plugins/network_transport/runtime_info/tConnectorInfo.h"
52#include "plugins/network_transport/runtime_info/tRemoteType.h"
53#include "plugins/network_transport/runtime_info/tUriConnectorInfo.h"
54
55//----------------------------------------------------------------------
56// Namespace declaration
57//----------------------------------------------------------------------
58namespace finroc
59{
60namespace network_transport
61{
62namespace runtime_info
63{
64
65//----------------------------------------------------------------------
66// Forward declarations / typedefs / enums
67//----------------------------------------------------------------------
68
69namespace internal
70{
71
72/*! Maximum number of links per port */
73enum { cMAX_LINKS = 3 };
74
75struct tLink
76{
77  /*! Path to this port (only required for shared ports) */
78  rrlib::uri::tPath path;
79
80  /*! Name of this framework element (from parent) */
81  std::string name;
82
83  /*! Handle of parent */
84  core::tFrameworkElement::tHandle parent_handle = 0;
85};
86
87typedef std::array<tLink, cMAX_LINKS> tLinkArray;
88
89void Serialize(rrlib::serialization::tOutputStream& stream, const core::tFrameworkElement::tFlags& flags, const tLinkArray& link_data,
90               const std::array<const std::string*, cMAX_LINKS>* alt_link_name_storage, uint8_t link_count, const rrlib::rtti::tType& type, const std::vector<std::string>& tags);
91}
92
93//----------------------------------------------------------------------
94// Class declaration
95//----------------------------------------------------------------------
96//! Framework element information
97/*!
98 * Information on (shared) framework elements - as exchanged by peers.
99 *
100 * In C++, this struct can only store info shared ports.
101 * The static Serialize method also serializes framework element info
102 * and port connection info.
103 */
104template <bool Tremote>
105struct tFrameworkElementInfo
106{
107  typedef typename core::tFrameworkElement::tHandle tHandle;
108  typedef typename core::tFrameworkElement::tFlag tFlag;
109  typedef typename core::tFrameworkElement::tFlags tFlags;
110  typedef typename std::conditional<Tremote, const tRemoteType*, rrlib::rtti::tType>::type tType;
111
112  struct tID
113  {
114    /*! Handle of element in runtime environment */
115    core::tFrameworkElement::tHandle handle = 0;
116
117    tID() : handle(0)
118    {}
119    tID(const core::tFrameworkElement& element) :
120      handle(element.GetHandle())
121    {}
122
123  } id;
124
125  struct tStaticInfo
126  {
127    /*! Framework element flags */
128    core::tFrameworkElement::tFlags flags;
129
130    typedef internal::tLinkArray tLinkArray;
131
132    /*! Per-link data - in fixed array for efficiency reasons */
133    tLinkArray link_data;
134
135    /*! Number of links */
136    uint8_t link_count;
137
138    /*! Type of port data */
139    tType type;
140
141    /*! Classification tags (strings) assigned to framework element */
142    std::vector<std::string> tags;
143
144
145    tStaticInfo() : link_count(0)
146    {}
147
148    template < bool ENABLE = !Tremote >
149    tStaticInfo(typename std::enable_if<ENABLE, const core::tFrameworkElement>::type& element) :
150      flags(element.GetAllFlags()),
151      link_count(0),
152      tags(core::tFrameworkElementTags::GetTags(element))
153    {
154      link_count = element.IsPort() ? element.GetLinkCount() : 1;
155      if (link_count > link_data.size())
156      {
157        FINROC_LOG_PRINT(WARNING, "Only three links are supported");
158        link_count = link_data.size();
159      }
160
161      bool shared_port = IsSharedPort(element);
162      for (size_t i = 0; i < link_count; i++)
163      {
164        if (shared_port)
165        {
166          element.GetPath(link_data[i].path, i);
167        }
168        link_data[i].name = element.GetLink(i).GetName();
169        link_data[i].parent_handle = element.GetParent(i)->GetHandle();
170      }
171
172      if (element.IsPort())
173      {
174        type = static_cast<const core::tAbstractPort&>(element).GetDataType();
175      }
176    }
177
178    template < bool ENABLE = !Tremote >
179    typename std::enable_if<ENABLE, bool>::type IsDataPort() const
180    {
181      return flags.Get(core::tFrameworkElementFlag::PORT) && data_ports::IsDataFlowType(type);
182    }
183
184  } static_info;
185
186  /*! Part of information that may be changed later */
187  struct tDynamicInfo
188  {
189    /*! Only relevant for ports: Strategy to use for port if it is destination port */
190    int16_t strategy;
191
192    tDynamicInfo() : strategy(-1)
193    {}
194    tDynamicInfo(const core::tFrameworkElement& element) :
195      strategy(-1)
196    {
197      if (IsDataPort(element))
198      {
199        strategy = static_cast<const data_ports::common::tAbstractDataPort&>(element).GetStrategy();
200      }
201    }
202
203  } dynamic_info;
204
205
206  tFrameworkElementInfo() : id(), static_info(), dynamic_info()
207  {}
208
209  template < bool ENABLE = !Tremote >
210  tFrameworkElementInfo(typename std::enable_if<ENABLE, const core::tFrameworkElement>::type& element) : id(element), static_info(element), dynamic_info(element)
211  {}
212
213  /*!
214   * \return Whether provided element is a data flow port
215   */
216  static bool IsDataPort(const core::tFrameworkElement& framework_element)
217  {
218    return framework_element.IsPort() && data_ports::IsDataFlowType(static_cast<const core::tAbstractPort&>(framework_element).GetDataType());
219  }
220
221  /*!
222   * \return Whether provided element a shared port (to be announced to other peers)?
223   */
224  static bool IsSharedPort(const core::tFrameworkElement& framework_element)
225  {
226    return framework_element.IsPort() && framework_element.GetFlag(core::tFrameworkElement::tFlag::SHARED) &&
227           (!framework_element.GetFlag(core::tFrameworkElement::tFlag::NETWORK_ELEMENT));
228  }
229
230  /*!
231   * Serializes info on single framework element to stream so that it can later
232   * be deserialized in typically another runtime environment.
233   *
234   * \param stream Binary stream to serialize to
235   * \param framework_element Framework element to serialize info of
236   * \param serialize_owned_connectors Whether to serialize connectors owned by framework element
237   *
238   * TODO: avoid frequent reallocation of (typically one) tPath
239   */
240  template < bool ENABLE = !Tremote >
241  static void Serialize(typename std::enable_if<ENABLE, rrlib::serialization::tOutputStream>::type& stream, const core::tFrameworkElement& framework_element, bool serialize_owned_connectors = false)
242  {
243    rrlib::uri::tURI uri;
244
245    // collect links
246    internal::tLinkArray link_data;
247    std::array<const std::string*, internal::cMAX_LINKS> alt_link_name_storage;
248    size_t link_count = framework_element.GetLinkCount();
249    if (link_count > link_data.size())
250    {
251      FINROC_LOG_PRINT(WARNING, "Only three links are supported");
252      link_count = link_data.size();
253    }
254
255    tStaticInfo static_info;
256    bool shared_port = IsSharedPort(framework_element);
257    for (size_t i = 0; i < link_count; i++)
258    {
259      if (shared_port)
260      {
261        framework_element.GetPath(link_data[i].path, i);
262      }
263      alt_link_name_storage[i] = &framework_element.GetName();
264      link_data[i].parent_handle = framework_element.GetParent(i)->GetHandle();
265    }
266
267    // Serialize
268    stream << tID(framework_element);
269    internal::Serialize(stream, framework_element.GetAllFlags(), link_data, &alt_link_name_storage, link_count, framework_element.IsPort() ? static_cast<const core::tAbstractPort&>(framework_element).GetDataType() : rrlib::rtti::tType(), core::tFrameworkElementTags::GetTags(framework_element));
270    if (IsDataPort(framework_element))
271    {
272      stream << tDynamicInfo(framework_element);
273    }
274
275    enum tNextConnector { NONE, PLAIN, URI };
276
277    if (serialize_owned_connectors && framework_element.IsPort())
278    {
279      const core::tAbstractPort& port = static_cast<const core::tAbstractPort&>(framework_element);
280      for (auto it = port.OutgoingConnectionsBegin(); it != port.OutgoingConnectionsEnd(); ++it)
281      {
282        runtime_info::tConnectorInfo info(*it);
283        stream.WriteByte(static_cast<uint8_t>(PLAIN));
284        stream << it->Destination().GetHandle() << info.static_info;
285      }
286      for (auto & connector : port.UriConnectors())
287      {
288        if (connector)
289        {
290          tUriConnectorInfo info(*connector);
291          stream.WriteByte(static_cast<uint8_t>(URI));
292          stream << info.id.index << info.static_info << info.dynamic_info;
293        }
294      }
295      stream.WriteByte(static_cast<uint8_t>(NONE));
296    }
297  }
298
299};
300
301typedef tFrameworkElementInfo<false> tLocalFrameworkElementInfo;
302typedef tFrameworkElementInfo<true> tRemoteFrameworkElementInfo;
303
304rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tRemoteFrameworkElementInfo& info);
305
306inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tID& info)
307{
308  stream << info.handle;
309  return stream;
310}
311
312inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tStaticInfo& info)
313{
314  internal::Serialize(stream, info.flags, info.link_data, nullptr, info.link_count, info.type, info.tags);
315  return stream;
316}
317
318inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo::tDynamicInfo& info)
319{
320  stream << info.strategy;
321  // As structure is only sent to client with new protocol, we can omit network update time
322  return stream;
323}
324
325inline rrlib::serialization::tInputStream& operator >> (rrlib::serialization::tInputStream& stream, tRemoteFrameworkElementInfo::tDynamicInfo& info)
326{
327  if (stream.GetSourceInfo().revision == 0)
328  {
329    stream.ReadInt();
330    stream >> info.strategy;
331    stream.ReadShort();
332  }
333  else
334  {
335    stream >> info.strategy;
336  }
337  return stream;
338}
339
340inline rrlib::serialization::tOutputStream& operator << (rrlib::serialization::tOutputStream& stream, const tLocalFrameworkElementInfo& info)
341{
342  stream << info.id << info.static_info;
343  if (info.static_info.IsDataPort())
344  {
345    stream << info.dynamic_info;;
346  }
347  return stream;
348}
349
350
351//----------------------------------------------------------------------
352// End of namespace declaration
353//----------------------------------------------------------------------
354}
355}
356}
357
358#endif
Note: See TracBrowser for help on using the repository browser.