source: finroc_plugins_runtime_construction/tAdministrationService.cpp @ 91:16104eff1b99

17.03
Last change on this file since 91:16104eff1b99 was 91:16104eff1b99, checked in by Max Reichardt <mreichardt@…>, 4 years ago

Changes tAdministrationService::DeleteUriConnector to be more suitable for use with finstruct

File size: 25.5 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/runtime_construction/tAdministrationService.cpp
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-12-02
27 *
28 */
29//----------------------------------------------------------------------
30#include "plugins/runtime_construction/tAdministrationService.h"
31
32//----------------------------------------------------------------------
33// External includes (system with <>, local with "")
34//----------------------------------------------------------------------
35#include "rrlib/rtti_conversion/tStaticCastOperation.h"
36#include "core/tRuntimeEnvironment.h"
37#include "core/tRuntimeSettings.h"
38#include "plugins/data_ports/tGenericPort.h"
39#include "plugins/network_transport/tNetworkTransportPlugin.h"
40#include "plugins/parameters/tConfigFile.h"
41#include "plugins/parameters/internal/tParameterInfo.h"
42#include "plugins/scheduling/tExecutionControl.h"
43
44//----------------------------------------------------------------------
45// Internal includes with ""
46//----------------------------------------------------------------------
47#include "plugins/runtime_construction/tCreateFrameworkElementAction.h"
48#include "plugins/runtime_construction/tFinstructable.h"
49#include "plugins/runtime_construction/dynamic_loading.h"
50
51//----------------------------------------------------------------------
52// Debugging
53//----------------------------------------------------------------------
54#include <cassert>
55
56//----------------------------------------------------------------------
57// Namespace usage
58//----------------------------------------------------------------------
59
60//----------------------------------------------------------------------
61// Namespace declaration
62//----------------------------------------------------------------------
63namespace finroc
64{
65namespace runtime_construction
66{
67
68//----------------------------------------------------------------------
69// Forward declarations / typedefs / enums
70//----------------------------------------------------------------------
71
72//----------------------------------------------------------------------
73// Const values
74//----------------------------------------------------------------------
75static const char* cPORT_NAME = "Administration";
76
77static rpc_ports::tRPCInterfaceType<tAdministrationService> cTYPE("Administration Interface", &tAdministrationService::Connect,
78    &tAdministrationService::CreateModule, &tAdministrationService::DeleteElement, &tAdministrationService::Disconnect,
79    &tAdministrationService::DisconnectAll, &tAdministrationService::GetAnnotation, &tAdministrationService::GetCreateModuleActions,
80    &tAdministrationService::GetModuleLibraries, &tAdministrationService::GetParameterInfo, &tAdministrationService::IsExecuting,
81    &tAdministrationService::LoadModuleLibrary, &tAdministrationService::PauseExecution, &tAdministrationService::SaveAllFinstructableFiles,
82    &tAdministrationService::SaveFinstructableGroup, &tAdministrationService::SetAnnotation, &tAdministrationService::SetPortValue,
83    &tAdministrationService::StartExecution, &tAdministrationService::NetworkConnect, &tAdministrationService::ConnectPorts,  // NetworkConnect etc. are last in order to not break binary compatibility
84    &tAdministrationService::CreateUriConnector, &tAdministrationService::DeleteUriConnector);
85
86static tAdministrationService administration_service;
87
88/*! Serialization info for memory buffers in some commands */
89static const rrlib::serialization::tSerializationInfo cBASIC_UID_SERIALIZATION_INFO(0, rrlib::serialization::tRegisterEntryEncoding::UID, 0);
90
91//----------------------------------------------------------------------
92// Implementation
93//----------------------------------------------------------------------
94
95static core::tRuntimeEnvironment& Runtime()
96{
97  return core::tRuntimeEnvironment::GetInstance();
98}
99
100/*!
101 * Returns all relevant execution controls for start/stop command on specified element
102 * (Helper method for IsExecuting, StartExecution and PauseExecution)
103 *
104 * \param result Result buffer for list of execution controls
105 * \param element_handle Handle of element
106 */
107static void GetExecutionControls(std::vector<scheduling::tExecutionControl*>& result, int element_handle)
108{
109  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
110  if (element)
111  {
112    scheduling::tExecutionControl::FindAll(result, *element);
113    if (result.size() == 0)
114    {
115      scheduling::tExecutionControl* control = scheduling::tExecutionControl::Find(*element);
116      if (control)
117      {
118        result.push_back(control);
119      }
120    }
121  }
122}
123
124tAdministrationService::tAdministrationService()
125{}
126
127tAdministrationService::~tAdministrationService()
128{}
129
130void tAdministrationService::Connect(int source_port_handle, int destination_port_handle)
131{
132  ConnectPorts(source_port_handle, destination_port_handle, core::tConnectOptions(core::tConnectionFlag::FINSTRUCTED));
133}
134
135std::string tAdministrationService::ConnectPorts(int source_port_handle, int destination_port_handle, const core::tConnectOptions& connect_options)
136{
137  std::stringstream result;
138  auto cVOLATILE = core::tFrameworkElement::tFlag::VOLATILE;
139  core::tAbstractPort* source_port = Runtime().GetPort(source_port_handle);
140  core::tAbstractPort* destination_port = Runtime().GetPort(destination_port_handle);
141  core::tConnectOptions options = connect_options;
142  if ((!source_port) || (!destination_port))
143  {
144    const char* result = "At least one port to be connected does not exist";
145    FINROC_LOG_PRINT(WARNING, result);
146    return result;
147  }
148  if (source_port->GetFlag(cVOLATILE) && destination_port->GetFlag(cVOLATILE))
149  {
150    FINROC_LOG_PRINT(WARNING, "Cannot really persistently connect two network ports: ", source_port, ", ", destination_port);
151  }
152
153  // Connect
154  try
155  {
156    if (source_port->GetFlag(cVOLATILE) && (!destination_port->GetFlag(cVOLATILE)))
157    {
158      options.flags |= core::tConnectionFlag::RECONNECT;
159      destination_port->ConnectTo(source_port->GetPath(), options);
160    }
161    else if (destination_port->GetFlag(cVOLATILE) && (!source_port->GetFlag(cVOLATILE)))
162    {
163      options.flags |= core::tConnectionFlag::RECONNECT;
164      source_port->ConnectTo(destination_port->GetPath(), options);
165    }
166    else
167    {
168      source_port->ConnectTo(*destination_port, options);
169    }
170  }
171  catch (const std::exception& e)
172  {
173    result << "Could not connect ports '" << source_port << "' and '" << destination_port << "'. Reason: " << e.what();
174    FINROC_LOG_PRINT(WARNING, result.str());
175    return result.str();
176  }
177
178  // Connection check
179  if (!source_port->IsConnectedTo(*destination_port))
180  {
181    result << "Could not connect ports '" << source_port << "' and '" << destination_port << "' (see output of connected Finroc program for details).";
182    FINROC_LOG_PRINT(WARNING, result.str());
183  }
184  else
185  {
186    FINROC_LOG_PRINT(USER, "Connected ports ", source_port, " ", destination_port);
187  }
188  return result.str();
189}
190
191void tAdministrationService::CreateAdministrationPort()
192{
193  rpc_ports::tServerPort<tAdministrationService>(administration_service, cPORT_NAME, cTYPE,
194      &core::tRuntimeEnvironment::GetInstance().GetElement(core::tSpecialRuntimeElement::SERVICES));
195}
196
197std::string tAdministrationService::CreateModule(uint32_t create_action_index, const std::string& module_name, int parent_handle, const rrlib::serialization::tMemoryBuffer& serialized_creation_parameters)
198{
199  std::string error_message;
200
201  try
202  {
203    rrlib::thread::tLock lock(Runtime().GetStructureMutex());
204    auto& create_actions = tCreateFrameworkElementAction::GetConstructibleElements();
205    if (create_action_index >= create_actions.Size())
206    {
207      error_message = "Invalid construction action index";
208    }
209    else
210    {
211      tCreateFrameworkElementAction* create_action = create_actions[create_action_index];
212      core::tFrameworkElement* parent = core::tRuntimeEnvironment::GetInstance().GetElement(parent_handle);
213      if (parent == NULL || (!parent->IsReady()))
214      {
215        error_message = "Parent not available. Cancelling remote module creation.";
216      }
217      else if (parent->GetChild(module_name))
218      {
219        error_message = std::string("Element with name '") + module_name + "' already exists. Creating another module with this name is not allowed.";
220      }
221      else
222      {
223        FINROC_LOG_PRINT(USER, "Creating Module ", parent, "/", module_name);
224        std::unique_ptr<tConstructorParameters> parameters;
225        if (create_action->GetParameterTypes() && create_action->GetParameterTypes()->Size() > 0)
226        {
227          parameters.reset(create_action->GetParameterTypes()->Instantiate());
228          rrlib::serialization::tInputStream input_stream(serialized_creation_parameters, cBASIC_UID_SERIALIZATION_INFO);
229          for (size_t i = 0; i < parameters->Size(); i++)
230          {
231            parameters::internal::tStaticParameterImplementationBase& parameter = parameters->Get(i);
232            try
233            {
234              parameter.DeserializeValue(input_stream);
235            }
236            catch (const std::exception& e)
237            {
238              error_message = "Error deserializing value for parameter " + parameter.GetName();
239              FINROC_LOG_PRINT(ERROR, e);
240            }
241          }
242        }
243        core::tFrameworkElement* created = create_action->CreateModule(parent, module_name, parameters.get());
244        tFinstructable::SetFinstructed(*created, *create_action, parameters.get());
245        created->Init();
246        parameters.release();
247        FINROC_LOG_PRINT(USER, "Creating Module succeeded");
248      }
249    }
250  }
251  catch (const std::exception& e)
252  {
253    FINROC_LOG_PRINT(ERROR, e);
254    error_message = e.what();
255  }
256
257  // Possibly print error message
258  if (error_message.size() > 0)
259  {
260    FINROC_LOG_PRINT(ERROR, error_message);
261  }
262
263  return error_message;
264}
265
266std::string tAdministrationService::CreateUriConnector(int local_port_handle, const rrlib::uri::tURI& uri, const core::tUriConnectOptions& connect_options)
267{
268  core::tAbstractPort* port = core::tRuntimeEnvironment::GetInstance().GetPort(local_port_handle);
269  std::stringstream result;
270  if (port && port->IsReady())
271  {
272    try
273    {
274      core::tUriConnector::Create(*port, uri, connect_options);
275      return "";
276    }
277    catch (const std::exception& e)
278    {
279      result << "Creating URI connector failed: " << e.what();
280    }
281  }
282  else
283  {
284    result << "No port with local handle " << local_port_handle << " found";
285  }
286  FINROC_LOG_PRINT(WARNING, result.str());
287  return result.str();
288}
289
290void tAdministrationService::DeleteElement(int element_handle)
291{
292  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
293  if (element && (!element->IsDeleted()))
294  {
295    FINROC_LOG_PRINT(USER, "Deleting element ", element);
296    element->ManagedDelete();
297  }
298  else
299  {
300    FINROC_LOG_PRINT(ERROR, "Could not delete Framework element, because it does not appear to be available.");
301  }
302}
303
304bool tAdministrationService::DeleteUriConnector(int local_port_handle, uint index)
305{
306  core::tAbstractPort* port = core::tRuntimeEnvironment::GetInstance().GetPort(local_port_handle);
307  std::stringstream result;
308  if (port && port->IsReady())
309  {
310    if (port->UriConnectors().size() > index && port->UriConnectors()[index])
311    {
312      port->UriConnectors()[index]->Disconnect();
313      return true;
314    }
315    result << "No URI connector with index " << index << " found";
316  }
317  else
318  {
319    result << "No port with local handle " << local_port_handle << " found";
320  }
321  FINROC_LOG_PRINT(WARNING, result.str());
322  return false;
323}
324
325void tAdministrationService::Disconnect(int source_port_handle, int destination_port_handle)
326{
327  auto cVOLATILE = core::tFrameworkElement::tFlag::VOLATILE;
328  core::tAbstractPort* source_port = Runtime().GetPort(source_port_handle);
329  core::tAbstractPort* destination_port = Runtime().GetPort(destination_port_handle);
330  if ((!source_port) || (!destination_port))
331  {
332    FINROC_LOG_PRINT(WARNING, "At least one port to be disconnected does not exist");
333    return;
334  }
335  if (source_port->GetFlag(cVOLATILE))
336  {
337    destination_port->DisconnectFrom(source_port->GetPath());
338  }
339  if (destination_port->GetFlag(cVOLATILE))
340  {
341    source_port->DisconnectFrom(destination_port->GetPath());
342  }
343  source_port->DisconnectFrom(*destination_port);
344  if (source_port->IsConnectedTo(*destination_port))
345  {
346    FINROC_LOG_PRINT(WARNING, "Could not disconnect ports ", source_port, " ", destination_port);
347  }
348  else
349  {
350    FINROC_LOG_PRINT(USER, "Disconnected ports ", source_port, " ", destination_port);
351  }
352}
353
354void tAdministrationService::DisconnectAll(int port_handle)
355{
356  core::tAbstractPort* port = Runtime().GetPort(port_handle);
357  if (!port)
358  {
359    FINROC_LOG_PRINT(WARNING, "Port to be disconnected does not exist");
360    return;
361  }
362  port->DisconnectAll();
363  FINROC_LOG_PRINT(USER, "Disconnected port ", port);
364}
365
366rrlib::serialization::tMemoryBuffer tAdministrationService::GetAnnotation(int element_handle, const std::string& annotation_type_name)
367{
368  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
369  rrlib::rtti::tType type = rrlib::rtti::tType::FindType(annotation_type_name);
370  if (element && element->IsReady() && type)
371  {
372    core::tAnnotation* result = element->GetAnnotation(type.GetRttiName());
373    if (result)
374    {
375      rrlib::serialization::tMemoryBuffer result_buffer;
376      rrlib::serialization::tOutputStream output_stream(result_buffer, cBASIC_UID_SERIALIZATION_INFO);
377      rrlib::rtti::tTypedConstPointer annotation_pointer(result, type);
378      annotation_pointer.Serialize(output_stream);
379      output_stream.Close();
380      return result_buffer;
381    }
382  }
383  else
384  {
385    FINROC_LOG_PRINT(ERROR, "Could not query element for annotation type ", annotation_type_name);
386  }
387  return rrlib::serialization::tMemoryBuffer(0);
388}
389
390rrlib::serialization::tMemoryBuffer tAdministrationService::GetCreateModuleActions()
391{
392  FINROC_LOG_PRINT(WARNING, "GetCreateModuleActions() is superseded");
393  return rrlib::serialization::tMemoryBuffer();
394}
395
396rrlib::serialization::tMemoryBuffer tAdministrationService::GetModuleLibraries()
397{
398  rrlib::serialization::tMemoryBuffer result_buffer;
399  rrlib::serialization::tOutputStream output_stream(result_buffer);
400  std::vector<tSharedLibrary> libs = GetLoadableFinrocLibraries();
401  for (size_t i = 0; i < libs.size(); i++)
402  {
403    output_stream.WriteString(libs[i].ToString());
404  }
405  output_stream.Close();
406  return result_buffer;
407}
408
409rrlib::serialization::tMemoryBuffer tAdministrationService::GetParameterInfo(int root_element_handle)
410{
411  core::tFrameworkElement* root = Runtime().GetElement(root_element_handle);
412  if ((!root) || (!root->IsReady()))
413  {
414    FINROC_LOG_PRINT(ERROR, "Could not get parameter info for framework element ", root_element_handle);
415    return rrlib::serialization::tMemoryBuffer(0);
416  }
417
418  parameters::tConfigFile* config_file = parameters::tConfigFile::Find(*root);
419  rrlib::serialization::tMemoryBuffer result_buffer;
420  rrlib::serialization::tOutputStream output_stream(result_buffer, cBASIC_UID_SERIALIZATION_INFO);
421  if (!config_file)
422  {
423    output_stream.WriteBoolean(false);
424  }
425  else
426  {
427    output_stream.WriteBoolean(true);
428    output_stream.WriteInt(config_file->GetAnnotated<core::tFrameworkElement>()->GetHandle());
429    output_stream << *config_file;
430    for (auto it = root->SubElementsBegin(true); it != root->SubElementsEnd(); ++it)
431    {
432      parameters::tConfigFile* element_config = it->GetAnnotation<parameters::tConfigFile>();
433      if (element_config)
434      {
435        output_stream.WriteByte(1);
436        output_stream.WriteInt(it->GetHandle());
437        output_stream.WriteString(element_config->GetFilename());
438        output_stream.WriteBoolean(element_config->IsActive());
439      }
440      else
441      {
442        parameters::internal::tParameterInfo* parameter_info = it->GetAnnotation<parameters::internal::tParameterInfo>();
443        if (parameter_info && config_file == parameters::tConfigFile::Find(*it))
444        {
445          output_stream.WriteByte(2);
446          output_stream.WriteInt(it->GetHandle());
447          output_stream.WriteString(parameter_info->GetConfigEntry());
448        }
449      }
450    }
451  }
452  output_stream.Close();
453  return result_buffer;
454}
455
456tAdministrationService::tExecutionStatus tAdministrationService::IsExecuting(int element_handle)
457{
458  std::vector<scheduling::tExecutionControl*> controls;
459  GetExecutionControls(controls, element_handle);
460
461  bool stopped = false;
462  bool running = false;
463  for (auto it = controls.begin(); it < controls.end(); it++)
464  {
465    stopped |= (!(*it)->IsRunning());
466    running |= (*it)->IsRunning();
467  }
468  if (running && stopped)
469  {
470    return tExecutionStatus::BOTH;
471  }
472  else if (running)
473  {
474    return tExecutionStatus::RUNNING;
475  }
476  else if (stopped)
477  {
478    return tExecutionStatus::PAUSED;
479  }
480  return tExecutionStatus::NONE;
481}
482
483rrlib::serialization::tMemoryBuffer tAdministrationService::LoadModuleLibrary(const std::string& library_name)
484{
485  FINROC_LOG_PRINT(USER, "Loading library ", library_name);
486  try
487  {
488    DLOpen(library_name);
489  }
490  catch (const std::exception& exception)
491  {
492    FINROC_LOG_PRINT(ERROR, exception);
493  }
494  return GetCreateModuleActions();
495}
496
497std::string tAdministrationService::NetworkConnect(int local_port_handle, const std::string& preferred_transport,
498    const std::string& remote_runtime_uuid, int remote_port_handle, const std::string& remote_port_link, bool disconnect)
499{
500  const char* message = "tAdministrationService::NetworkConnect() is superseded. Please use a newer version of your tool that uses CreateUriConnector().";
501  FINROC_LOG_PRINT(WARNING, message);
502  return message;
503}
504
505void tAdministrationService::PauseExecution(int element_handle)
506{
507  std::vector<scheduling::tExecutionControl*> controls;
508  GetExecutionControls(controls, element_handle);
509  if (controls.size() == 0)
510  {
511    FINROC_LOG_PRINT(WARNING, "Start/Pause command has not effect");
512  }
513  for (auto it = controls.begin(); it < controls.end(); it++)
514  {
515    if ((*it)->IsRunning())
516    {
517      (*it)->Pause();
518    }
519  }
520}
521
522void tAdministrationService::SaveAllFinstructableFiles()
523{
524  FINROC_LOG_PRINT(USER, "Saving all finstructable files in this process:");
525  core::tRuntimeEnvironment& runtime_environment = core::tRuntimeEnvironment::GetInstance();
526  for (auto it = runtime_environment.SubElementsBegin(); it != runtime_environment.SubElementsEnd(); ++it)
527  {
528    if (it->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCTABLE_GROUP))
529    {
530      try
531      {
532        if (it->GetAnnotation<tFinstructable>())
533        {
534          it->GetAnnotation<tFinstructable>()->SaveXml();
535        }
536        else
537        {
538          FINROC_LOG_PRINT(ERROR, "Element invalidly flagged as finstructable: ", *it);
539        }
540      }
541      catch (const std::exception& e)
542      {
543        FINROC_LOG_PRINT(ERROR, "Error saving finstructable group ", *it);
544        FINROC_LOG_PRINT(ERROR, e);
545      }
546    }
547  }
548  FINROC_LOG_PRINT(USER, "Done.");
549}
550
551void tAdministrationService::SaveFinstructableGroup(int group_handle)
552{
553  core::tFrameworkElement* group = Runtime().GetElement(group_handle);
554  if (group && group->IsReady() && group->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCTABLE_GROUP))
555  {
556    try
557    {
558      if (group->GetAnnotation<tFinstructable>())
559      {
560        group->GetAnnotation<tFinstructable>()->SaveXml();
561      }
562      else
563      {
564        FINROC_LOG_PRINT(ERROR, "Element invalidly flagged as finstructable: ", *group);
565      }
566    }
567    catch (const std::exception& e)
568    {
569      FINROC_LOG_PRINT(ERROR, "Error saving finstructable group ", *group);
570      FINROC_LOG_PRINT(ERROR, e);
571    }
572  }
573  else
574  {
575    FINROC_LOG_PRINT(ERROR, "Could not save finstructable group, because it does not appear to be available.");
576  }
577}
578
579void tAdministrationService::SetAnnotation(int element_handle, const rrlib::serialization::tMemoryBuffer& serialized_annotation)
580{
581  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
582  if (element == NULL || (!element->IsReady()))
583  {
584    FINROC_LOG_PRINT(ERROR, "Parent not available. Canceling setting of annotation.");
585  }
586  else
587  {
588    rrlib::serialization::tInputStream input_stream(serialized_annotation, cBASIC_UID_SERIALIZATION_INFO);
589    rrlib::rtti::tType type;
590    input_stream >> type;
591    if (!type)
592    {
593      FINROC_LOG_PRINT(ERROR, "Data type not available. Canceling setting of annotation.");
594    }
595    else
596    {
597      core::tAnnotation* annotation = element->GetAnnotation(type.GetRttiName());
598      if (annotation == NULL)
599      {
600        FINROC_LOG_PRINT(ERROR, "Creating new annotations not supported yet. Canceling setting of annotation.");
601      }
602      else if (typeid(*annotation).name() != type.GetRttiName())
603      {
604        FINROC_LOG_PRINT(ERROR, "Existing annotation has wrong type?!. Canceling setting of annotation.");
605      }
606      else
607      {
608        rrlib::rtti::tTypedPointer annotation_pointer(annotation, type);
609        annotation_pointer.Deserialize(input_stream);
610
611        // In case a new config entry is set (from finstruct), load it immediately
612        if (type.GetRttiName() == typeid(parameters::internal::tParameterInfo).name())
613        {
614          parameters::internal::tParameterInfo* info = static_cast<parameters::internal::tParameterInfo*>(annotation);
615          if (info->GetConfigEntry().length())
616          {
617            info->LoadValue(true);
618          }
619        }
620      }
621    }
622  }
623}
624
625std::string tAdministrationService::SetPortValue(int port_handle, const rrlib::serialization::tMemoryBuffer& serialized_new_value)
626{
627  enum tDataEncoding
628  {
629    BINARY,
630    STRING,
631    XML,
632    STATIC_CAST,
633    DOUBLE_STATIC_CAST,
634    DIMENSION
635  };
636
637  core::tAbstractPort* port = Runtime().GetPort(port_handle);
638  std::string error_message;
639  if (port && port->IsReady())
640  {
641    if (port->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCT_READ_ONLY))
642    {
643      return "Port is read-only and cannot be set from finstruct";
644    }
645
646    rrlib::thread::tLock lock(port->GetStructureMutex()); // TODO: obtaining structure lock is quite heavy-weight - however, set calls should not occur often
647    if (port->IsReady())
648    {
649      try
650      {
651        rrlib::serialization::tInputStream input_stream(serialized_new_value, cBASIC_UID_SERIALIZATION_INFO);
652        uint8_t encoding = input_stream.ReadByte();
653        if (encoding >= DIMENSION)
654        {
655          throw std::runtime_error("Invalid encoding");
656        }
657        data_ports::tGenericPort wrapped_port = data_ports::tGenericPort::Wrap(*port);
658        data_ports::tPortDataPointer<rrlib::rtti::tGenericObject> buffer = wrapped_port.GetUnusedBuffer();
659        if (encoding <= XML)
660        {
661          buffer->Deserialize(input_stream, static_cast<rrlib::serialization::tDataEncoding>(encoding));
662        }
663        else
664        {
665          rrlib::serialization::tDataEncoding encoding2;
666          input_stream >> encoding2;
667          rrlib::rtti::tType type = rrlib::rtti::tType::GetType(input_stream.ReadShort());
668          rrlib::rtti::conversion::tCompiledConversionOperation operation;
669          if (encoding == STATIC_CAST)
670          {
671            operation = rrlib::rtti::conversion::tConversionOperationSequence(rrlib::rtti::conversion::tStaticCastOperation::GetInstance()).Compile(false, type, wrapped_port.GetDataType());
672          }
673          else
674          {
675            rrlib::rtti::tType inter_type = rrlib::rtti::tType::GetType(input_stream.ReadShort());
676            operation = rrlib::rtti::conversion::tConversionOperationSequence(rrlib::rtti::conversion::tStaticCastOperation::GetInstance(), rrlib::rtti::conversion::tStaticCastOperation::GetInstance(), inter_type).Compile(false, type, wrapped_port.GetDataType());
677          }
678          std::unique_ptr<rrlib::rtti::tGenericObject> object(type.CreateGenericObject());
679          object->Deserialize(input_stream, encoding2);
680          operation.Convert(*object, *buffer);
681        }
682        error_message = wrapped_port.BrowserPublish(buffer);
683        if (error_message.length() > 0)
684        {
685          FINROC_LOG_PRINT(WARNING, "Setting value of port '", port, "' failed: ", error_message);
686        }
687      }
688      catch (const std::exception& e)
689      {
690        FINROC_LOG_PRINT(WARNING, "Setting value of port '", port, "' failed: ", e);
691        error_message = e.what();
692      }
693      return error_message;
694    }
695  }
696  error_message = "Port with handle " + std::to_string(port_handle) + " is not available.";
697  FINROC_LOG_PRINT(WARNING, "Setting value of port failed: ", error_message);
698  return error_message;
699}
700
701void tAdministrationService::StartExecution(int element_handle)
702{
703  std::vector<scheduling::tExecutionControl*> controls;
704  GetExecutionControls(controls, element_handle);
705  if (controls.size() == 0)
706  {
707    FINROC_LOG_PRINT(WARNING, "Start/Pause command has not effect");
708  }
709  for (auto it = controls.begin(); it < controls.end(); it++)
710  {
711    if (!(*it)->IsRunning())
712    {
713      (*it)->Start();
714    }
715  }
716}
717
718
719//----------------------------------------------------------------------
720// End of namespace declaration
721//----------------------------------------------------------------------
722}
723}
Note: See TracBrowser for help on using the repository browser.