Executor.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore::core
19  * @author Nicola Miskowiec
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 
26 #include "Executor.h"
27 
28 #include <signal.h>
29 
30 #include <chrono>
31 #include <filesystem>
32 #include <thread>
33 
34 #include <sys/types.h>
35 
39 
40 using namespace ScenarioManager;
41 
43 {
44  setDefaultStopStrategy(strategy);
45  setDefaultStarter(starter);
46 }
47 
48 std::future<void>
50  bool printOnly,
51  const std::string& commandLineParameters)
52 {
53  if (application->getPid() != -1 || application->getStatusWriteBlock())
54  {
55  return std::future<void>();
56  }
57 
58  application->setStatusWriteBlock(true);
59  std::packaged_task<void()> task(std::bind(&ApplicationStarter::startApplication,
60  getStarter(application->getScenario()).get(),
61  application,
62  statusManager,
63  commandLineParameters,
64  printOnly)); // wrap the function
65 
66  std::future<void> result = task.get_future(); // get a future
67  std::thread t(std::move(task));
68  if (printOnly)
69  {
70  t.join(); //if only the commands should be printed then we want sync behaviour
71  }
72  else
73  {
74  t.detach();
75  }
76  return result;
77 }
78 
79 std::future<void>
81 {
82  if (application->getStatusWriteBlock())
83  {
84  return std::future<void>();
85  }
86 
87  application->setStatusWriteBlock(true);
88  std::packaged_task<void()> task(std::bind(&StopStrategy::stop,
89  getStopStrategy(application->getScenario()).get(),
90  application)); // wrap the function
91  std::future<void> result = task.get_future(); // get a future
92  std::thread(std::move(task)).detach(); // launch on a thread
93 
94  return result;
95 }
96 
97 void
98 Exec::Executor::asyncApplicationRestart(ApplicationInstancePtr application, bool printOnly)
99 {
100  Data_Structure::ScenarioPtr scenario = application->getScenario();
101  getStopStrategy(scenario)->stop(application);
102 
103  int waitCount = 0;
104  auto state = getStarter(scenario)->getStatus(application, statusManager);
107  {
108  std::this_thread::sleep_for(std::chrono::milliseconds(100));
109  waitCount++;
110  //Try to stop for 20 secs
111  if (waitCount == 200)
112  {
113  ARMARX_INFO_S << "The application " << application->getName()
114  << " is not Stopping please force kill it or try again. Aborting restart";
115  return;
116  }
117  state = getStarter(scenario)->getStatus(application, statusManager);
118  }
119 
120  ARMARX_INFO << "Starting application `" << application->getName() << "` which is `"
121  << application->getExecutableAbsPath() << "`";
122  getStarter(scenario)->startApplication(application, statusManager, "", printOnly);
123 }
124 
125 std::future<void>
127 {
128  if (application->getStatusWriteBlock())
129  {
130  return std::future<void>();
131  }
132 
133  application->setStatusWriteBlock(true);
134 
135  std::packaged_task<void()> task(std::bind(
136  &Executor::asyncApplicationRestart, this, application, printOnly)); // wrap the function
137 
138  std::future<void> result = task.get_future(); // get a future
139  std::thread(std::move(task)).detach(); // launch on a thread
140 
141  return result;
142 }
143 
144 std::string
146 {
147  if (application->getStatusWriteBlock())
148  {
149  return "Waiting";
150  }
151  return getStarter(application->getScenario())->getStatus(application, statusManager);
152 }
153 
154 std::future<void>
155 Exec::Executor::startScenario(std::shared_ptr<Data_Structure::Scenario> scenario,
156  bool printOnly,
157  const std::string& commandLineParameters)
158 {
159  if (scenario->getStatusWriteBlock())
160  {
161  return std::future<void>();
162  }
163 
164  scenario->setStatusWriteBlock(true);
165  std::packaged_task<void()> task(std::bind(&ApplicationStarter::startScenario,
166  getStarter(scenario).get(),
167  scenario,
168  statusManager,
169  commandLineParameters,
170  printOnly)); // wrap the function
171 
172  std::future<void> result = task.get_future(); // get a future
173  std::thread t(std::move(task)); // launch on a thread
174  if (printOnly)
175  {
176  t.join(); //if only the commands should be printed then we want sync behaviour
177  }
178  else
179  {
180  t.detach();
181  }
182  return result;
183 }
184 
185 void
186 Exec::Executor::asyncScenarioStop(Data_Structure::ScenarioPtr scenario)
187 {
188  std::vector<std::future<void>> futures;
189 
190  std::vector<ApplicationInstancePtr> apps = *scenario->getApplications();
191  for (auto it = apps.begin(); it != apps.end(); it++)
192  {
193  futures.push_back(stopApplication(*it));
194  }
195 
196  for (auto future = futures.begin(); future != futures.end(); ++future)
197  {
198  future->wait();
199  }
200 }
201 
202 std::future<void>
204 {
205  std::packaged_task<void()> task(
206  std::bind(&Executor::asyncScenarioStop, this, scenario)); // wrap the function
207  std::future<void> result = task.get_future(); // get a future
208  std::thread(std::move(task)).detach(); // launch on a thread
209 
210  return result;
211 }
212 
213 void
214 Exec::Executor::asyncScenarioRestart(Data_Structure::ScenarioPtr scenario, bool printOnly)
215 {
216  std::vector<std::future<void>> futures;
217  for (auto app : *scenario->getApplications())
218  {
219  futures.push_back(restartApplication(app, printOnly));
220  }
221 
222  for (auto future = futures.begin(); future != futures.end(); ++future)
223  {
224  future->wait();
225  }
226 }
227 
228 std::future<void>
230 {
231  std::packaged_task<void()> task(
232  std::bind(&Executor::asyncScenarioRestart, this, scenario, printOnly)); // wrap the function
233  std::future<void> result = task.get_future(); // get a future
234  std::thread(std::move(task)).detach(); // launch on a thread
235 
236  return result;
237 }
238 
239 void
241  std::string path,
242  bool reload,
243  bool set)
244 {
245  std::filesystem::path xmlFilePath =
246  std::filesystem::path(path) / std::filesystem::path(application->getPackageName() + "." +
247  application->getName() + ".xml");
248 
249  if (reload || !std::filesystem::exists(xmlFilePath))
250  {
251  std::filesystem::create_directories(path);
252 
253  std::string strCommand = application->getExecutableAbsPath()
254  .append(" -p -f xml -o ")
255  .append(xmlFilePath.string());
256  int ret = system(strCommand.c_str());
257  if (ret != 0)
258  {
259  ARMARX_WARNING << "Failed to generate properties xml for " << application->getName()
260  << "\nCommand was: " << strCommand;
261  }
262  }
263  else
264  {
265  application->updateFound();
266  if (!application->getFound())
267  {
268  return;
269  }
270  //if executable more recent that xml reload xml
271  auto xmlDate = (std::filesystem::last_write_time(xmlFilePath));
272 
273  auto execDate =
274  std::filesystem::last_write_time(application->getPathToExecutable().append("/").append(
275  application->getExecutableName()));
276 
277  if (execDate > xmlDate)
278  {
279  loadAndSetCachedProperties(application, path, true, set);
280  return;
281  }
282  }
283 
284  if (set)
285  {
287  application->setProperties(parser.loadFromXml(xmlFilePath.string()));
288  }
289 }
290 
291 void
293 {
294  defaultStopStrategy = strategy;
295 }
296 
297 void
299 {
300  defaultStartStrategy = appStarter;
301 }
302 
303 void
305 {
306  this->stopStrategy[scenario] = strategy;
307 }
308 
309 void
311 {
312  this->starter[scenario] = appStarter;
313 }
314 
317 {
318  if (starter.count(scenario) == 0)
319  {
320  return defaultStartStrategy;
321  }
322  return starter[scenario];
323 }
324 
327 {
328  if (stopStrategy.count(scenario) == 0)
329  {
330  return defaultStopStrategy;
331  }
332  return stopStrategy[scenario];
333 }
334 
337 {
338  return defaultStopStrategy;
339 }
ScenarioManager::Exec::Executor::setStopStrategy
void setStopStrategy(StopStrategyPtr strategy, Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:304
ScenarioManager::Exec::Executor::setDefaultStopStrategy
void setDefaultStopStrategy(StopStrategyPtr strategy)
Sets the strategy this Executor uses to stop applications.
Definition: Executor.cpp:292
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:13
ScenarioManager::Data_Structure::ScenarioPtr
std::shared_ptr< Scenario > ScenarioPtr
Definition: Scenario.h:35
iceparser.h
ScenarioManager::Exec::Executor::getStarter
ApplicationStarterPtr getStarter(Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:316
ScenarioManager::Exec::Executor::restartApplication
std::future< void > restartApplication(Data_Structure::ApplicationInstancePtr application, bool printOnly=false)
Restarts an application.
Definition: Executor.cpp:126
ScenarioManager::Data_Structure::ApplicationPtr
std::shared_ptr< Application > ApplicationPtr
Definition: Application.h:121
ScenarioManager::Parser::IceParser
Definition: iceparser.h:39
ScenarioManager::Exec::Executor::stopApplication
std::future< void > stopApplication(Data_Structure::ApplicationInstancePtr application)
Stops an application.
Definition: Executor.cpp:80
ScenarioManager::Exec::StopStrategy::stop
virtual void stop(Data_Structure::ApplicationInstancePtr application)=0
Stops an application.
ScenarioManager::Exec::StopStrategyPtr
std::shared_ptr< StopStrategy > StopStrategyPtr
Definition: Executor.h:46
ScenarioManager::Data_Structure::ApplicationStatus::Stopped
static const std::string Stopped
Definition: ApplicationInstance.h:47
ScenarioManager::Exec::Executor::startApplication
std::future< void > startApplication(Data_Structure::ApplicationInstancePtr application, bool printOnly=false, const std::string &commandLineParameters="")
Starts an application.
Definition: Executor.cpp:49
ScenarioManager::Exec::Executor::getApplicationStatus
std::string getApplicationStatus(Data_Structure::ApplicationInstancePtr application)
Returns the status of an application.
Definition: Executor.cpp:145
ApplicationInstancePtr
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition: StopStrategy.h:8
ScenarioManager::Exec::Executor::stopScenario
std::future< void > stopScenario(Data_Structure::ScenarioPtr scenario)
Stops a scenario.
Definition: Executor.cpp:203
ScenarioManager::Exec::Executor::getStopStrategy
StopStrategyPtr getStopStrategy(Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:326
Executor.h
ScenarioManager::Exec::Executor::setDefaultStarter
void setDefaultStarter(ApplicationStarterPtr appStarter)
Sets the appStarter this Executor uses to start applications and request statuses.
Definition: Executor.cpp:298
ScenarioManager::Data_Structure::ApplicationStatus::Inactive
static const std::string Inactive
Definition: ApplicationInstance.h:52
ScenarioManager::Exec::ApplicationStarterPtr
std::shared_ptr< ApplicationStarter > ApplicationStarterPtr
Definition: ApplicationStarter.h:72
ScenarioManager::Exec::ApplicationStarter::startScenario
virtual void startScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false)=0
IceStorm::parser
Parser * parser
Definition: Parser.cpp:34
ScenarioManager
Definition: Application.cpp:180
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
set
set(LIBS ArmarXCoreInterfaces ${CMAKE_THREAD_LIBS_INIT} ${dl_LIBRARIES} ${rt_LIBRARIES} ${QT_LIBRARIES} ${Boost_LIBRARIES} BoostAssertionHandler ArmarXCPPUtility SimoxUtility) set(LIB_FILES ArmarXManager.cpp ArmarXMultipleObjectsScheduler.cpp ArmarXObjectScheduler.cpp ManagedIceObject.cpp ManagedIceObjectPlugin.cpp Component.cpp ComponentPlugin.cpp IceGridAdmin.cpp ArmarXObjectObserver.cpp IceManager.cpp PackagePath.cpp RemoteReferenceCount.cpp logging/LoggingUtil.cpp logging/Logging.cpp logging/LogSender.cpp logging/ArmarXLogBuf.cpp system/ArmarXDataPath.cpp system/DynamicLibrary.cpp system/ProcessWatcher.cpp system/FactoryCollectionBase.cpp system/cmake/CMakePackageFinder.cpp system/cmake/CMakePackageFinderCache.cpp system/cmake/ArmarXPackageToolInterface.cpp system/RemoteObjectNode.cpp services/sharedmemory/HardwareId.cpp services/tasks/RunningTask.cpp services/tasks/ThreadList.cpp services/tasks/ThreadPool.cpp services/profiler/Profiler.cpp services/profiler/FileLoggingStrategy.cpp services/profiler/IceLoggingStrategy.cpp application/Application.cpp application/ApplicationOptions.cpp application/ApplicationProcessFacet.cpp application/ApplicationNetworkStats.cpp application/properties/PropertyUser.cpp application/properties/Property.cpp application/properties/PropertyDefinition.cpp application/properties/PropertyDefinitionContainer.cpp application/properties/PropertyDefinitionHelpFormatter.cpp application/properties/PropertyDefinitionConfigFormatter.cpp application/properties/PropertyDefinitionBriefHelpFormatter.cpp application/properties/PropertyDefinitionXmlFormatter.cpp application/properties/PropertyDefinitionDoxygenFormatter.cpp application/properties/PropertyDefinitionDoxygenComponentPagesFormatter.cpp application/properties/PropertyDefinitionContainerBriefHelpFormatter.cpp application/properties/IceProperties.cpp exceptions/Exception.cpp exceptions/local/UnexpectedEnumValueException.cpp util/FileSystemPathBuilder.cpp util/StringHelpers.cpp util/IceReportSkipper.cpp util/Throttler.cpp util/distributed/AMDCallbackCollection.cpp util/distributed/RemoteHandle/ClientSideRemoteHandleControlBlock.cpp util/distributed/RemoteHandle/RemoteHandle.cpp util/distributed/RemoteHandle/RemoteHandleControlBlock.cpp time/ice_conversions.cpp time/json_conversions.cpp time/CallbackWaitLock.cpp time/Clock.cpp time/ClockType.cpp time/ClockTypeNames.cpp time/CycleUtil.cpp time/DateTime.cpp time/Duration.cpp time/Frequency.cpp time/LocalTimeServer.cpp time/Metronome.cpp time/ScopedStopWatch.cpp time/StopWatch.cpp time/Timer.cpp time/TimeKeeper.cpp time/TimeUtil.cpp csv/CsvWriter.cpp csv/CsvReader.cpp eigen/conversions.cpp eigen/ice_conversions.cpp) set(LIB_HEADERS ArmarXManager.h ArmarXDummyManager.h ArmarXMultipleObjectsScheduler.h ArmarXObjectObserver.h ArmarXObjectScheduler.h ArmarXFwd.h Component.h ComponentPlugin.h ComponentFactories.h CoreObjectFactories.h IceGridAdmin.h IceManager.h IceManagerImpl.h json_conversions.h ManagedIceObject.h ManagedIceObjectPlugin.h ManagedIceObjectImpl.h ManagedIceObjectDependency.h ManagedIceObjectRegistryInterface.h PackagePath.h RemoteReferenceCount.h system/ImportExport.h system/ImportExportComponent.h system/AbstractFactoryMethod.h system/FactoryCollectionBase.h system/Synchronization.h system/ArmarXDataPath.h system/DynamicLibrary.h system/ProcessWatcher.h system/ConditionSynchronization.h system/cmake/CMakePackageFinder.h system/cmake/CMakePackageFinderCache.h system/cmake/FindPackageX.cmake system/cmake/ArmarXPackageToolInterface.h system/RemoteObjectNode.h logging/LoggingUtil.h logging/LogSender.h logging/Logging.h logging/ArmarXLogBuf.h logging/SpamFilterData.h services/tasks/RunningTask.h services/tasks/PeriodicTask.h services/tasks/ThreadList.h services/tasks/TaskUtil.h services/tasks/ThreadPool.h services/sharedmemory/SharedMemoryProvider.h services/sharedmemory/SharedMemoryConsumer.h services/sharedmemory/IceSharedMemoryProvider.h services/sharedmemory/IceSharedMemoryConsumer.h services/sharedmemory/HardwareIdentifierProvider.h services/sharedmemory/HardwareId.h services/sharedmemory/exceptions/SharedMemoryExceptions.h services/profiler/Profiler.h services/profiler/LoggingStrategy.h services/profiler/FileLoggingStrategy.h services/profiler/IceLoggingStrategy.h application/Application.h application/ApplicationOptions.h application/ApplicationProcessFacet.h application/ApplicationNetworkStats.h application/properties/forward_declarations.h application/properties/Properties.h application/properties/Property.h application/properties/PluginEigen.h application/properties/PluginEnumNames.h application/properties/PluginCfgStruct.h application/properties/PluginAll.h application/properties/PropertyUser.h application/properties/PropertyDefinition.h application/properties/PropertyDefinition.hpp application/properties/PropertyDefinitionInterface.h application/properties/PropertyDefinitionContainer.h application/properties/PropertyDefinitionFormatter.h application/properties/PropertyDefinitionContainerFormatter.h application/properties/PropertyDefinitionConfigFormatter.h application/properties/PropertyDefinitionHelpFormatter.h application/properties/PropertyDefinitionBriefHelpFormatter.h application/properties/PropertyDefinitionXmlFormatter.h application/properties/PropertyDefinitionDoxygenFormatter.h application/properties/PropertyDefinitionDoxygenComponentPagesFormatter.h application/properties/PropertyDefinitionContainerBriefHelpFormatter.h application/properties/ProxyPropertyDefinition.h application/properties/IceProperties.h exceptions/Exception.h exceptions/LocalException.h exceptions/local/DynamicLibraryException.h exceptions/local/ExpressionException.h exceptions/local/FileIOException.h exceptions/local/InvalidPropertyValueException.h exceptions/local/MissingRequiredPropertyException.h exceptions/local/PropertyInheritanceCycleException.h exceptions/local/ProxyNotInitializedException.h exceptions/local/UnexpectedEnumValueException.h exceptions/local/UnmappedValueException.h exceptions/local/ValueRangeExceededException.h exceptions/user/NotImplementedYetException.h rapidxml/rapidxml.hpp rapidxml/rapidxml_print.hpp rapidxml/rapidxml_iterators.hpp rapidxml/rapidxml_utils.hpp rapidxml/wrapper/RapidXmlReader.h rapidxml/wrapper/RapidXmlWriter.h rapidxml/wrapper/DefaultRapidXmlReader.h rapidxml/wrapper/MultiNodeRapidXMLReader.h util/IceBlobToObject.h util/ObjectToIceBlob.h util/FileSystemPathBuilder.h util/FiniteStateMachine.h util/StringHelpers.h util/StringHelperTemplates.h util/algorithm.h util/OnScopeExit.h util/Predicates.h util/Preprocessor.h util/PropagateConst.h util/Registrar.h util/TemplateMetaProgramming.h util/TripleBuffer.h util/IceReportSkipper.h util/Throttler.h util/distributed/AMDCallbackCollection.h util/distributed/RemoteHandle/ClientSideRemoteHandleControlBlock.h util/distributed/RemoteHandle/RemoteHandle.h util/distributed/RemoteHandle/RemoteHandleControlBlock.h util/SimpleStatemachine.h time.h time_minimal.h time/forward_declarations.h time/ice_conversions.h time/json_conversions.h time/CallbackWaitLock.h time/Clock.h time/ClockType.h time/ClockTypeNames.h time/CycleUtil.h time/DateTime.h time/Duration.h time/Frequency.h time/LocalTimeServer.h time/Metronome.h time/ScopedStopWatch.h time/StopWatch.h time/Timer.h time/TimeUtil.h time/TimeKeeper.h csv/CsvWriter.h csv/CsvReader.h eigen/conversions.h eigen/ice_conversions.h ice_conversions.h ice_conversions/ice_conversions_boost_templates.h ice_conversions/ice_conversions_templates.h ice_conversions/ice_conversions_templates.tpp $
Definition: CMakeLists.txt:12
ScenarioManager::Exec::Executor::setStarter
void setStarter(ApplicationStarterPtr appStarter, Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:310
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
Logging.h
ScenarioManager::Exec::Executor::Executor
Executor(StopStrategyPtr strategy, ApplicationStarterPtr starter)
Constructor that sets StopStrategy and ApplicationStarter.
Definition: Executor.cpp:42
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
ScenarioManager::Exec::Executor::getDefaultStopStrategy
StopStrategyPtr getDefaultStopStrategy()
Definition: Executor.cpp:336
ScenarioManager::Exec::Executor::restartScenario
std::future< void > restartScenario(Data_Structure::ScenarioPtr scenario, bool printOnly=false)
Restarts a scenario.
Definition: Executor.cpp:229
ScenarioManager::Exec::Executor::loadAndSetCachedProperties
void loadAndSetCachedProperties(Data_Structure::ApplicationPtr application, std::string path, bool reload=false, bool set=true)
Generates an XML file of the given application and saves it in the specified path.
Definition: Executor.cpp:240
Exception.h
ScenarioManager::Exec::Executor::startScenario
std::future< void > startScenario(Data_Structure::ScenarioPtr scenario, bool printOnly=false, const std::string &commandLineParameters="")
Starts a scenario.
Definition: Executor.cpp:155
ScenarioManager::Exec::ApplicationStarter::startApplication
virtual void startApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false)=0
Starts an application.