42 #include <Ice/BuiltinSequences.h>
43 #include <Ice/Communicator.h>
44 #include <Ice/Identity.h>
45 #include <Ice/Initialize.h>
46 #include <Ice/LocalException.h>
47 #include <Ice/Metrics.h>
48 #include <Ice/NativePropertiesAdmin.h>
49 #include <Ice/ObjectAdapter.h>
50 #include <Ice/ObjectF.h>
51 #include <Ice/Properties.h>
52 #include <Ice/PropertiesF.h>
53 #include <Ice/Proxy.h>
54 #include <Ice/ProxyF.h>
55 #include <IceGrid/Admin.h>
56 #include <IceGrid/Registry.h>
57 #include <IceStorm/IceStorm.h>
58 #include <IceUtil/Handle.h>
67 #include "ArmarXCore/interface/core/BasicTypes.h"
68 #include "ArmarXCore/interface/core/Log.h"
69 #include "ArmarXCore/interface/core/ManagedIceObjectDefinitions.h"
70 #include "ArmarXCore/interface/core/ThreadingIceBase.h"
96 #define MANAGEROBJNAME applicationName + "Manager"
97 #define OBJOBSNAME std::string("ArmarXObjectObserver_") + applicationName
105 std::string locatorName,
106 Ice::StringSeq args) :
107 applicationName(applicationName), managerState(eCreated)
110 std::stringstream defaultLocator;
111 defaultLocator <<
"--Ice.Default.Locator=" << locatorName <<
":tcp -p " << port <<
" -h "
113 args.push_back(defaultLocator.str());
117 init(applicationName, communicator);
122 applicationName(applicationName), managerState(eCreated)
125 init(applicationName, communicator);
143 const std::string armarxHint =
"'\nDid you start armarx?\n\nTo start armarx: armarx start\n"
144 "To kill a hanging armarx: armarx killIce";
147 if (communicator->getProperties()->getProperty(
"Ice.Default.Locator").empty())
151 std::cerr <<
"Required Ice property 'Ice.Default.Locator' not set! "
152 <<
"It has to has a value similar to 'IceGrid/Locator:tcp -p 4061 -h "
157 auto locatorProp = communicator->getProperties()->getProperty(
"Ice.Default.Locator");
158 auto pos = locatorProp.find_first_of(
':');
159 std::string locatorId = locatorProp.substr(0, pos);
160 auto proxy = communicator->stringToProxy(locatorId);
161 IceGrid::LocatorPrx::checkedCast(proxy);
167 std::cerr <<
"Could not contact default locator at '"
168 << communicator->getProperties()->getProperty(
"Ice.Default.Locator")
176 std::string registryId =
"IceGrid/Registry";
177 auto proxy = communicator->stringToProxy(registryId);
178 IceGrid::RegistryPrx::checkedCast(proxy);
184 std::cerr <<
"Could not contact IceGrid registry at '"
185 << communicator->getProperties()->getProperty(
186 "IceGrid.Registry.Client.Endpoints")
196 catch (
const Ice::NoEndpointException& e)
198 std::cout <<
"Caught exception: \n" << e.what() << std::endl;
203 <<
"Could not contact TopicManager at '"
205 <<
"IceStorm/TopicManager"
249 bool addWithOwnAdapter,
250 const std::string& objectName,
251 bool useOwnScheduleThread)
256 useOwnScheduleThread);
261 const std::string& objectName,
262 bool addWithOwnAdapter,
263 bool useOwnScheduleThread)
265 addObject(
object, addWithOwnAdapter, objectName, useOwnScheduleThread);
271 const std::string& objectName,
272 bool useOwnScheduleThread)
276 throw LocalException(
"Cannot add NULL object");
279 auto cptr = ComponentPtr::dynamicCast(
object);
280 if (cptr && !cptr->createdByComponentCreate)
282 throw LocalException(
"Components need to be created by Component::create");
286 if (!objectName.empty())
288 if (!object->getName().empty())
290 ARMARX_INFO <<
"Adding object with custom name: " << objectName;
292 object->setName(objectName);
294 if (object->getName().empty())
296 object->setName(object->getDefaultName());
298 if (object->getName().empty())
300 throw LocalException(
"Object name must not be empty");
302 auto lock = acquireManagedObjectsMutex();
308 bool reachable =
false;
312 reachable =
getIceManager()->isObjectReachable(object->getName());
321 throw Ice::AlreadyRegisteredException(
322 __FILE__, __LINE__, object->ice_id(), object->getName());
328 this, iceManager,
object, objectAdapterToAddTo, useOwnScheduleThread);
329 auto pair = managedObjects.insert(
330 std::make_pair(object->getName(), std::move(objectScheduler)));
333 ARMARX_WARNING <<
"Insert of object scheduler in managedObjects failed since there "
334 "is already a scheduler for name "
335 <<
object->getName();
337 if (!useOwnScheduleThread)
339 std::scoped_lock lock(schedulerListMutex);
340 singleThreadedSchedulers.at(rand() % singleThreadedSchedulers.size())
341 ->addObjectScheduler(pair.first->second);
352 const std::string& objectName,
353 bool addWithOwnAdapter,
354 bool useOwnScheduleThread)
362 manager->addObject(
object, objectName, addWithOwnAdapter, useOwnScheduleThread);
378 auto lock = acquireManagedObjectsMutex();
383 scheduler = managedObjects.find(objectName)->second;
389 removeObject(scheduler,
true);
401 auto removal = [objectName,
this]()
405 auto lock = acquireManagedObjectsMutex();
410 scheduler = managedObjects.find(objectName)->second;
414 this->removeObject(scheduler,
false);
421 std::thread{removal}.detach();
443 managerStateMutex.lock();
445 if (managerState == eShutdown)
447 managerStateMutex.unlock();
452 std::unique_lock lock(shutdownMutex);
453 managerStateMutex.unlock();
454 shutdownCondition.wait(lock);
465 std::scoped_lock lock(managerStateMutex);
468 if (managerState >= eShutdownInProgress)
473 managerState = eShutdownInProgress;
476 managedObjectsMutex.lock();
482 cleanupSchedulersTask->stop();
484 if (checkDependencyStatusTask)
486 checkDependencyStatusTask->stop();
489 sharedRemoteHandleState.reset();
490 remoteReferenceCountControlBlockManager.reset();
492 disconnectAllObjects();
498 removeAllObjects(
true);
501 iceManager->getIceGridSession()->getAdmin()->removeObject(
508 singleThreadedSchedulers.clear();
513 iceManager->shutdown();
516 iceManager->waitForShutdown();
522 iceManager->destroy();
525 objObserver =
nullptr;
529 std::scoped_lock lock(managerStateMutex);
533 std::unique_lock lock(shutdownMutex);
535 shutdownCondition.notify_all();
538 managerState = eShutdown;
541 managedObjectsMutex.unlock();
543 catch (std::exception& e)
545 ARMARX_INFO <<
"shutdown failed with exception!\n" << e.what() << std::endl;
548 ARMARX_INFO <<
"Shutdown of ArmarXManager finished!" << std::endl;
554 std::thread{[
this, timeoutMs]
556 std::this_thread::sleep_for(std::chrono::milliseconds{timeoutMs});
565 std::scoped_lock lock(managerStateMutex);
566 return (managerState == eShutdown);
582 return iceManager->getCommunicator();
585 std::vector<ManagedIceObjectPtr>
588 std::vector<ManagedIceObjectPtr> objects;
590 auto lock = acquireManagedObjectsMutex();
596 ObjectSchedulerMap::iterator iter = managedObjects.begin();
598 while (iter != managedObjects.end())
600 objects.push_back(iter->second->getObject());
615 char hostname[HOST_NAME_MAX];
616 gethostname(hostname, HOST_NAME_MAX);
617 return std::string(hostname);
626 mice::MiceObjectConnectivity
629 mice::MiceObjectConnectivity miceCon = mice::MiceObjectConnectivity();
631 miceCon.subscribedTopics = con.usedTopics;
632 miceCon.publishedTopics = con.offeredTopics;
633 miceCon.usedObjects = Ice::StringSeq();
635 for (
const auto& entry : con.dependencies)
637 miceCon.usedObjects.push_back(entry.first);
643 IceMX::MetricsAdminPrx
646 Ice::ObjectPrx adminObj =
getIceManager()->getCommunicator()->getAdmin();
647 IceMX::MetricsAdminPrx metrAdmin = IceMX::MetricsAdminPrx::checkedCast(adminObj,
"Metrics");
654 ManagedIceObjectState
657 auto lock = acquireManagedObjectsMutex();
660 return eManagedIceObjectExiting;
663 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
665 if (iter == managedObjects.end())
667 return eManagedIceObjectExited;
670 ManagedIceObjectState state = (ManagedIceObjectState)iter->second->getObject()->getState();
675 ManagedIceObjectConnectivity
678 auto lock = acquireManagedObjectsMutex();
681 return ManagedIceObjectConnectivity();
684 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
686 if (iter == managedObjects.end())
688 return ManagedIceObjectConnectivity();
691 ManagedIceObjectConnectivity con = iter->second->getObject()->getConnectivity();
697 StringStringDictionary
700 StringStringDictionary propertyMap;
701 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
703 if (iter == managedObjects.end())
715 auto result =
component->getPropertyDefinitions()->getPropertyValues(
716 component->getPropertyDefinitions()->getPrefix());
723 ObjectPropertyInfos propertyMap;
724 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
726 if (iter == managedObjects.end())
739 for (
auto prop :
component->getPropertyDefinitions()->getPropertyValues())
741 propertyMap[
component->getPropertyDefinitions()->getPrefix() + prop.first] = {
742 component->getPropertyDefinitions()->getDefinitionBase(prop.first)->isConstant(),
751 ObjectPropertyInfos propertyMap;
760 ->getPropertyDefinitions()
761 ->getDefinitionBase(prop.first)
768 Ice::PropertiesAdminPrx
771 Ice::ObjectPrx adminObj =
getIceManager()->getCommunicator()->getAdmin();
772 Ice::PropertiesAdminPrx propAdmin =
773 Ice::PropertiesAdminPrx::checkedCast(adminObj,
"Properties");
798 component->updateIceProperties(properties);
806 Ice::StringSeq objectNames;
808 auto lock = acquireManagedObjectsMutex();
814 ObjectSchedulerMap::iterator iter = managedObjects.begin();
816 while (iter != managedObjects.end())
818 objectNames.push_back(iter->first);
834 updated(
const Ice::PropertyDict& changes)
override
839 application->updateIceProperties(changes);
864 appInstance ? appInstance->getProperty<std::string>(
"TopicSuffix").getValue() :
"");
869 throw Ice::ConnectFailedException(__FILE__, __LINE__);
872 this->installProcessFacet();
883 auto icegrid = iceManager->getIceGridSession();
887 Ice::ObjectPrx oPrx =
888 icegrid->registerObjectWithNewAdapter(objObserver, OBJOBSNAME, observerAdapter);
889 IceGrid::ObjectObserverPrx objObsPrx = IceGrid::ObjectObserverPrx::checkedCast(oPrx);
890 icegrid->setObjectObserver(objObsPrx);
893 icegrid->registerObjectWithNewAdapter(
this, MANAGEROBJNAME, armarxManagerAdapter);
898 &ArmarXManager::cleanupSchedulers,
901 "ArmarXManager::cleanupSchedulers");
902 cleanupSchedulersTask->start();
904 checkDependencyStatusTask =
906 &ArmarXManager::checkDependencies,
909 "ArmarXManager::DependenciesChecker");
910 checkDependencyStatusTask->start();
915 std::scoped_lock lock(managerStateMutex);
916 managerState = eRunning;
932 if (appInstance && appInstance->getProperty<
bool>(
"UseTimeServer").getValue())
936 applicationName +
"LocalTimeServer");
947 ? appInstance->getProperty<
unsigned int>(
"RemoteHandlesDeletionTimeout").getValue()
949 remoteReferenceCountControlBlockManager.reset(
954 ArmarXManager::cleanupSchedulers()
956 std::scoped_lock lock(terminatingObjectsMutex);
958 ObjectSchedulerList::iterator iter = terminatingObjects.begin();
960 while (iter != terminatingObjects.end())
964 <<
"Checking termination state of " << sched->getObject()->getName()
968 if ((*iter)->isTerminated())
971 << (*iter)->getObject()->getName() <<
" finished";
972 iter = terminatingObjects.erase(iter);
982 ArmarXManager::disconnectDependees(
const std::string&
object)
986 std::vector<std::string> dependees = getDependendees(
object);
988 auto lock = acquireManagedObjectsMutex();
994 for (
const auto& dependee : dependees)
996 ArmarXManager::ObjectSchedulerMap::iterator it = managedObjects.find(dependee);
998 <<
"' disconnected because of '" <<
object <<
"'";
1000 if (it != managedObjects.end())
1002 it->second->disconnected(
true);
1013 ArmarXManager::disconnectAllObjects()
1015 auto lock = acquireManagedObjectsMutex();
1020 ObjectSchedulerMap::iterator iter = managedObjects.begin();
1022 for (; iter != managedObjects.end(); iter++)
1024 iter->second->disconnected(
false);
1028 std::vector<std::string>
1029 ArmarXManager::getDependendees(
const std::string& removedObject)
1031 std::vector<std::string> result;
1033 auto lock = acquireManagedObjectsMutex();
1042 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
1044 for (; it != managedObjects.end(); it++)
1048 if (scheduler->dependsOn(removedObject))
1050 result.push_back(it->first);
1063 ArmarXManager::wakeupWaitingSchedulers()
1065 auto lock = acquireManagedObjectsMutex();
1074 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
1076 for (; it != managedObjects.end(); it++)
1079 scheduler->wakeupDependencyCheck();
1089 ArmarXManager::removeAllObjects(
bool blocking)
1091 ObjectSchedulerMap tempMap;
1093 std::scoped_lock lock(managedObjectsMutex);
1094 tempMap = managedObjects;
1097 for (
auto& it : tempMap)
1099 removeObject(it.second,
false);
1104 for (
auto objectScheduler : terminatingObjects)
1106 objectScheduler->waitForTermination();
1109 terminatingObjects.clear();
1116 if (!objectScheduler)
1121 const std::string objName = objectScheduler->getObject()->getName();
1125 iceManager->removeObject(objName);
1127 std::scoped_lock lock2(managedObjectsMutex);
1128 managedObjects.erase(objectScheduler->getObject()->getName());
1131 objectScheduler->terminate();
1135 objectScheduler->waitForTermination();
1136 ARMARX_VERBOSE <<
"Blocking removal of ManagedIceObject " << objName <<
" finished";
1140 ARMARX_VERBOSE <<
"Inserting ManagedIceObject into delayed removal list: "
1142 std::scoped_lock lockTerm(terminatingObjectsMutex);
1143 terminatingObjects.push_back(objectScheduler);
1150 ARMARX_ERROR <<
"Removing of object '" << objName <<
"' failed with an exception!\n"
1186 ArmarXManager::findObjectScheduler(
const std::string& objectName)
const
1188 std::scoped_lock lock(managedObjectsMutex);
1189 auto it = managedObjects.find(objectName);
1190 if (it != managedObjects.end())
1201 ArmarXManager::checkDependencies()
1205 auto lock = acquireManagedObjectsMutex();
1213 ObjectSchedulerMap::const_iterator it = managedObjects.begin();
1215 for (; it != managedObjects.end(); it++)
1219 if (scheduler->getObjectState() == eManagedIceObjectStarted &&
1220 !scheduler->checkDependenciesStatus())
1222 scheduler->disconnected(
true);
1236 std::scoped_lock lock(managerStateMutex);
1238 if (managerState >= eShutdownInProgress)
1245 new std::scoped_lock<std::recursive_mutex>(managedObjectsMutex));
1251 ArmarXManager::installProcessFacet()
1257 if (applicationCommunicator->findAdminFacet(
"Process"))
1259 applicationCommunicator->removeAdminFacet(
"Process");
1262 Ice::ProcessPtr applicationProcessFacet =
new ApplicationProcessFacet(*
this);
1263 applicationCommunicator->addAdminFacet(applicationProcessFacet,
"Process");
1266 new IcePropertyChangeCallback(appInstance);
1268 Ice::ObjectPtr obj = applicationCommunicator->findAdminFacet(
"Properties");
1269 Ice::NativePropertiesAdminPtr admin = Ice::NativePropertiesAdminPtr::dynamicCast(obj);
1272 admin->addUpdateCallback(propertyChangeCallback);
1277 <<
"Could not get properties admin - online property changing will not work";
1281 applicationCommunicator->getAdmin();
1295 for (
const auto& id2factory : preregistration->getFactories())
1297 if (!
ic->getValueFactoryManager()->find(id2factory.first))
1300 ic->getValueFactoryManager()->add(id2factory.second, id2factory.first);
1315 return armarxManagerAdapter;
1318 const std::shared_ptr<SharedRemoteHandleState>&
1321 return sharedRemoteHandleState;
1327 std::scoped_lock lock(schedulerListMutex);
1328 for (
int i = 0; i < increaseBy; ++i)
1338 static std::map<std::string, DynamicLibraryPtr> loadedLibs;
1339 static std::mutex libsMutex;
1340 std::lock_guard<std::mutex> guard{libsMutex};
1341 if (loadedLibs.count(path))
1356 if (lib->isLibraryLoaded())
1359 loadedLibs[path] = lib;
1363 ARMARX_ERROR <<
"Could not load lib " + path +
": " + lib->getErrorMessage();
1414 std::scoped_lock lock(managedObjectsMutex);
1415 StringStringDictionary propertyMap;
1416 ObjectSchedulerMap::iterator iter = managedObjects.find(objectName);
1418 if (iter == managedObjects.end())
1423 return iter->second->getObject()->getMetaInfoMap();