SimpleStatechartExecutor.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarXCore::ArmarXObjects::SimpleStatechartExecutor
17 * @author Stefan Reither ( stefan dot reither at kit dot edu )
18 * @date 2020
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
30
31namespace armarx
32{
33 void
35 const StateParameterMap& inputArguments,
36 const Ice::Current&)
37 {
38 for (const auto& arg : inputArguments)
39 {
40 ContainerTypePtr type = checkIfLibraryNeedsToBeLoaded(arg.second);
41 if (type)
42 {
43 ARMARX_DEBUG << "Loading lib for variant: " << type->typeId;
44 _loadedDynamicLibraries[type->typeId] =
45 variantInfo->loadLibraryOfVariant(type->typeId);
46 }
47 }
49 }
50
51 bool
52 SimpleStatechartExecutor::startStatechart(const std::string& proxyName,
53 const std::string& stateName,
54 const StateParameterMap& inputArguments,
55 const Ice::Current&)
56 {
57 for (const auto& arg : inputArguments)
58 {
59 if (checkIfLibraryNeedsToBeLoaded(arg.second))
60 {
61 ARMARX_ERROR << "DynamicLibrary for argument '" << arg.first
62 << "' is not loaded! Statechart will not be started.";
63 return false;
64 }
65 }
66
67 if (!_finished)
68 {
69 ARMARX_WARNING << "SimpleStatechartExecutor is not ready. Cannot start statechart";
70 return false;
71 }
72
73 RemoteStateOffererIceBasePrx prx;
74 try
75 {
76 prx = getProxy<RemoteStateOffererIceBasePrx>(proxyName, false);
77 }
78 catch (::Ice::NotRegisteredException& e)
79 {
80 ARMARX_WARNING << "RemoteStateOfferer '" << proxyName << "' not available!";
81 return false;
82 }
83
84 if (!prx)
85 {
86 ARMARX_WARNING << "RemoteStateOfferer '" << proxyName << "' not available!";
87 return false;
88 }
89
90 StateBasePtr stateBasePtr = StateBasePtr::dynamicCast(prx->getStatechart(stateName));
91 if (!stateBasePtr)
92 {
93 ARMARX_WARNING << "RemoteStateOfferer '" << proxyName
94 << "' does not have an available state with name: '" << stateName
95 << "'!";
96 return false;
97 }
98
99 _prx = RemoteStateOffererInterfacePrx::checkedCast(prx);
100 _currentStateId = _prx->createRemoteStateInstance(
101 stateName, nullptr, stateName, stateName + IceUtil::generateUUID());
102
103 StringVariantContainerBaseMap input = StateUtilFunctions::getSetValues(inputArguments);
104 _prx->callRemoteState(_currentStateId, input);
105
106 {
107 std::unique_lock lock(_finishedMutex);
108 _finished = false;
109 }
110 _aborted = false;
111
112 if (_runningTask)
113 {
114 _runningTask->stop(false);
115 }
116 _runningTask = new RunningTask<SimpleStatechartExecutor>(
117 this, &SimpleStatechartExecutor::statechartTask, "StatechartManager");
118 _runningTask->start();
119 return true;
120 }
121
122 void
124 {
125 std::unique_lock lock(_finishedMutex);
126 if (!_finished && _prx && isCurrentStateIdValid())
127 {
128 _prx->breakActiveSubstateRemotely(_currentStateId, nullptr);
129 _prx->breakRemoteState(_currentStateId, nullptr);
130 _aborted = true;
131 _finishedCondition.wait(lock);
132 }
133 else
134 {
135 _finished = true;
136 _finishedCondition.notify_all();
137 }
138 _currentStateId = -1;
139 }
140
141 bool
143 {
144 return _finished;
145 }
146
147 StatechartExecutionResult
149 {
150 std::unique_lock lock(_finishedMutex);
151
152 while (!_finished)
153 {
154 _finishedCondition.wait(lock);
155 usleep(1000);
156 }
157 return _lastResult;
158 }
159
160 StringVariantContainerBaseMap
162 {
163 std::unique_lock lock(_finishedMutex);
164 if (_finished)
165 {
166 return StateUtilFunctions::getSetValues(_lastOutputParameters);
167 }
168 else
169 {
170 return StringVariantContainerBaseMap();
171 }
172 }
173
174 StateParameterMap
176 {
177 std::unique_lock lock(_finishedMutex);
178 if (_finished)
179 {
180 return _lastOutputParameters;
181 }
182 else
183 {
184 return StateParameterMap();
185 }
186 }
187
188 void
190 const Ice::Current&)
191 {
192 for (const auto& typeName : typeNames)
193 {
194 ARMARX_INFO << "Loading library for type '" << typeName << "'";
195 _loadedDynamicLibraries[typeName] = variantInfo->loadLibraryOfVariant(typeName);
196 }
198 }
199
200 void
202 {
203 std::string packagesString =
204 getProperty<std::string>("PackagesForVariantLibraries").getValue();
205 _packages = armarx::Split(packagesString, ",", true, true);
206 variantInfo = VariantInfo::ReadInfoFiles(_packages, true, false);
207 }
208
209 void
211 {
212 _finished = true;
213 }
214
215 void
217 {
218 ARMARX_DEBUG << "Unloading dynamicLibraries";
219 for (const auto& it : _loadedDynamicLibraries)
220 {
221 DynamicLibraryPtr lib = it.second;
222 lib->unload();
223 }
224
225 if (!_finished)
226 {
227 stopImmediatly(Ice::emptyCurrent);
228 {
229 std::unique_lock lock(_finishedMutex);
230 _finished = true;
231 _finishedCondition.notify_all();
232 }
233 _runningTask->stop();
234 }
235 }
236
243
244 void
245 SimpleStatechartExecutor::statechartTask()
246 {
247 while (_prx && isCurrentStateIdValid() && !_prx->isRemoteStateFinished(_currentStateId))
248 {
249 usleep(1000);
250 }
251 if (_prx)
252 {
253 _lastResult = (_aborted ? eAborted : eSuccess);
254 // TODO find better way to solve the problem of not laoded libraries for outputParameter
255 _lastOutputParameters = _prx->getStatechartInstance(_currentStateId)->outputParameters;
256 ensureVariantLibrariesAreLoaded(_lastOutputParameters, Ice::emptyCurrent);
257 _lastOutputParameters = _prx->getStatechartInstance(_currentStateId)->outputParameters;
258 }
259 std::unique_lock lock(_finishedMutex);
260 _finished = true;
261 _finishedCondition.notify_all();
262
263 ARMARX_INFO << "statechartTask finished";
264 }
265
266 ContainerTypePtr
267 SimpleStatechartExecutor::checkIfLibraryNeedsToBeLoaded(
268 const StateParameterIceBasePtr parameter) const
269 {
270 bool loadLib = false;
271 ContainerTypePtr containerType = parameter->value->getContainerType();
272 if (containerType->typeId == "::armarx::SingleTypeVariantListBase" ||
273 containerType->typeId == "::armarx::StringValueMapBase")
274 {
275 while (containerType->subType)
276 {
277 containerType = containerType->subType;
278 }
279 loadLib = _loadedDynamicLibraries.count(containerType->typeId) == 0;
280 }
281 else
282 {
283 SingleVariantPtr variant = SingleVariantPtr::dynamicCast(parameter->value);
284 if (variant && variant->get()->data->ice_id() == "::armarx::VariantData")
285 {
286 loadLib = _loadedDynamicLibraries.count(containerType->typeId) == 0;
287 }
288 }
289
290 return loadLib ? containerType : ContainerTypePtr();
291 }
292
293 bool
294 SimpleStatechartExecutor::isCurrentStateIdValid() const
295 {
296 for (const auto& it : _prx->getAvailableStateInstances())
297 {
298 if (it.first == _currentStateId)
299 {
300 return true;
301 }
302 }
303 return false;
304 }
305} // namespace armarx
static void RegisterKnownObjectFactoriesWithIce(const Ice::CommunicatorPtr &ic)
Registers all object factories that are known with Ice.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
Property< PropertyType > getProperty(const std::string &name)
IceManagerPtr getIceManager() const
Returns the IceManager.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
Ice::CommunicatorPtr getCommunicator() const
void onInitComponent() override
Pure virtual hook for the subclass.
StringVariantContainerBaseMap getSetOutputParameters(const Ice::Current &) override
bool hasExecutionFinished(const Ice::Current &) override
StateParameterMap getOutputParameters(const Ice::Current &) override
void ensureVariantLibrariesAreLoaded(const StateParameterMap &inputArguments, const Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
bool startStatechart(const std::string &proxyName, const std::string &stateName, const StateParameterMap &inputArguments, const Ice::Current &) override
void onConnectComponent() override
Pure virtual hook for the subclass.
StatechartExecutionResult waitUntilStatechartExecutionIsFinished(const Ice::Current &) override
void preloadLibrariesFromHumanNames(const StringList &typeNames, const Ice::Current &) override
void onExitComponent() override
Hook for subclass.
void stopImmediatly(const Ice::Current &) override
static VariantInfoPtr ReadInfoFiles(const std::vector< std::string > &packages, bool showErrors=true, bool throwOnError=true)
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
StringVariantContainerBaseMap getSetValues(const StateParameterMap &paramMap)
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceInternal::Handle< SingleVariant > SingleVariantPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
IceInternal::Handle< StateBase > StateBasePtr
Definition StateBase.h:49
std::shared_ptr< DynamicLibrary > DynamicLibraryPtr