source: finroc_plugins_runtime_construction/tAdministrationService.cpp @ 90:88b6f38d610a

17.03
Last change on this file since 90:88b6f38d610a was 90:88b6f38d610a, checked in by Max Reichardt <mreichardt@…>, 7 years ago

Adds support for type conversion and other connector options in finstructable groups and administration service. CreateFrameworkElementAction register is now based on register mechanism from rrlib_serialization.

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, const rrlib::uri::tURI& uri)
305{
306  core::tAbstractPort* port = core::tRuntimeEnvironment::GetInstance().GetPort(local_port_handle);
307  std::stringstream result;
308  if (port && port->IsReady())
309  {
310    for (auto & connector : port->UriConnectors())
311    {
312      if (connector->Uri() == uri)
313      {
314        connector->Disconnect();
315        return true;
316      }
317    }
318    result << "No connector with URI " << uri.ToString() << " found";
319  }
320  else
321  {
322    result << "No port with local handle " << local_port_handle << " found";
323  }
324  FINROC_LOG_PRINT(WARNING, result.str());
325  return false;
326}
327
328void tAdministrationService::Disconnect(int source_port_handle, int destination_port_handle)
329{
330  auto cVOLATILE = core::tFrameworkElement::tFlag::VOLATILE;
331  core::tAbstractPort* source_port = Runtime().GetPort(source_port_handle);
332  core::tAbstractPort* destination_port = Runtime().GetPort(destination_port_handle);
333  if ((!source_port) || (!destination_port))
334  {
335    FINROC_LOG_PRINT(WARNING, "At least one port to be disconnected does not exist");
336    return;
337  }
338  if (source_port->GetFlag(cVOLATILE))
339  {
340    destination_port->DisconnectFrom(source_port->GetPath());
341  }
342  if (destination_port->GetFlag(cVOLATILE))
343  {
344    source_port->DisconnectFrom(destination_port->GetPath());
345  }
346  source_port->DisconnectFrom(*destination_port);
347  if (source_port->IsConnectedTo(*destination_port))
348  {
349    FINROC_LOG_PRINT(WARNING, "Could not disconnect ports ", source_port, " ", destination_port);
350  }
351  else
352  {
353    FINROC_LOG_PRINT(USER, "Disconnected ports ", source_port, " ", destination_port);
354  }
355}
356
357void tAdministrationService::DisconnectAll(int port_handle)
358{
359  core::tAbstractPort* port = Runtime().GetPort(port_handle);
360  if (!port)
361  {
362    FINROC_LOG_PRINT(WARNING, "Port to be disconnected does not exist");
363    return;
364  }
365  port->DisconnectAll();
366  FINROC_LOG_PRINT(USER, "Disconnected port ", port);
367}
368
369rrlib::serialization::tMemoryBuffer tAdministrationService::GetAnnotation(int element_handle, const std::string& annotation_type_name)
370{
371  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
372  rrlib::rtti::tType type = rrlib::rtti::tType::FindType(annotation_type_name);
373  if (element && element->IsReady() && type)
374  {
375    core::tAnnotation* result = element->GetAnnotation(type.GetRttiName());
376    if (result)
377    {
378      rrlib::serialization::tMemoryBuffer result_buffer;
379      rrlib::serialization::tOutputStream output_stream(result_buffer, cBASIC_UID_SERIALIZATION_INFO);
380      rrlib::rtti::tTypedConstPointer annotation_pointer(result, type);
381      annotation_pointer.Serialize(output_stream);
382      output_stream.Close();
383      return result_buffer;
384    }
385  }
386  else
387  {
388    FINROC_LOG_PRINT(ERROR, "Could not query element for annotation type ", annotation_type_name);
389  }
390  return rrlib::serialization::tMemoryBuffer(0);
391}
392
393rrlib::serialization::tMemoryBuffer tAdministrationService::GetCreateModuleActions()
394{
395  FINROC_LOG_PRINT(WARNING, "GetCreateModuleActions() is superseded");
396  return rrlib::serialization::tMemoryBuffer();
397}
398
399rrlib::serialization::tMemoryBuffer tAdministrationService::GetModuleLibraries()
400{
401  rrlib::serialization::tMemoryBuffer result_buffer;
402  rrlib::serialization::tOutputStream output_stream(result_buffer);
403  std::vector<tSharedLibrary> libs = GetLoadableFinrocLibraries();
404  for (size_t i = 0; i < libs.size(); i++)
405  {
406    output_stream.WriteString(libs[i].ToString());
407  }
408  output_stream.Close();
409  return result_buffer;
410}
411
412rrlib::serialization::tMemoryBuffer tAdministrationService::GetParameterInfo(int root_element_handle)
413{
414  core::tFrameworkElement* root = Runtime().GetElement(root_element_handle);
415  if ((!root) || (!root->IsReady()))
416  {
417    FINROC_LOG_PRINT(ERROR, "Could not get parameter info for framework element ", root_element_handle);
418    return rrlib::serialization::tMemoryBuffer(0);
419  }
420
421  parameters::tConfigFile* config_file = parameters::tConfigFile::Find(*root);
422  rrlib::serialization::tMemoryBuffer result_buffer;
423  rrlib::serialization::tOutputStream output_stream(result_buffer, cBASIC_UID_SERIALIZATION_INFO);
424  if (!config_file)
425  {
426    output_stream.WriteBoolean(false);
427  }
428  else
429  {
430    output_stream.WriteBoolean(true);
431    output_stream.WriteInt(config_file->GetAnnotated<core::tFrameworkElement>()->GetHandle());
432    output_stream << *config_file;
433    for (auto it = root->SubElementsBegin(true); it != root->SubElementsEnd(); ++it)
434    {
435      parameters::tConfigFile* element_config = it->GetAnnotation<parameters::tConfigFile>();
436      if (element_config)
437      {
438        output_stream.WriteByte(1);
439        output_stream.WriteInt(it->GetHandle());
440        output_stream.WriteString(element_config->GetFilename());
441        output_stream.WriteBoolean(element_config->IsActive());
442      }
443      else
444      {
445        parameters::internal::tParameterInfo* parameter_info = it->GetAnnotation<parameters::internal::tParameterInfo>();
446        if (parameter_info && config_file == parameters::tConfigFile::Find(*it))
447        {
448          output_stream.WriteByte(2);
449          output_stream.WriteInt(it->GetHandle());
450          output_stream.WriteString(parameter_info->GetConfigEntry());
451        }
452      }
453    }
454  }
455  output_stream.Close();
456  return result_buffer;
457}
458
459tAdministrationService::tExecutionStatus tAdministrationService::IsExecuting(int element_handle)
460{
461  std::vector<scheduling::tExecutionControl*> controls;
462  GetExecutionControls(controls, element_handle);
463
464  bool stopped = false;
465  bool running = false;
466  for (auto it = controls.begin(); it < controls.end(); it++)
467  {
468    stopped |= (!(*it)->IsRunning());
469    running |= (*it)->IsRunning();
470  }
471  if (running && stopped)
472  {
473    return tExecutionStatus::BOTH;
474  }
475  else if (running)
476  {
477    return tExecutionStatus::RUNNING;
478  }
479  else if (stopped)
480  {
481    return tExecutionStatus::PAUSED;
482  }
483  return tExecutionStatus::NONE;
484}
485
486rrlib::serialization::tMemoryBuffer tAdministrationService::LoadModuleLibrary(const std::string& library_name)
487{
488  FINROC_LOG_PRINT(USER, "Loading library ", library_name);
489  try
490  {
491    DLOpen(library_name);
492  }
493  catch (const std::exception& exception)
494  {
495    FINROC_LOG_PRINT(ERROR, exception);
496  }
497  return GetCreateModuleActions();
498}
499
500std::string tAdministrationService::NetworkConnect(int local_port_handle, const std::string& preferred_transport,
501    const std::string& remote_runtime_uuid, int remote_port_handle, const std::string& remote_port_link, bool disconnect)
502{
503  const char* message = "tAdministrationService::NetworkConnect() is superseded. Please use a newer version of your tool that uses CreateUriConnector().";
504  FINROC_LOG_PRINT(WARNING, message);
505  return message;
506}
507
508void tAdministrationService::PauseExecution(int element_handle)
509{
510  std::vector<scheduling::tExecutionControl*> controls;
511  GetExecutionControls(controls, element_handle);
512  if (controls.size() == 0)
513  {
514    FINROC_LOG_PRINT(WARNING, "Start/Pause command has not effect");
515  }
516  for (auto it = controls.begin(); it < controls.end(); it++)
517  {
518    if ((*it)->IsRunning())
519    {
520      (*it)->Pause();
521    }
522  }
523}
524
525void tAdministrationService::SaveAllFinstructableFiles()
526{
527  FINROC_LOG_PRINT(USER, "Saving all finstructable files in this process:");
528  core::tRuntimeEnvironment& runtime_environment = core::tRuntimeEnvironment::GetInstance();
529  for (auto it = runtime_environment.SubElementsBegin(); it != runtime_environment.SubElementsEnd(); ++it)
530  {
531    if (it->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCTABLE_GROUP))
532    {
533      try
534      {
535        if (it->GetAnnotation<tFinstructable>())
536        {
537          it->GetAnnotation<tFinstructable>()->SaveXml();
538        }
539        else
540        {
541          FINROC_LOG_PRINT(ERROR, "Element invalidly flagged as finstructable: ", *it);
542        }
543      }
544      catch (const std::exception& e)
545      {
546        FINROC_LOG_PRINT(ERROR, "Error saving finstructable group ", *it);
547        FINROC_LOG_PRINT(ERROR, e);
548      }
549    }
550  }
551  FINROC_LOG_PRINT(USER, "Done.");
552}
553
554void tAdministrationService::SaveFinstructableGroup(int group_handle)
555{
556  core::tFrameworkElement* group = Runtime().GetElement(group_handle);
557  if (group && group->IsReady() && group->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCTABLE_GROUP))
558  {
559    try
560    {
561      if (group->GetAnnotation<tFinstructable>())
562      {
563        group->GetAnnotation<tFinstructable>()->SaveXml();
564      }
565      else
566      {
567        FINROC_LOG_PRINT(ERROR, "Element invalidly flagged as finstructable: ", *group);
568      }
569    }
570    catch (const std::exception& e)
571    {
572      FINROC_LOG_PRINT(ERROR, "Error saving finstructable group ", *group);
573      FINROC_LOG_PRINT(ERROR, e);
574    }
575  }
576  else
577  {
578    FINROC_LOG_PRINT(ERROR, "Could not save finstructable group, because it does not appear to be available.");
579  }
580}
581
582void tAdministrationService::SetAnnotation(int element_handle, const rrlib::serialization::tMemoryBuffer& serialized_annotation)
583{
584  core::tFrameworkElement* element = Runtime().GetElement(element_handle);
585  if (element == NULL || (!element->IsReady()))
586  {
587    FINROC_LOG_PRINT(ERROR, "Parent not available. Canceling setting of annotation.");
588  }
589  else
590  {
591    rrlib::serialization::tInputStream input_stream(serialized_annotation, cBASIC_UID_SERIALIZATION_INFO);
592    rrlib::rtti::tType type;
593    input_stream >> type;
594    if (!type)
595    {
596      FINROC_LOG_PRINT(ERROR, "Data type not available. Canceling setting of annotation.");
597    }
598    else
599    {
600      core::tAnnotation* annotation = element->GetAnnotation(type.GetRttiName());
601      if (annotation == NULL)
602      {
603        FINROC_LOG_PRINT(ERROR, "Creating new annotations not supported yet. Canceling setting of annotation.");
604      }
605      else if (typeid(*annotation).name() != type.GetRttiName())
606      {
607        FINROC_LOG_PRINT(ERROR, "Existing annotation has wrong type?!. Canceling setting of annotation.");
608      }
609      else
610      {
611        rrlib::rtti::tTypedPointer annotation_pointer(annotation, type);
612        annotation_pointer.Deserialize(input_stream);
613
614        // In case a new config entry is set (from finstruct), load it immediately
615        if (type.GetRttiName() == typeid(parameters::internal::tParameterInfo).name())
616        {
617          parameters::internal::tParameterInfo* info = static_cast<parameters::internal::tParameterInfo*>(annotation);
618          if (info->GetConfigEntry().length())
619          {
620            info->LoadValue(true);
621          }
622        }
623      }
624    }
625  }
626}
627
628std::string tAdministrationService::SetPortValue(int port_handle, const rrlib::serialization::tMemoryBuffer& serialized_new_value)
629{
630  enum tDataEncoding
631  {
632    BINARY,
633    STRING,
634    XML,
635    STATIC_CAST,
636    DOUBLE_STATIC_CAST,
637    DIMENSION
638  };
639
640  core::tAbstractPort* port = Runtime().GetPort(port_handle);
641  std::string error_message;
642  if (port && port->IsReady())
643  {
644    if (port->GetFlag(core::tFrameworkElement::tFlag::FINSTRUCT_READ_ONLY))
645    {
646      return "Port is read-only and cannot be set from finstruct";
647    }
648
649    rrlib::thread::tLock lock(port->GetStructureMutex()); // TODO: obtaining structure lock is quite heavy-weight - however, set calls should not occur often
650    if (port->IsReady())
651    {
652      try
653      {
654        rrlib::serialization::tInputStream input_stream(serialized_new_value, cBASIC_UID_SERIALIZATION_INFO);
655        uint8_t encoding = input_stream.ReadByte();
656        if (encoding >= DIMENSION)
657        {
658          throw std::runtime_error("Invalid encoding");
659        }
660        data_ports::tGenericPort wrapped_port = data_ports::tGenericPort::Wrap(*port);
661        data_ports::tPortDataPointer<rrlib::rtti::tGenericObject> buffer = wrapped_port.GetUnusedBuffer();
662        if (encoding <= XML)
663        {
664          buffer->Deserialize(input_stream, static_cast<rrlib::serialization::tDataEncoding>(encoding));
665        }
666        else
667        {
668          rrlib::serialization::tDataEncoding encoding2;
669          input_stream >> encoding2;
670          rrlib::rtti::tType type = rrlib::rtti::tType::GetType(input_stream.ReadShort());
671          rrlib::rtti::conversion::tCompiledConversionOperation operation;
672          if (encoding == STATIC_CAST)
673          {
674            operation = rrlib::rtti::conversion::tConversionOperationSequence(rrlib::rtti::conversion::tStaticCastOperation::GetInstance()).Compile(false, type, wrapped_port.GetDataType());
675          }
676          else
677          {
678            rrlib::rtti::tType inter_type = rrlib::rtti::tType::GetType(input_stream.ReadShort());
679            operation = rrlib::rtti::conversion::tConversionOperationSequence(rrlib::rtti::conversion::tStaticCastOperation::GetInstance(), rrlib::rtti::conversion::tStaticCastOperation::GetInstance(), inter_type).Compile(false, type, wrapped_port.GetDataType());
680          }
681          std::unique_ptr<rrlib::rtti::tGenericObject> object(type.CreateGenericObject());
682          object->Deserialize(input_stream, encoding2);
683          operation.Convert(*object, *buffer);
684        }
685        error_message = wrapped_port.BrowserPublish(buffer);
686        if (error_message.length() > 0)
687        {
688          FINROC_LOG_PRINT(WARNING, "Setting value of port '", port, "' failed: ", error_message);
689        }
690      }
691      catch (const std::exception& e)
692      {
693        FINROC_LOG_PRINT(WARNING, "Setting value of port '", port, "' failed: ", e);
694        error_message = e.what();
695      }
696      return error_message;
697    }
698  }
699  error_message = "Port with handle " + std::to_string(port_handle) + " is not available.";
700  FINROC_LOG_PRINT(WARNING, "Setting value of port failed: ", error_message);
701  return error_message;
702}
703
704void tAdministrationService::StartExecution(int element_handle)
705{
706  std::vector<scheduling::tExecutionControl*> controls;
707  GetExecutionControls(controls, element_handle);
708  if (controls.size() == 0)
709  {
710    FINROC_LOG_PRINT(WARNING, "Start/Pause command has not effect");
711  }
712  for (auto it = controls.begin(); it < controls.end(); it++)
713  {
714    if (!(*it)->IsRunning())
715    {
716      (*it)->Start();
717    }
718  }
719}
720
721
722//----------------------------------------------------------------------
723// End of namespace declaration
724//----------------------------------------------------------------------
725}
726}
Note: See TracBrowser for help on using the repository browser.