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"
30 
31 #include <filesystem>
32 #include <sys/types.h>
33 #include <signal.h>
34 #include <chrono>
35 #include <thread>
36 
37 using namespace ScenarioManager;
38 
40 {
41  setDefaultStopStrategy(strategy);
42  setDefaultStarter(starter);
43 }
44 
45 std::future<void> Exec::Executor::startApplication(ApplicationInstancePtr application, bool printOnly, const std::string& commandLineParameters)
46 {
47  if (application->getPid() != -1 || application->getStatusWriteBlock())
48  {
49  return std::future<void>();
50  }
51 
52  application->setStatusWriteBlock(true);
53  std::packaged_task<void()> task(std::bind(&ApplicationStarter::startApplication, getStarter(application->getScenario()).get(), application, statusManager, commandLineParameters, printOnly)); // wrap the function
54 
55  std::future<void> result = task.get_future(); // get a future
56  std::thread t(std::move(task));
57  if (printOnly)
58  {
59  t.join(); //if only the commands should be printed then we want sync behaviour
60  }
61  else
62  {
63  t.detach();
64  }
65  return result;
66 }
67 
69 {
70  if (application->getStatusWriteBlock())
71  {
72  return std::future<void>();
73  }
74 
75  application->setStatusWriteBlock(true);
76  std::packaged_task<void()> task(std::bind(&StopStrategy::stop, getStopStrategy(application->getScenario()).get(), application)); // wrap the function
77  std::future<void> result = task.get_future(); // get a future
78  std::thread(std::move(task)).detach(); // launch on a thread
79 
80  return result;
81 }
82 
83 void Exec::Executor::asyncApplicationRestart(ApplicationInstancePtr application, bool printOnly)
84 {
85  Data_Structure::ScenarioPtr scenario = application->getScenario();
86  getStopStrategy(scenario)->stop(application);
87 
88  int waitCount = 0;
89  auto state = getStarter(scenario)->getStatus(application, statusManager);
92  {
93  std::this_thread::sleep_for(std::chrono::milliseconds(100));
94  waitCount ++;
95  //Try to stop for 20 secs
96  if (waitCount == 200)
97  {
98  ARMARX_INFO_S << "The application " << application->getName() << " is not Stopping please force kill it or try again. Aborting restart";
99  return;
100  }
101  state = getStarter(scenario)->getStatus(application, statusManager);
102  }
103 
104  ARMARX_INFO << "Starting application `" << application->getName() << "` which is `" << application->getExecutableAbsPath() << "`";
105  getStarter(scenario)->startApplication(application, statusManager, "", printOnly);
106 }
107 
108 std::future<void> Exec::Executor::restartApplication(ApplicationInstancePtr application, bool printOnly)
109 {
110  if (application->getStatusWriteBlock())
111  {
112  return std::future<void>();
113  }
114 
115  application->setStatusWriteBlock(true);
116 
117  std::packaged_task<void()> task(std::bind(&Executor::asyncApplicationRestart, this, application, printOnly)); // wrap the function
118 
119  std::future<void> result = task.get_future(); // get a future
120  std::thread(std::move(task)).detach(); // launch on a thread
121 
122  return result;
123 }
124 
126 {
127  if (application->getStatusWriteBlock())
128  {
129  return "Waiting";
130  }
131  return getStarter(application->getScenario())->getStatus(application, statusManager);
132 }
133 
134 std::future<void> Exec::Executor::startScenario(std::shared_ptr<Data_Structure::Scenario> scenario, bool printOnly, const std::string& commandLineParameters)
135 {
136  if (scenario->getStatusWriteBlock())
137  {
138  return std::future<void>();
139  }
140 
141  scenario->setStatusWriteBlock(true);
142  std::packaged_task<void()> task(std::bind(&ApplicationStarter::startScenario, getStarter(scenario).get(), scenario, statusManager, commandLineParameters, printOnly)); // wrap the function
143 
144  std::future<void> result = task.get_future(); // get a future
145  std::thread t(std::move(task)); // launch on a thread
146  if (printOnly)
147  {
148  t.join(); //if only the commands should be printed then we want sync behaviour
149  }
150  else
151  {
152  t.detach();
153  }
154  return result;
155 }
156 
157 void Exec::Executor::asyncScenarioStop(Data_Structure::ScenarioPtr scenario)
158 {
159  std::vector<std::future<void>> futures;
160 
161  std::vector<ApplicationInstancePtr> apps = *scenario->getApplications();
162  for (auto it = apps.begin(); it != apps.end(); it++)
163  {
164  futures.push_back(stopApplication(*it));
165  }
166 
167  for (auto future = futures.begin(); future != futures.end(); ++future)
168  {
169  future->wait();
170  }
171 }
172 
174 {
175  std::packaged_task<void()> task(std::bind(&Executor::asyncScenarioStop, this, scenario)); // wrap the function
176  std::future<void> result = task.get_future(); // get a future
177  std::thread(std::move(task)).detach(); // launch on a thread
178 
179  return result;
180 }
181 
182 void Exec::Executor::asyncScenarioRestart(Data_Structure::ScenarioPtr scenario, bool printOnly)
183 {
184  std::vector<std::future<void>> futures;
185  for (auto app : *scenario->getApplications())
186  {
187  futures.push_back(restartApplication(app, printOnly));
188  }
189 
190  for (auto future = futures.begin(); future != futures.end(); ++future)
191  {
192  future->wait();
193  }
194 }
195 
196 std::future<void> Exec::Executor::restartScenario(Data_Structure::ScenarioPtr scenario, bool printOnly)
197 {
198  std::packaged_task<void()> task(std::bind(&Executor::asyncScenarioRestart, this, scenario, printOnly)); // wrap the function
199  std::future<void> result = task.get_future(); // get a future
200  std::thread(std::move(task)).detach(); // launch on a thread
201 
202  return result;
203 }
204 
205 void Exec::Executor::loadAndSetCachedProperties(Data_Structure::ApplicationPtr application, std::string path, bool reload, bool set)
206 {
207  std::filesystem::path xmlFilePath = std::filesystem::path(path) / std::filesystem::path(application->getPackageName() + "." + application->getName() + ".xml");
208 
209  if (reload || !std::filesystem::exists(xmlFilePath))
210  {
211  std::filesystem::create_directories(path);
212 
213  std::string strCommand = application->getExecutableAbsPath().append(" -p -f xml -o ").append(xmlFilePath.string());
214  int ret = system(strCommand.c_str());
215  if (ret != 0)
216  {
217  ARMARX_WARNING << "Failed to generate properties xml for " << application->getName() << "\nCommand was: " << strCommand;
218  }
219  }
220  else
221  {
222  application->updateFound();
223  if (!application->getFound())
224  {
225  return;
226  }
227  //if executable more recent that xml reload xml
228  auto xmlDate = (std::filesystem::last_write_time(xmlFilePath));
229 
230  auto execDate = std::filesystem::last_write_time(application->getPathToExecutable().append("/").append(application->getExecutableName()));
231 
232  if (execDate > xmlDate)
233  {
234  loadAndSetCachedProperties(application, path, true, set);
235  return;
236  }
237  }
238 
239  if (set)
240  {
242  application->setProperties(parser.loadFromXml(xmlFilePath.string()));
243  }
244 }
245 
247 {
248  defaultStopStrategy = strategy;
249 }
251 {
252  defaultStartStrategy = appStarter;
253 }
254 
256 {
257  this->stopStrategy[scenario] = strategy;
258 }
259 
261 {
262  this->starter[scenario] = appStarter;
263 }
264 
266 {
267  if (starter.count(scenario) == 0)
268  {
269  return defaultStartStrategy;
270  }
271  return starter[scenario];
272 }
273 
275 {
276  if (stopStrategy.count(scenario) == 0)
277  {
278  return defaultStopStrategy;
279  }
280  return stopStrategy[scenario];
281 }
282 
284 {
285  return defaultStopStrategy;
286 }
ScenarioManager::Exec::Executor::setStopStrategy
void setStopStrategy(StopStrategyPtr strategy, Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:255
ScenarioManager::Exec::Executor::setDefaultStopStrategy
void setDefaultStopStrategy(StopStrategyPtr strategy)
Sets the strategy this Executor uses to stop applications.
Definition: Executor.cpp:246
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:21
ScenarioManager::Data_Structure::ScenarioPtr
std::shared_ptr< Scenario > ScenarioPtr
Definition: Scenario.h:36
iceparser.h
ScenarioManager::Exec::Executor::getStarter
ApplicationStarterPtr getStarter(Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:265
ScenarioManager::Exec::Executor::restartApplication
std::future< void > restartApplication(Data_Structure::ApplicationInstancePtr application, bool printOnly=false)
Restarts an application.
Definition: Executor.cpp:108
ScenarioManager::Data_Structure::ApplicationPtr
std::shared_ptr< Application > ApplicationPtr
Definition: Application.h:119
ScenarioManager::Parser::IceParser
Definition: iceparser.h:37
ScenarioManager::Exec::Executor::stopApplication
std::future< void > stopApplication(Data_Structure::ApplicationInstancePtr application)
Stops an application.
Definition: Executor.cpp:68
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:45
ScenarioManager::Exec::Executor::getApplicationStatus
std::string getApplicationStatus(Data_Structure::ApplicationInstancePtr application)
Returns the status of an application.
Definition: Executor.cpp:125
ApplicationInstancePtr
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition: StopStrategy.h:7
ScenarioManager::Exec::Executor::stopScenario
std::future< void > stopScenario(Data_Structure::ScenarioPtr scenario)
Stops a scenario.
Definition: Executor.cpp:173
ScenarioManager::Exec::Executor::getStopStrategy
StopStrategyPtr getStopStrategy(Data_Structure::ScenarioPtr scenario)
Definition: Executor.cpp:274
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:250
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:64
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:33
ScenarioManager
Definition: Application.cpp:166
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
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:260
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
Logging.h
ScenarioManager::Exec::Executor::Executor
Executor(StopStrategyPtr strategy, ApplicationStarterPtr starter)
Constructor that sets StopStrategy and ApplicationStarter.
Definition: Executor.cpp:39
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
ScenarioManager::Exec::Executor::getDefaultStopStrategy
StopStrategyPtr getDefaultStopStrategy()
Definition: Executor.cpp:283
ScenarioManager::Exec::Executor::restartScenario
std::future< void > restartScenario(Data_Structure::ScenarioPtr scenario, bool printOnly=false)
Restarts a scenario.
Definition: Executor.cpp:196
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:205
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:134
ScenarioManager::Exec::ApplicationStarter::startApplication
virtual void startApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false)=0
Starts an application.