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
40using namespace ScenarioManager;
41
47
48std::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
79std::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
97void
98Exec::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
125std::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
144std::string
146{
147 if (application->getStatusWriteBlock())
148 {
149 return "Waiting";
150 }
151 return getStarter(application->getScenario())->getStatus(application, statusManager);
152}
153
154std::future<void>
155Exec::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
185void
186Exec::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
202std::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
213void
214Exec::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
228std::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
239void
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 {
286 Parser::IceParser parser;
287 application->setProperties(parser.loadFromXml(xmlFilePath.string()));
288 }
289}
290
291void
293{
294 defaultStopStrategy = strategy;
295}
296
297void
299{
300 defaultStartStrategy = appStarter;
301}
302
303void
305{
306 this->stopStrategy[scenario] = strategy;
307}
308
309void
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}
std::shared_ptr< ScenarioManager::Data_Structure::ApplicationInstance > ApplicationInstancePtr
Definition StopStrategy.h:7
virtual void startApplication(Data_Structure::ApplicationInstancePtr application, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false)=0
Starts an application.
virtual void startScenario(Data_Structure::ScenarioPtr scenario, StatusManager statusManager, const std::string &commandLineParameters="", bool printOnly=false)=0
StopStrategyPtr getStopStrategy(Data_Structure::ScenarioPtr scenario)
Definition Executor.cpp:326
std::future< void > startScenario(Data_Structure::ScenarioPtr scenario, bool printOnly=false, const std::string &commandLineParameters="")
Starts a scenario.
Definition Executor.cpp:155
void setDefaultStarter(ApplicationStarterPtr appStarter)
Sets the appStarter this Executor uses to start applications and request statuses.
Definition Executor.cpp:298
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
std::future< void > restartApplication(Data_Structure::ApplicationInstancePtr application, bool printOnly=false)
Restarts an application.
Definition Executor.cpp:126
std::future< void > stopScenario(Data_Structure::ScenarioPtr scenario)
Stops a scenario.
Definition Executor.cpp:203
std::string getApplicationStatus(Data_Structure::ApplicationInstancePtr application)
Returns the status of an application.
Definition Executor.cpp:145
std::future< void > restartScenario(Data_Structure::ScenarioPtr scenario, bool printOnly=false)
Restarts a scenario.
Definition Executor.cpp:229
std::future< void > startApplication(Data_Structure::ApplicationInstancePtr application, bool printOnly=false, const std::string &commandLineParameters="")
Starts an application.
Definition Executor.cpp:49
Executor(StopStrategyPtr strategy, ApplicationStarterPtr starter)
Constructor that sets StopStrategy and ApplicationStarter.
Definition Executor.cpp:42
std::future< void > stopApplication(Data_Structure::ApplicationInstancePtr application)
Stops an application.
Definition Executor.cpp:80
void setDefaultStopStrategy(StopStrategyPtr strategy)
Sets the strategy this Executor uses to stop applications.
Definition Executor.cpp:292
StopStrategyPtr getDefaultStopStrategy()
Definition Executor.cpp:336
void setStarter(ApplicationStarterPtr appStarter, Data_Structure::ScenarioPtr scenario)
Definition Executor.cpp:310
ApplicationStarterPtr getStarter(Data_Structure::ScenarioPtr scenario)
Definition Executor.cpp:316
void setStopStrategy(StopStrategyPtr strategy, Data_Structure::ScenarioPtr scenario)
Definition Executor.cpp:304
virtual void stop(Data_Structure::ApplicationInstancePtr application)=0
Stops an application.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
std::shared_ptr< Scenario > ScenarioPtr
Definition Scenario.h:35
std::shared_ptr< Application > ApplicationPtr
std::shared_ptr< StopStrategy > StopStrategyPtr
Definition Executor.h:46
std::shared_ptr< ApplicationStarter > ApplicationStarterPtr