38 #include <Ice/BuiltinSequences.h>
39 #include <Ice/Communicator.h>
40 #include <Ice/Identity.h>
41 #include <Ice/Initialize.h>
42 #include <Ice/LocalException.h>
43 #include <Ice/NativePropertiesAdmin.h>
44 #include <Ice/ObjectAdapter.h>
45 #include <Ice/ObjectF.h>
46 #include <Ice/Properties.h>
47 #include <Ice/PropertiesF.h>
48 #include <Ice/Proxy.h>
49 #include <Ice/ProxyF.h>
50 #include <IceGrid/Admin.h>
51 #include <IceGrid/Registry.h>
52 #include <IceUtil/Handle.h>
53 #include <IceStorm/IceStorm.h>
73 #include "ArmarXCore/interface/core/BasicTypes.h"
74 #include "ArmarXCore/interface/core/Log.h"
75 #include "ArmarXCore/interface/core/ManagedIceObjectDefinitions.h"
76 #include "ArmarXCore/interface/core/ThreadingIceBase.h"
89 #define MANAGEROBJNAME applicationName + "Manager"
90 #define OBJOBSNAME std::string("ArmarXObjectObserver_") + applicationName
96 applicationName(applicationName),
97 managerState(eCreated)
100 std::stringstream defaultLocator;
101 defaultLocator <<
"--Ice.Default.Locator=" << locatorName <<
":tcp -p " << port <<
" -h " << host;
102 args.push_back(defaultLocator.str());
106 init(applicationName, communicator);
110 applicationName(applicationName),
111 managerState(eCreated)
114 init(applicationName, communicator);
131 const std::string armarxHint =
"'\nDid you start armarx?\n\nTo start armarx: armarx start\n"
132 "To kill a hanging armarx: armarx killIce" ;
135 if (communicator->getProperties()->getProperty(
"Ice.Default.Locator").empty())
139 std::cerr <<
"Required Ice property 'Ice.Default.Locator' not set! "
140 <<
"It has to has a value similar to 'IceGrid/Locator:tcp -p 4061 -h localhost'";
144 auto locatorProp = communicator->getProperties()->getProperty(
"Ice.Default.Locator");
145 auto pos = locatorProp.find_first_of(
':');
146 std::string locatorId = locatorProp.substr(0, pos) ;
147 auto proxy = communicator->stringToProxy(locatorId);
148 IceGrid::LocatorPrx::checkedCast(proxy);
154 std::cerr <<
"Could not contact default locator at '"
155 << communicator->getProperties()->getProperty(
"Ice.Default.Locator")
163 std::string registryId =
"IceGrid/Registry";
164 auto proxy = communicator->stringToProxy(registryId);
165 IceGrid::RegistryPrx::checkedCast(proxy);
171 std::cerr <<
"Could not contact IceGrid registry at '"
172 << communicator->getProperties()->getProperty(
"IceGrid.Registry.Client.Endpoints")
182 catch (
const Ice::NoEndpointException& e)
184 std::cout <<
"Caught exception: \n" << e.what() << std::endl;
188 std::cerr <<
"Could not contact TopicManager at '"
190 <<
"IceStorm/TopicManager"
237 addObject(
object, addWithOwnAdapter, objectName, useOwnScheduleThread);
244 throw LocalException(
"Cannot add NULL object");
247 auto cptr = ComponentPtr::dynamicCast(
object);
248 if (cptr && !cptr->createdByComponentCreate)
250 throw LocalException(
"Components need to be created by Component::create");
254 if (!objectName.empty())
256 if (!object->getName().empty())
258 ARMARX_INFO <<
"Adding object with custom name: " << objectName;
260 object->setName(objectName);
262 if (object->getName().empty())
264 object->setName(object->getDefaultName());
266 if (object->getName().empty())
268 throw LocalException(
"Object name must not be empty");
270 auto lock = acquireManagedObjectsMutex();
276 bool reachable =
false;
280 reachable =
getIceManager()->isObjectReachable(object->getName());
289 throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, object->ice_id(), object->getName());
295 auto pair = managedObjects.insert(std::make_pair(object->getName(), std::move(objectScheduler)));
298 ARMARX_WARNING <<
"Insert of object scheduler in managedObjects failed since there is already a scheduler for name " <<
object->getName();
300 if (!useOwnScheduleThread)
302 std::scoped_lock lock(schedulerListMutex);
303 singleThreadedSchedulers.at(rand() % singleThreadedSchedulers.size())->addObjectScheduler(pair.first->second);
321 manager->addObject(
object, objectName, addWithOwnAdapter, useOwnScheduleThread);
336 auto lock = acquireManagedObjectsMutex();
341 scheduler = managedObjects.find(objectName)->second;
347 removeObject(scheduler,
true);
359 auto removal = [objectName,
this]()
363 auto lock = acquireManagedObjectsMutex();
368 scheduler = managedObjects.find(objectName)->second;
372 this->removeObject(scheduler,
false);
381 std::thread {removal} .detach();
400 managerStateMutex.lock();
402 if (managerState == eShutdown)
404 managerStateMutex.unlock();
409 std::unique_lock lock(shutdownMutex);
410 managerStateMutex.unlock();
411 shutdownCondition.wait(lock);
421 std::scoped_lock lock(managerStateMutex);
424 if (managerState >= eShutdownInProgress)
429 managerState = eShutdownInProgress;
432 managedObjectsMutex.lock();
438 cleanupSchedulersTask->stop();
440 if (checkDependencyStatusTask)
442 checkDependencyStatusTask->stop();
445 sharedRemoteHandleState.reset();
446 remoteReferenceCountControlBlockManager.reset();
448 disconnectAllObjects();
454 removeAllObjects(
true);
457 iceManager->getIceGridSession()->getAdmin()->removeObject(
Ice::Identity {MANAGEROBJNAME,
""});
461 singleThreadedSchedulers.clear();
466 iceManager->shutdown();
469 iceManager->waitForShutdown();
475 iceManager->destroy();
478 objObserver =
nullptr;
482 std::scoped_lock lock(managerStateMutex);
486 std::unique_lock lock(shutdownMutex);
488 shutdownCondition.notify_all();
491 managerState = eShutdown;
494 managedObjectsMutex.unlock();
496 catch (std::exception& e)
498 ARMARX_INFO <<
"shutdown failed with exception!\n" << e.what() << std::endl;
501 ARMARX_INFO <<
"Shutdown of ArmarXManager finished!" << std::endl;
506 std::thread {[
this, timeoutMs]{
507 std::this_thread::sleep_for(std::chrono::milliseconds{timeoutMs});
515 std::scoped_lock lock(managerStateMutex);
516 return (managerState == eShutdown);
531 return iceManager->getCommunicator();
536 std::vector<ManagedIceObjectPtr> objects;
538 auto lock = acquireManagedObjectsMutex();
544 ObjectSchedulerMap::iterator iter = managedObjects.begin();
546 while (iter != managedObjects.end())
548 objects.push_back(iter->second->getObject());
561 auto lock = acquireManagedObjectsMutex();
564 return eManagedIceObjectExiting;
567 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
569 if (iter == managedObjects.end())
571 return eManagedIceObjectExited;
574 ManagedIceObjectState state = (ManagedIceObjectState)iter->second->getObject()->getState();
581 auto lock = acquireManagedObjectsMutex();
584 return ManagedIceObjectConnectivity();
587 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
589 if (iter == managedObjects.end())
591 return ManagedIceObjectConnectivity();
594 ManagedIceObjectConnectivity con = iter->second->getObject()->getConnectivity();
603 StringStringDictionary propertyMap;
604 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
606 if (iter == managedObjects.end())
618 auto result =
component->getPropertyDefinitions()->getPropertyValues(
component->getPropertyDefinitions()->getPrefix());
624 ObjectPropertyInfos propertyMap;
625 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
627 if (iter == managedObjects.end())
640 for (
auto prop :
component->getPropertyDefinitions()->getPropertyValues())
642 propertyMap[
component->getPropertyDefinitions()->getPrefix() + prop.first] = {
component->getPropertyDefinitions()->getDefinitionBase(prop.first)->isConstant(),
651 ObjectPropertyInfos propertyMap;
668 Ice::ObjectPrx adminObj =
getIceManager()->getCommunicator()->getAdmin();
669 Ice::PropertiesAdminPrx propAdmin = Ice::PropertiesAdminPrx::checkedCast(adminObj,
"Properties");
692 component->updateIceProperties(properties);
700 Ice::StringSeq objectNames;
702 auto lock = acquireManagedObjectsMutex();
708 ObjectSchedulerMap::iterator iter = managedObjects.begin();
710 while (iter != managedObjects.end())
712 objectNames.push_back(iter->first);
721 public Ice::PropertiesAdminUpdateCallback
725 application(application)
729 void updated(
const Ice::PropertyDict& changes)
override
734 application->updateIceProperties(changes);
754 communicator, applicationName,
755 appInstance ? appInstance->getProperty<std::string>(
"TopicSuffix").getValue() :
"");
760 throw Ice::ConnectFailedException(__FILE__, __LINE__);
763 this->installProcessFacet();
767 iceManager->getTopic<
LogPrx>(
"Log"));
775 auto icegrid = iceManager->getIceGridSession();
779 Ice::ObjectPrx oPrx = icegrid->registerObjectWithNewAdapter(objObserver, OBJOBSNAME, observerAdapter);
780 IceGrid::ObjectObserverPrx objObsPrx = IceGrid::ObjectObserverPrx::checkedCast(oPrx);
781 icegrid->setObjectObserver(objObsPrx);
784 icegrid->registerObjectWithNewAdapter(
this, MANAGEROBJNAME, armarxManagerAdapter);
789 cleanupSchedulersTask =
new PeriodicTask<ArmarXManager>(
this, &ArmarXManager::cleanupSchedulers, 500,
false,
"ArmarXManager::cleanupSchedulers");
790 cleanupSchedulersTask->start();
792 checkDependencyStatusTask =
new PeriodicTask<ArmarXManager>(
this, &ArmarXManager::checkDependencies, 1000,
false,
"ArmarXManager::DependenciesChecker");
793 checkDependencyStatusTask->start();
798 std::scoped_lock lock(managerStateMutex);
799 managerState = eRunning;
812 if (appInstance && appInstance->getProperty<
bool>(
"UseTimeServer").getValue())
824 sharedRemoteHandleState.reset(
828 appInstance->getProperty<
unsigned int>(
"RemoteHandlesDeletionTimeout").getValue() :
835 void ArmarXManager::cleanupSchedulers()
837 std::scoped_lock lock(terminatingObjectsMutex);
839 ObjectSchedulerList::iterator iter = terminatingObjects.begin();
841 while (iter != terminatingObjects.end())
845 "Checking termination state of " << sched->getObject()->getName() <<
848 if ((*iter)->isTerminated())
850 ARMARX_VERBOSE <<
"Delayed Removal of ManagedIceObject " << (*iter)->getObject()->getName() <<
" finished";
851 iter = terminatingObjects.erase(iter);
860 void ArmarXManager::disconnectDependees(
const std::string&
object)
864 std::vector<std::string> dependees = getDependendees(
object);
866 auto lock = acquireManagedObjectsMutex();
872 for (
const auto& dependee : dependees)
874 ArmarXManager::ObjectSchedulerMap::iterator it = managedObjects.find(dependee);
875 ARMARX_INFO <<
deactivateSpam(10, dependee +
object) <<
"'" << dependee <<
"' disconnected because of '" <<
object <<
"'";
877 if (it != managedObjects.end())
879 it->second->disconnected(
true);
890 void ArmarXManager::disconnectAllObjects()
892 auto lock = acquireManagedObjectsMutex();
897 ObjectSchedulerMap::iterator iter = managedObjects.begin();
899 for (; iter != managedObjects.end(); iter++)
901 iter->second->disconnected(
false);
906 std::vector<std::string> ArmarXManager::getDependendees(
const std::string& removedObject)
908 std::vector<std::string> result;
910 auto lock = acquireManagedObjectsMutex();
919 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
921 for (; it != managedObjects.end(); it++)
925 if (scheduler->dependsOn(removedObject))
927 result.push_back(it->first);
939 void ArmarXManager::wakeupWaitingSchedulers()
941 auto lock = acquireManagedObjectsMutex();
950 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
952 for (; it != managedObjects.end(); it++)
955 scheduler->wakeupDependencyCheck();
965 void ArmarXManager::removeAllObjects(
bool blocking)
967 ObjectSchedulerMap tempMap;
969 std::scoped_lock lock(managedObjectsMutex);
970 tempMap = managedObjects;
973 for (
auto& it : tempMap)
975 removeObject(it.second,
false);
980 for (
auto objectScheduler : terminatingObjects)
982 objectScheduler->waitForTermination();
986 terminatingObjects.clear();
994 if (!objectScheduler)
999 const std::string objName = objectScheduler->getObject()->getName();
1003 iceManager->removeObject(objName);
1005 std::scoped_lock lock2(managedObjectsMutex);
1006 managedObjects.erase(objectScheduler->getObject()->getName());
1009 objectScheduler->terminate();
1013 objectScheduler->waitForTermination();
1014 ARMARX_VERBOSE <<
"Blocking removal of ManagedIceObject " << objName <<
" finished";
1018 ARMARX_VERBOSE <<
"Inserting ManagedIceObject into delayed removal list: " << objName;
1019 std::scoped_lock lockTerm(terminatingObjectsMutex);
1020 terminatingObjects.push_back(objectScheduler);
1065 std::scoped_lock lock(managedObjectsMutex);
1066 auto it = managedObjects.find(objectName);
1067 if (it != managedObjects.end())
1077 void ArmarXManager::checkDependencies()
1081 auto lock = acquireManagedObjectsMutex();
1089 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
1091 for (; it != managedObjects.end(); it++)
1095 if (scheduler->getObjectState() == eManagedIceObjectStarted && !scheduler->checkDependenciesStatus())
1097 scheduler->disconnected(
true);
1111 std::scoped_lock lock(managerStateMutex);
1113 if (managerState >= eShutdownInProgress)
1124 void ArmarXManager::installProcessFacet()
1130 if (applicationCommunicator->findAdminFacet(
"Process"))
1132 applicationCommunicator->removeAdminFacet(
"Process");
1135 Ice::ProcessPtr applicationProcessFacet =
new ApplicationProcessFacet(*
this);
1136 applicationCommunicator->addAdminFacet(applicationProcessFacet,
"Process");
1140 Ice::ObjectPtr obj = applicationCommunicator->findAdminFacet(
"Properties");
1141 Ice::NativePropertiesAdminPtr admin = Ice::NativePropertiesAdminPtr::dynamicCast(obj);
1144 admin->addUpdateCallback(propertyChangeCallback);
1148 ARMARX_WARNING <<
"Could not get properties admin - online property changing will not work";
1152 applicationCommunicator->getAdmin();
1164 for (
const auto& id2factory : preregistration->getFactories())
1166 if (!
ic->getValueFactoryManager()->find(id2factory.first))
1169 ic->getValueFactoryManager()->add(id2factory.second, id2factory.first);
1183 return armarxManagerAdapter;
1188 return sharedRemoteHandleState;
1193 std::scoped_lock lock(schedulerListMutex);
1194 for (
int i = 0; i < increaseBy; ++i)
1203 static std::map<std::string, DynamicLibraryPtr> loadedLibs;
1204 static std::mutex libsMutex;
1205 std::lock_guard<std::mutex> guard {libsMutex};
1206 if (loadedLibs.count(path))
1221 if (lib->isLibraryLoaded())
1224 loadedLibs[path] = lib;
1228 ARMARX_ERROR <<
"Could not load lib " + path +
": " + lib->getErrorMessage();
1235 std::string absPath;
1248 ARMARX_ERROR <<
"Could not find package '" <<
package << "'";
1254 std::filesystem::path fullPath = libDirPath;
1256 if (!std::filesystem::exists(fullPath))
1258 fullPath = libDirPath;
1259 fullPath /= libname;
1260 if (!std::filesystem::exists(fullPath))
1270 ARMARX_ERROR <<
"Could not find library " << libname <<
" in package " << package;
1277 std::scoped_lock lock(managedObjectsMutex);
1278 StringStringDictionary propertyMap;
1279 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
1281 if (iter == managedObjects.end())
1286 return iter->second->getObject()->getMetaInfoMap();