28#include <boost/interprocess/sync/file_lock.hpp>
29#include <boost/interprocess/sync/scoped_lock.hpp>
31#include <IceUtil/IceUtil.h>
46 stateType = eRemoteState;
57 RemoteStateInterface(source),
58 RemoteStateIceBase(source),
69 remoteStateId = source.remoteStateId;
76 stateOffererPrx = source.stateOffererPrx;
89 if (remoteStateId >= 0 && stateOffererPrx)
95 stateOffererPrx->removeInstance(remoteStateId);
97 catch (Ice::NotRegisteredException& e)
99 ARMARX_WARNING <<
"Could not remove instance of RemoteState '" << stateClassName
100 <<
"'; probably the remote component is not alive anymore" <<
flush;
108 if (!stateName.empty())
110 this->stateName = stateName;
119 if (!proxyName.empty())
121 this->proxyName = proxyName;
133 static const char*
const g_lockFile =
"/tmp/armarx-statechart.lock";
134 static std::once_flag g_createLockFileFlag;
135 static std::mutex g_processMutex;
144 if (!stateOffererPrx)
150 myProxy = RemoteStateIceBasePrx::checkedCast(
getProxy());
153#define USE_NEW_CREATE_STATECHART_INSTANCE
154#ifdef USE_NEW_CREATE_STATECHART_INSTANCE
156 std::call_once(g_createLockFileFlag,
159 if (!std::filesystem::exists(g_lockFile))
161 std::ofstream lockFile(g_lockFile);
162 lockFile <<
"ArmarX Statechart Lock File";
166 boost::interprocess::file_lock file_lock(g_lockFile);
169 boost::interprocess::scoped_lock<boost::interprocess::file_lock> globalLock(file_lock);
170 std::scoped_lock localLock(g_processMutex);
173 catch (std::exception
const& ex)
176 <<
"'\n Waiting for 10 ms before calling createRemoteStateInstance for "
177 << stateClassName <<
", " << stateName;
181 ARMARX_IMPORTANT <<
"Calling stateOffererPrx->createRemoteStateInstanceNew for "
182 << stateClassName <<
", " << stateName;
184 CreateRemoteStateInstanceInput input;
185 input.stateClassName = stateClassName;
186 input.remoteState = myProxy;
187 input.parentStateItentifierStr = globalStateIdentifier;
188 input.instanceName = stateName;
190 CreateRemoteStateInstanceOutput output;
195 output = stateOffererPrx->createRemoteStateInstanceNew(input);
197 catch (Ice::ConnectFailedException
const& e)
199 ARMARX_WARNING <<
"Ice connect failed, trying again in a little bit";
201 output = stateOffererPrx->createRemoteStateInstanceNew(input);
203 remoteStateId = output.remoteStateId;
204 inputParameters = output.inputParameters;
205 outputParameters = output.outputParameters;
207 StateIceBasePtr state = output.statechartInstance;
210 stateOffererPrx->getRemoteInputParameters(stateClassName), inputParameters);
215 stateOffererPrx->getRemoteOutputParameters(stateClassName), outputParameters);
217 std::call_once(g_createLockFileFlag,
220 if (!std::filesystem::exists(g_lockFile))
222 std::ofstream lockFile(g_lockFile);
223 lockFile <<
"ArmarX Statechart Lock File";
227 boost::interprocess::file_lock file_lock(g_lockFile);
230 boost::interprocess::scoped_lock<boost::interprocess::file_lock> globalLock(file_lock);
231 std::scoped_lock localLock(g_processMutex);
234 catch (std::exception
const& ex)
237 <<
"'\n Waiting for 10 ms before calling createRemoteStateInstance for "
238 << stateClassName <<
", " << stateName;
242 ARMARX_IMPORTANT <<
"Calling stateOffererPrx->createRemoteStateInstance for "
243 << stateClassName <<
", " << stateName;
246 remoteStateId = stateOffererPrx->createRemoteStateInstance(
247 stateClassName, myProxy, globalStateIdentifier, stateName);
249 catch (Ice::ConnectFailedException
const& e)
251 ARMARX_WARNING <<
"Ice connect failed, trying again in a little bit";
253 remoteStateId = stateOffererPrx->createRemoteStateInstance(
254 stateClassName, myProxy, globalStateIdentifier, stateName);
256 StateIceBasePtr state = stateOffererPrx->getStatechartInstance(remoteStateId);
259 subStateList = state->subStateList;
260 transitions = state->transitions;
261 activeSubstate = state->activeSubstate;
262 initState = state->initState;
271 <<
"' was disconnected during execution -> sending failure event";
279 if (remoteStateId != -1 && stateOffererPrx)
281 stateOffererPrx->removeInstance(remoteStateId);
289 stateOffererPrx =
nullptr;
299 getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(result),
false);
302 result->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
313 result->setName(result->getDefaultName());
314 result->setStateName(stateName);
316 result->setProxyName(proxyName);
318 getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(result),
false);
325 std::stringstream componentName;
326 componentName <<
"RemoteState_" <<
getLocalUniqueId() <<
"_" << proxyName <<
"_"
327 << globalStateIdentifier;
328 return componentName.str();
358 stateName +
" is NULL");
369 stateName +
" is NULL");
377 const EventBasePtr& event,
378 const Ice::Current&
c)
387 stateName +
" is NULL");
399 stateName +
" is NULL");
418 stateName +
" is NULL");
434 if (!stateOffererPrx || remoteStateId == -1)
441 return stateOffererPrx->hasSubstatesRemote(stateClassName);
452 if (!stateOffererPrx || remoteStateId == -1)
459 return stateOffererPrx->hasActiveSubstateRemote(remoteStateId);
472 if (remoteStateId != -1)
474 inputParameters = stateOffererPrx->getRemoteInputParametersById(remoteStateId);
478 inputParameters = stateOffererPrx->getRemoteInputParameters(stateClassName);
482 StateParameterMap result;
491 if (stateOffererPrx &&
494 if (remoteStateId != -1)
496 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
500 outputParameters = stateOffererPrx->getRemoteOutputParameters(stateClassName);
505 return outputParameters;
511 if (remoteStateId == -1 || !stateOffererPrx)
516 return StateBasePtr::dynamicCast(stateOffererPrx->getStatechartInstance(remoteStateId));
522 auto start = IceUtil::Time::now();
527 double waitTime = (IceUtil::Time::now() - start).toMilliSecondsDouble();
529 eManagedIceObjectStarted, timeoutMS < 0 ? -1 : std::max(0.0, timeoutMS - waitTime));
535 return initialized &&
getState() >= eManagedIceObjectStarted;
545 <<
"', but it is not reachable yet!";
555 if (lock.owns_lock())
559 ARMARX_DEBUG <<
"input for remotestate " << stateName <<
" (" << remoteStateId
563 stateOffererPrx->callRemoteState(remoteStateId,
566 catch (Ice::Exception& e)
569 <<
"::baseOnEnter(): " << e.what() <<
"\n"
570 << e.ice_stackTrace() <<
flush;
572 catch (std::exception& e)
575 <<
"::baseOnEnter(): " << e.what() <<
"\n"
598 if (remoteStateId == -1)
605 bool result = stateOffererPrx->breakRemoteState(remoteStateId, evt);
607 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
625 stateOffererPrx->exitRemoteState(remoteStateId);
626 outputParameters = stateOffererPrx->getRemoteOutputParametersById(remoteStateId);
636 ARMARX_DEBUG <<
"notifying state with id " << remoteStateId
637 <<
" eventBuffered:" << std::string((eventBuffered) ?
"true" :
"false")
640 if (remoteStateId != -1 && stateOffererPrx)
642 stateOffererPrx->begin_notifyEventBufferedDueToUnbreakableStateRemote(remoteStateId,
650 if (remoteStateId != -1 && stateOffererPrx)
652 StateIceBasePtr state = stateOffererPrx->refetchRemoteSubstates(remoteStateId);
653 subStateList = state->subStateList;
654 transitions = state->transitions;
655 activeSubstate = state->activeSubstate;
656 initState = state->initState;
664 if (remoteStateId != -1 && stateOffererPrx)
667 auto pos =
id.find_last_of(
">");
668 if (pos != std::string::npos)
670 id.erase(
id.find_last_of(
">") - 1);
672 stateOffererPrx->updateGlobalStateIdRecursive(remoteStateId,
id);
681 return stateOffererPrx->breakActiveSubstateRemotely(remoteStateId, event);
689 <<
", parentState Ice ID: "
690 << (parentState ? parentState->ice_id() :
"(null)");
Base Class for all Logging classes.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
ArmarXObjectSchedulerPtr getObjectScheduler() const
ManagedIceObject(ManagedIceObject const &other)
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
int getState() const
Retrieve current state of the ManagedIceObject.
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
void setName(std::string name)
Override name of well-known object.
This Statetype is used to create a state instance that represents a state that is located in another ...
void onInitComponent() override
Pure virtual hook for the subclass.
StateParameterMap getInputParameters() override
Not const because RemoteState implementation gets the current parameters via Ice and sets them.
bool waitForInitialization(int timeoutMS) const override
RemoteState & operator=(const RemoteState &source)
void setProxyName(const std::string &proxyName)
void __updateGlobalStateIdRecursive() override
StateBasePtr clone() const override
Pure virtual function to clone of the derived class type.
void onDisconnectComponent() override
Hook for subclass.
bool isInitialized() const override
Returns the status of this state. Only if a state is initialized, it can be used.
bool _baseOnBreak(const EventPtr evt) override
Called by processEvent()-function or parentstate. Must NOT be called by user.
void refetchSubstates() override
This functions updates the substates.
void remoteFinalize(const StringVariantContainerBaseMap &properties, const EventBasePtr &event, const ::Ice::Current &c=Ice::emptyCurrent) override
bool __breakActiveSubstate(const EventPtr event) override
Overridden function to redirect this call to the real state in the other application.
StateBasePtr createEmptyCopy() const override
bool getRemoteUnbreakableBufferStati(const ::Ice::Current &=Ice::emptyCurrent) const override
void setStateName(const std::string &stateName)
StateIceBasePtr getParentStateLayout(const Ice::Current &) const override
void onConnectComponent() override
Pure virtual hook for the subclass.
void remoteProcessEvent(const EventBasePtr &evt, bool buffered, const ::Ice::Current &c=Ice::emptyCurrent) override
void _baseOnExit() override
Overridden function to redirect this call to the real state in the other application.
void remoteEnqueueEvent(const EventBasePtr &evt, const ::Ice::Current &c=Ice::emptyCurrent) override
::Ice::Int getRemoteUnbreakableBufferSize(const ::Ice::Current &=Ice::emptyCurrent) const override
void __notifyEventBufferedDueToUnbreakableState(bool eventBuffered) override
Overridden function to redirect this call to the real state in the other application.
bool __hasSubstates() override
not used at the moment
StateBasePtr getRemoteStatePtr()
Function that retrieves a copy of the remoteState. Calling functions or setting members on this insta...
void remoteProcessBufferedEvents(const ::Ice::Current &c=Ice::emptyCurrent) override
void _baseOnEnter() override
Overridden function to redirect this call to the real state in the other application.
std::string getDefaultName() const override
Retrieve default name of component.
bool __hasActiveSubstate() override
Overridden function to redirect this call to the real state in the other application.
StateParameterMap & getOutputParameters() override
This class is the implementation of the Slice Definition of a state.
void __updateGlobalStateId()
virtual bool waitForInitialization(int timeoutMS=-1) const
void setStatePhase(StatePhase newPhase)
const std::string & getStateClassName() const
std::unique_ptr< Impl > impl
StatePhase getStatePhase() const
std::string getGlobalHierarchyString() const
Ice::Int getLocalUniqueId() const
std::string getStateName() const
getStateName
virtual void onExit()
Virtual function, in which the behaviour of state is defined, when it is exited. Can be overridden,...
The StateController class processes events and controls the statechart flow.
virtual void __enqueueEvent(const EventPtr event)
virtual void __finalize(const EventPtr event)
Function that gets called, when a state enters a FinalSubstate. Virtual function, so that RemoteState...
StateControllerPtr __getParentState() const
Getter function that automatically casts the parentState member of StateBase into StateControllerPtr.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
boost::detail::try_lock_wrapper< HiddenTimedMutex > ScopedTryLock
boost::unique_lock< HiddenTimedMutex > ScopedLock
void copyDictionary(const StringVariantContainerBaseMap &source, StringVariantContainerBaseMap &destination)
Clears the destination map and copies the parameters of the source in it.
std::string getDictionaryString(const StringVariantContainerBaseMap &mymap)
Converts the map into a string-representation.
StringVariantContainerBaseMap getSetValues(const StateParameterMap ¶mMap)
void fillDictionary(const StringVariantContainerBaseMap &source, StringVariantContainerBaseMap &destination)
Tries to fill the destination map with matching entries of the source map. Entries that could not be ...
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< RemoteState > RemoteStatePtr
const LogSender::manipulator flush
IceInternal::Handle< Event > EventPtr
Typedef of EventPtr as IceInternal::Handle<Event> for convenience.
IceInternal::Handle< StateBase > StateBasePtr
IceInternal::Handle< StateController > StateControllerPtr