27 #include <IceUtil/IceUtil.h>
33 #include <boost/interprocess/sync/file_lock.hpp>
34 #include <boost/interprocess/sync/scoped_lock.hpp>
42 stateType = eRemoteState;
53 RemoteStateInterface(
source),
54 RemoteStateIceBase(
source),
65 remoteStateId =
source.remoteStateId;
72 stateOffererPrx =
source.stateOffererPrx;
84 if (remoteStateId >= 0 && stateOffererPrx)
90 stateOffererPrx->removeInstance(remoteStateId);
92 catch (Ice::NotRegisteredException& e)
94 ARMARX_WARNING <<
"Could not remove instance of RemoteState '" << stateClassName <<
"'; probably the remote component is not alive anymore" <<
flush;
101 if (!stateName.empty())
103 this->stateName = stateName;
111 if (!proxyName.empty())
113 this->proxyName = proxyName;
125 static const char*
const g_lockFile =
"/tmp/armarx-statechart.lock";
126 static std::once_flag g_createLockFileFlag;
127 static std::mutex g_processMutex;
134 stateOffererPrx = getProxy<RemoteStateOffererIceBasePrx>(proxyName);
136 if (!stateOffererPrx)
142 myProxy = RemoteStateIceBasePrx::checkedCast(
getProxy());
145 #define USE_NEW_CREATE_STATECHART_INSTANCE
146 #ifdef USE_NEW_CREATE_STATECHART_INSTANCE
148 std::call_once(g_createLockFileFlag, []()
150 if (!std::filesystem::exists(g_lockFile))
152 std::ofstream lockFile(g_lockFile);
153 lockFile <<
"ArmarX Statechart Lock File";
157 boost::interprocess::file_lock file_lock(g_lockFile);
160 boost::interprocess::scoped_lock<boost::interprocess::file_lock> globalLock(file_lock);
161 std::scoped_lock localLock(g_processMutex);
164 catch (std::exception
const& ex)
167 <<
"'\n Waiting for 10 ms before calling createRemoteStateInstance for "
168 << stateClassName <<
", " << stateName;
172 ARMARX_IMPORTANT <<
"Calling stateOffererPrx->createRemoteStateInstanceNew for " << stateClassName <<
", " << stateName;
174 CreateRemoteStateInstanceInput
input;
175 input.stateClassName = stateClassName;
176 input.remoteState = myProxy;
177 input.parentStateItentifierStr = globalStateIdentifier;
178 input.instanceName = stateName;
180 CreateRemoteStateInstanceOutput output;
185 output = stateOffererPrx->createRemoteStateInstanceNew(
input);
187 catch (Ice::ConnectFailedException
const& e)
189 ARMARX_WARNING <<
"Ice connect failed, trying again in a little bit";
191 output = stateOffererPrx->createRemoteStateInstanceNew(
input);
193 remoteStateId = output.remoteStateId;
194 inputParameters = output.inputParameters;
195 outputParameters = output.outputParameters;
197 StateIceBasePtr state = output.statechartInstance;
205 std::call_once(g_createLockFileFlag, []()
207 if (!std::filesystem::exists(g_lockFile))
209 std::ofstream lockFile(g_lockFile);
210 lockFile <<
"ArmarX Statechart Lock File";
214 boost::interprocess::file_lock file_lock(g_lockFile);
217 boost::interprocess::scoped_lock<boost::interprocess::file_lock> globalLock(file_lock);
218 std::scoped_lock localLock(g_processMutex);
221 catch (std::exception
const& ex)
224 <<
"'\n Waiting for 10 ms before calling createRemoteStateInstance for "
225 << stateClassName <<
", " << stateName;
229 ARMARX_IMPORTANT <<
"Calling stateOffererPrx->createRemoteStateInstance for " << stateClassName <<
", " << stateName;
232 remoteStateId = stateOffererPrx->createRemoteStateInstance(stateClassName, myProxy, globalStateIdentifier, stateName);
234 catch (Ice::ConnectFailedException
const& e)
236 ARMARX_WARNING <<
"Ice connect failed, trying again in a little bit";
238 remoteStateId = stateOffererPrx->createRemoteStateInstance(stateClassName, myProxy, globalStateIdentifier, stateName);
240 StateIceBasePtr state = stateOffererPrx->getStatechartInstance(remoteStateId);
243 subStateList = state->subStateList;
244 transitions = state->transitions;
245 activeSubstate = state->activeSubstate;
246 initState = state->initState;
255 ARMARX_INFO <<
"Remote State '" << this->
getStateName() <<
"' was disconnected during execution -> sending failure event";
263 if (remoteStateId != -1 && stateOffererPrx)
265 stateOffererPrx->removeInstance(remoteStateId);
274 stateOffererPrx =
nullptr;
285 getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(result),
false);
288 result->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
299 result->setName(result->getDefaultName());
300 result->setStateName(stateName);
302 result->setProxyName(proxyName);
304 getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(result),
false);
310 std::stringstream componentName;
311 componentName <<
"RemoteState_" <<
getLocalUniqueId() <<
"_" << proxyName <<
"_" << globalStateIdentifier;
312 return componentName.str();
414 if (!stateOffererPrx || remoteStateId == -1)
421 return stateOffererPrx->hasSubstatesRemote(stateClassName);
431 if (!stateOffererPrx || remoteStateId == -1)
438 return stateOffererPrx->hasActiveSubstateRemote(remoteStateId);
450 if (remoteStateId != -1)
452 inputParameters = stateOffererPrx->getRemoteInputParametersById(remoteStateId);
456 inputParameters = stateOffererPrx->getRemoteInputParameters(stateClassName);
470 if (remoteStateId != -1)
472 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
476 outputParameters = stateOffererPrx->getRemoteOutputParameters(stateClassName);
481 return outputParameters;
487 if (remoteStateId == -1 || !stateOffererPrx)
492 return StateBasePtr::dynamicCast(stateOffererPrx->getStatechartInstance(remoteStateId));
497 auto start = IceUtil::Time::now();
502 double waitTime = (IceUtil::Time::now() - start).toMilliSecondsDouble();
503 return getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted, timeoutMS < 0 ? -1 :
std::max(0.0, timeoutMS - waitTime));
508 return initialized &&
getState() >= eManagedIceObjectStarted;
517 ARMARX_WARNING <<
"Trying to enter remote state '" << stateName <<
"', but it is not reachable yet!";
528 if (lock.owns_lock())
535 catch (Ice::Exception& e)
537 ARMARX_ERROR <<
"Caught exception in " << stateName <<
"::baseOnEnter(): " << e.what() <<
"\n" << e.ice_stackTrace() <<
flush;
539 catch (std::exception& e)
541 ARMARX_ERROR <<
"Caught exception in " << stateName <<
"::baseOnEnter(): " << e.what() <<
"\n" <<
flush;
561 if (remoteStateId == -1)
568 bool result = stateOffererPrx->breakRemoteState(remoteStateId, evt);
570 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
587 stateOffererPrx->exitRemoteState(remoteStateId);
588 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
598 ARMARX_DEBUG <<
"notifying state with id " << remoteStateId <<
" eventBuffered:" << std::string((eventBuffered) ?
"true" :
"false") <<
flush;
600 if (remoteStateId != -1 && stateOffererPrx)
602 stateOffererPrx->begin_notifyEventBufferedDueToUnbreakableStateRemote(remoteStateId, eventBuffered);
608 if (remoteStateId != -1 && stateOffererPrx)
610 StateIceBasePtr state = stateOffererPrx->refetchRemoteSubstates(remoteStateId);
611 subStateList = state->subStateList;
612 transitions = state->transitions;
613 activeSubstate = state->activeSubstate;
614 initState = state->initState;
621 if (remoteStateId != -1 && stateOffererPrx)
624 auto pos =
id.find_last_of(
">");
625 if (pos != std::string::npos)
627 id.erase(
id.find_last_of(
">") - 1);
629 stateOffererPrx->updateGlobalStateIdRecursive(remoteStateId,
id);
638 return stateOffererPrx->breakActiveSubstateRemotely(remoteStateId, event);
644 <<
", parentState Ice ID: " << (parentState ? parentState->ice_id() :
"(null)");