7 #include "fwServices/AppConfigManager.hpp" 9 #include "fwServices/helper/Config.hpp" 10 #include "fwServices/op/Get.hpp" 11 #include "fwServices/registry/ActiveWorkers.hpp" 12 #include "fwServices/registry/Proxy.hpp" 13 #include "fwServices/registry/ServiceConfig.hpp" 14 #include "fwServices/registry/ServiceFactory.hpp" 16 #include <fwCom/Slots.hpp> 17 #include <fwCom/Slots.hxx> 19 #define FW_PROFILING_DISABLED 20 #include <fwCore/Profiling.hpp> 22 #include <fwData/Composite.hpp> 23 #include <fwData/Object.hpp> 25 #include <fwRuntime/Bundle.hpp> 26 #include <fwRuntime/operations.hpp> 28 #include <boost/foreach.hpp> 29 #include <boost/thread/futures/wait_for_all.hpp> 36 static const ::fwCom::Slots::SlotKeyType s_ADD_OBJECTS_SLOT =
"addObject";
37 static const ::fwCom::Slots::SlotKeyType s_CHANGE_OBJECTS_SLOT =
"changeObject";
38 static const ::fwCom::Slots::SlotKeyType s_REMOVE_OBJECTS_SLOT =
"removeObjects";
46 newSlot(s_ADD_OBJECTS_SLOT, &AppConfigManager::addObjects,
this);
47 newSlot(s_REMOVE_OBJECTS_SLOT, &AppConfigManager::removeObjects,
this);
50 ::fwCom::HasSlots::m_slots.setWorker( defaultWorker );
57 SLM_ASSERT(
"Manager must be stopped before destruction.",
m_state == STATE_DESTROYED);
64 m_configId = configId;
72 m_configId = configId;
100 SLM_ERROR_IF(
"Bundle is not specified, it can not be started.", m_configId.empty());
101 if (!m_configId.empty() && !m_isUnitTest)
104 SLM_INFO_IF(
"Bundle '" + bundle->getIdentifier() +
"' (used for '" + m_configId +
"') is already started !",
105 bundle->isStarted());
106 if (!bundle->isStarted())
121 m_tmpRootObject = ::fwData::Composite::New();
123 m_addObjectConnection = ::fwServices::OSR::getRegisterSignal()->connect( this->slot(s_ADD_OBJECTS_SLOT) );
124 m_removeObjectConnection = ::fwServices::OSR::getUnregisterSignal()->connect( this->slot(s_REMOVE_OBJECTS_SLOT) );
127 this->createConnections();
139 this->processStartItems();
140 for(
auto& createdObject : m_createdObjects)
142 createdObject.second.second->startConfig();
152 this->processUpdateItems();
153 for(
auto& createdObject : m_createdObjects)
155 createdObject.second.second->updateConfig();
165 ::fwServices::OSR::getRegisterSignal()->disconnect( this->slot(s_ADD_OBJECTS_SLOT) );
166 ::fwServices::OSR::getUnregisterSignal()->disconnect( this->slot(s_REMOVE_OBJECTS_SLOT) );
169 this->destroyProxies();
171 for(
auto& createdObject : m_createdObjects)
173 createdObject.second.second->stopConfig();
175 this->stopStartedServices();
177 OSLM_INFO(
"Parsing OSR after stopping the config :" << std::endl
188 for(
auto& createdObject : m_createdObjects)
190 createdObject.second.second->destroyConfig();
192 this->destroyCreatedServices();
194 OSLM_INFO(
"Parsing OSR after destroying the config :" << std::endl
198 m_createdObjects.clear();
199 m_deferredObjects.clear();
200 m_deferredServices.clear();
201 m_deferredStartSrv.clear();
202 m_deferredUpdateSrv.clear();
203 m_servicesProxies.clear();
212 m_isUnitTest = isUnitTest;
219 if (m_createdObjects.empty())
221 return m_tmpRootObject;
223 return m_createdObjects.begin()->second.first;
228 fwData::Object::sptr AppConfigManager::findObject(
const std::string& uid,
const std::string& errMsgTail)
const 230 ::fwData::Object::sptr obj;
233 auto it = m_createdObjects.find(uid);
234 if(it != m_createdObjects.end())
236 obj = it->second.first;
241 auto itDeferredObj = m_deferredObjects.find(uid);
243 SLM_ASSERT(this->msgHead() +
"Object '" + uid +
"' has not been found" + errMsgTail,
244 itDeferredObj != m_deferredObjects.end());
245 obj = itDeferredObj->second.m_object;
252 ::fwData::Object::sptr AppConfigManager::getNewObject(ConfigAttribute type, ConfigAttribute uid)
const 258 const std::string className = ::fwCore::getClassname< ::fwData::Object >();
259 SLM_ASSERT(
"Extension and classname are different.",
260 ext->getPoint() == className);
263 ext->getBundle()->start();
266 ::fwData::Object::sptr obj = ::fwData::factory::New(type.first);
267 SLM_ASSERT(
"Factory failed to build object : " + type.first, obj);
271 SLM_ASSERT(
"Object already has an UID.", !obj->hasID());
273 obj->setID(uid.first);
281 ::fwData::Object::sptr AppConfigManager::getNewObject(ConfigAttribute type,
const std::string& uid)
const 283 return this->getNewObject(type, ConfigAttribute(uid,
true));
288 ::fwData::Object::sptr AppConfigManager::getObject(ConfigAttribute type,
const std::string& uid)
const 293 SLM_ASSERT(this->msgHead() +
"The UID '" + uid +
"' does not reference any object.", obj);
297 SLM_ASSERT(this->msgHead() +
"Object with UID \"" + uid +
298 "\" has a different type (\"" + obj->getClassname() +
"\" != \"" + type.first +
"\").",
299 type.first == obj->getClassname());
306 ::fwServices::IService::sptr AppConfigManager::getNewService(
const std::string& uid,
const std::string& implType)
const 310 ::fwServices::IService::sptr srv = srvFactory->create(implType);
312 SLM_ASSERT(
"Factory could not create service of type <" + implType +
">.", srv);
313 SLM_ASSERT(
"Service already has an UID.", !srv->hasID());
326 void AppConfigManager::stopStartedServices()
328 std::vector< ::fwServices::IService::SharedFutureType > futures;
330 BOOST_REVERSE_FOREACH(::fwServices::IService::wptr w_srv, m_startedSrv)
332 SLM_ASSERT(
"Service expired.", !w_srv.expired());
334 const ::fwServices::IService::sptr srv = w_srv.lock();
335 OSLM_ASSERT(
"Service " << srv->getID() <<
" already stopped.", !srv->isStopped());
336 futures.emplace_back(srv->stop());
338 m_startedSrv.clear();
339 std::for_each(futures.begin(), futures.end(), std::mem_fn(&::std::shared_future<void>::wait));
344 void AppConfigManager::destroyCreatedServices()
346 BOOST_REVERSE_FOREACH(::fwServices::IService::wptr w_srv, m_createdSrv)
348 SLM_ASSERT(
"Service expired.", !w_srv.expired());
350 const ::fwServices::IService::sptr srv = w_srv.lock();
351 OSLM_ASSERT(
"Service " << srv->getID() <<
" must be stopped before destruction.", srv->isStopped());
352 ::fwServices::OSR::unregisterService(srv);
354 m_createdSrv.clear();
359 void AppConfigManager::processStartItems()
361 std::vector< ::fwServices::IService::SharedFutureType > futures;
363 for(
const auto& elem :
m_cfgElem->getElements())
365 if (elem->getName() ==
"start")
367 SLM_ASSERT(
"Missing attribute \"uid\".", elem->hasAttribute(
"uid"));
368 const std::string uid = elem->getAttributeValue(
"uid");
369 SLM_ASSERT(
"\"uid\" attribute is empty.", !uid.empty());
373 if(m_deferredServices.find(uid) != m_deferredServices.end())
375 m_deferredStartSrv.push_back(uid);
376 SLM_INFO( this->msgHead() +
"Start for service '" + uid +
"' will be deferred since at least one " 377 "of its data is missing. With DEBUG log level, you can know which are the " 382 SLM_FATAL( this->msgHead() +
"Start is requested for service '" + uid +
383 "', but it does not exist.");
388 const ::fwServices::IService::sptr srv = ::fwServices::get(uid);
389 SLM_FATAL_IF( this->msgHead() +
"Start is requested for service '" + uid +
"', though this identifier " 390 "exists, this is not a service.", !srv);
392 futures.emplace_back(srv->start());
394 m_startedSrv.push_back(srv);
400 std::for_each(futures.begin(), futures.end(), std::mem_fn(&::std::shared_future<void>::wait));
405 void AppConfigManager::processUpdateItems()
407 std::vector< ::fwServices::IService::SharedFutureType > futures;
409 for(
const auto& elem :
m_cfgElem->getElements())
411 if (elem->getName() ==
"update")
413 const std::string uid = elem->getAttributeValue(
"uid");
414 SLM_ASSERT(
"\"uid\" attribute is empty.", !uid.empty());
418 if(m_deferredServices.find(uid) != m_deferredServices.end())
420 m_deferredUpdateSrv.push_back(uid);
421 SLM_INFO( this->msgHead() +
"Update for service '" + uid +
"'will be deferred since at least one " 422 "of its data is missing. With DEBUG log level, you can know which are the " 427 SLM_FATAL( this->msgHead() +
"Update is requested for service '" + uid +
428 "', but it does not exist.");
433 const ::fwServices::IService::sptr srv = ::fwServices::get(uid);
434 SLM_FATAL_IF( this->msgHead() +
"Update is requested for service '" + uid +
435 "', though this identifier exists, this is not a service.", !srv);
437 futures.emplace_back(srv->update());
442 std::for_each(futures.begin(), futures.end(), std::mem_fn(&::std::shared_future<void>::wait));
447 void AppConfigManager::createObjects(::fwRuntime::ConfigurationElement::csptr cfgElem)
449 for(
const auto& elem : cfgElem->getElements())
451 if (elem->getName() ==
"object")
456 ConfigAttribute id(
"",
false);
457 if (elem->hasAttribute(
"uid"))
459 id.first = elem->getAttributeValue(
"uid");
460 SLM_ASSERT(this->msgHead() +
"\"uid\" attribute is empty.", !
id.first.empty());
465 ConfigAttribute type(
"",
false);
466 if (elem->hasAttribute(
"type"))
468 type.first = elem->getAttributeValue(
"type");
469 SLM_ASSERT(this->msgHead() +
"\"type\" attribute is empty.", !type.first.empty());
470 SLM_ASSERT(this->msgHead() +
"\"type\" must be a rooted namespace.", type.first.substr(0, 2) ==
"::");
475 ConfigAttribute buildMode(
"",
false);
476 if (elem->hasAttribute(
"src"))
478 buildMode.first = elem->getAttributeValue(
"src");
479 SLM_ASSERT(
"this->msgHead() + \"src\" attribute is empty.", !buildMode.first.empty());
481 SLM_ASSERT(
"Unhandled build mode (bad \"src\" attribute). Must be \"new\", \"deferred\" or \"ref\".",
482 buildMode.first ==
"ref" || buildMode.first ==
"src" || buildMode.first ==
"deferred");
483 buildMode.second =
true;
486 if(buildMode.first ==
"deferred")
488 SLM_ASSERT(this->msgHead() +
"Missing attribute \"id\".",
id.second);
489 auto ret = m_deferredObjects.insert( std::make_pair(
id.first, DeferredObjectType()));
490 SLM_ASSERT(this->msgHead() +
"Object '" +
id.first +
"' already exists in this config.", ret.second);
495 ::fwData::Object::sptr obj;
498 if (buildMode.second && buildMode.first ==
"ref")
500 SLM_ASSERT(this->msgHead() +
"Missing attribute \"id\".",
id.second);
501 obj = this->getObject(type,
id.first);
505 obj = this->getNewObject(type,
id);
511 std::string srvImpl = srvFactory->getDefaultImplementationIdFromObjectAndType(
512 obj->getClassname(),
"::fwServices::IXMLParser");
514 ::fwServices::IService::sptr srv = srvFactory->create(
"::fwServices::IXMLParser", srvImpl);
515 auto objectParser = ::fwServices::IXMLParser::dynamicCast(srv);
516 objectParser->setObjectConfig(elem);
517 objectParser->createConfig(obj);
519 m_createdObjects[
id.first] = std::make_pair( obj, objectParser);
527 void AppConfigManager::createServices(::fwRuntime::ConfigurationElement::csptr cfgElem)
529 for(
const auto& elem : cfgElem->getElements())
531 if (elem->getName() ==
"service")
537 bool createService =
true;
538 std::vector<std::string> uids;
540 for(
const auto& objectCfg : srvConfig.m_objects)
544 auto it = m_deferredObjects.find(objectCfg.m_uid);
545 if(it != m_deferredObjects.end())
547 it->second.m_servicesCfg.emplace_back(srvConfig);
548 uids.push_back(objectCfg.m_uid);
549 m_deferredServices.insert(srvConfig.m_uid);
551 if(!objectCfg.m_optional)
553 createService =
false;
559 this->msgHead() +
"Object '" + objectCfg.m_uid +
"' is not deferred but it is used " 560 "as an optional key in service '" + srvConfig.m_uid +
"'. This is useless, so maybe you " 561 "intended to use a deferred object instead ?", objectCfg.m_optional);
565 if(objectCfg.m_access == ::fwServices::IService::AccessType::OUTPUT)
567 SLM_ERROR_IF(this->msgHead() +
"Object '" + objectCfg.m_uid +
"' is used as output in service '" +
568 srvConfig.m_uid +
"' but it not declared as 'deferred'.",
569 it == m_deferredObjects.end());
575 this->createService(srvConfig);
580 SLM_ASSERT(this->msgHead() +
"UID " + srvConfig.m_uid +
" already exists.",
583 const std::string msg = AppConfigManager::getUIDListAsString(uids);
584 SLM_INFO(this->msgHead() +
"Service '" + srvConfig.m_uid +
585 "' has not been created because the object" + msg +
"not available.");
588 else if (elem->getName() ==
"serviceList")
590 this->createServices(elem);
597 ::fwServices::IService::sptr AppConfigManager::createService(const ::fwServices::IService::Config& srvConfig)
600 const ::fwServices::IService::sptr srv = this->getNewService(srvConfig.m_uid, srvConfig.m_type);
601 m_createdSrv.push_back(srv);
603 if (!srvConfig.m_worker.empty())
606 ::fwThread::Worker::sptr worker;
607 worker = activeWorkers->getWorker(srvConfig.m_worker);
610 worker = ::fwThread::Worker::New();
611 activeWorkers->addWorker(srvConfig.m_worker, worker);
613 srv->setWorker(worker);
616 std::string errMsgTail =
" when creating service '" + srvConfig.m_uid +
"'.";
618 for(
const auto& objectCfg : srvConfig.m_objects)
620 srv->setObjectId(objectCfg.m_key, objectCfg.m_uid);
622 ::fwData::Object::sptr obj = this->findObject(objectCfg.m_uid, errMsgTail);
624 SLM_ASSERT(this->msgHead() +
"Object '" + objectCfg.m_uid +
"' has not been found" + errMsgTail,
625 (!objectCfg.m_optional && obj) || objectCfg.m_optional);
626 if((obj || !objectCfg.m_optional) && objectCfg.m_access != ::fwServices::IService::AccessType::OUTPUT)
628 ::fwServices::OSR::registerService(obj, objectCfg.m_key, objectCfg.m_access, srv);
639 ::fwServices::IService::AccessType::INOUT, srv);
643 srv->m_keyGroupSize = srvConfig.m_groupSize;
646 const auto& itSrvProxy = m_servicesProxies.find(srvConfig.m_uid);
647 if(itSrvProxy != m_servicesProxies.end())
649 for(
const auto& itProxy : itSrvProxy->second.m_proxyCnt)
651 srv->addProxyConnection(itProxy.second);
656 srv->setConfiguration(srvConfig);
664 void AppConfigManager::createConnections()
666 for(
const auto& elem :
m_cfgElem->getElements())
668 if (elem->getName() ==
"connect")
671 auto genIdFn = [
this]()
673 return "Proxy_" + this->
getID() +
"_" + std::to_string(m_proxyID++);
682 for(
const auto& signalInfo : connectionInfos.m_signals)
684 auto itDeferredObj = m_deferredObjects.find(signalInfo.first);
685 if( itDeferredObj != m_deferredObjects.end() )
688 ProxyConnections& proxy = itDeferredObj->second.m_proxyCnt[connectionInfos.m_channel];
689 proxy.addSignalConnection(signalInfo);
693 auto itObj = m_createdObjects.find(signalInfo.first);
694 if( itObj != m_createdObjects.end() )
697 createdObjectsProxy.addSignalConnection(signalInfo);
702 auto& itSrv = m_servicesProxies[signalInfo.first];
704 proxy.addSignalConnection(signalInfo);
705 proxy.m_channel = connectionInfos.m_channel;
711 for(
const auto& slotInfo : connectionInfos.m_slots)
713 auto itDeferredObj = m_deferredObjects.find(slotInfo.first);
714 if( itDeferredObj != m_deferredObjects.end() )
717 ProxyConnections& proxy = itDeferredObj->second.m_proxyCnt[connectionInfos.m_channel];
718 proxy.addSlotConnection(slotInfo);
722 auto itObj = m_createdObjects.find(slotInfo.first);
723 if( itObj != m_createdObjects.end() )
726 createdObjectsProxy.addSlotConnection(slotInfo);
731 auto& itSrv = m_servicesProxies[slotInfo.first];
733 proxy.addSlotConnection(slotInfo);
734 proxy.m_channel = connectionInfos.m_channel;
739 m_createdObjectsProxies[connectionInfos.m_channel] = createdObjectsProxy;
740 this->connectProxy(connectionInfos.m_channel, createdObjectsProxy);
747 void AppConfigManager::destroyProxy(
const std::string& channel,
const ProxyConnections& proxyCfg,
748 const std::string& key, ::fwData::Object::csptr hintObj)
752 for(
const ProxyConnections::ProxyEltType& signalElt : proxyCfg.m_signals)
754 if(key.empty() || signalElt.first == key)
756 ::fwTools::Object::csptr obj = hintObj;
761 ::fwCom::HasSignals::csptr hasSignals = std::dynamic_pointer_cast< const ::fwCom::HasSignals >(obj);
762 SLM_ASSERT(this->msgHead() +
"Signal source not found '" + signalElt.first +
"'", obj);
764 ::fwCom::SignalBase::sptr sig = hasSignals->signal(signalElt.second);
768 proxy->disconnect(channel, sig);
770 catch (
const std::exception& e)
772 SLM_ERROR(
"Signal '" + signalElt.second +
"' from '" + signalElt.first +
"' can not be disconnected " 773 "from the channel '" + channel +
"': " + std::string(e.what()));
777 for(
const ProxyConnections::ProxyEltType& slotElt : proxyCfg.m_slots)
779 if(key.empty() || slotElt.first == key)
782 ::fwCom::HasSlots::sptr hasSlots = std::dynamic_pointer_cast<
::fwCom::HasSlots >(obj);
783 SLM_ASSERT(this->msgHead() +
"Slot destination not found '" + slotElt.first +
"'", hasSlots);
785 ::fwCom::SlotBase::sptr slot = hasSlots->slot(slotElt.second);
789 proxy->disconnect(channel, slot);
791 catch (
const std::exception& e)
793 SLM_ERROR(
"Slot '" + slotElt.second +
"' from '" + slotElt.first +
"' can not be disconnected from the " 794 "channel '" + channel +
"': " + std::string(e.what()));
802 void AppConfigManager::destroyProxies()
805 for(
auto& itDeferredObj : m_deferredObjects)
807 if(itDeferredObj.second.m_object)
809 for(
const auto& itProxy : itDeferredObj.second.m_proxyCnt)
811 this->destroyProxy(itProxy.first, itProxy.second, itDeferredObj.first, itDeferredObj.second.m_object);
813 itDeferredObj.second.m_object.reset();
818 for(
const auto& itProxy : m_createdObjectsProxies)
820 this->destroyProxy(itProxy.first, itProxy.second);
823 m_createdObjectsProxies.clear();
828 void AppConfigManager::addObjects(fwData::Object::sptr obj,
const std::string&
id)
830 FW_PROFILE(
"addObjects");
833 std::map< std::string, const ServiceConfig* > servicesMapCfg;
837 std::vector< const ServiceConfig* > servicesCfg;
840 auto itDeferredObj = m_deferredObjects.find(
id);
841 if(itDeferredObj != m_deferredObjects.end())
844 for(
const auto& srvCfg : itDeferredObj->second.m_servicesCfg)
846 if(servicesMapCfg.find(srvCfg.m_uid) == servicesMapCfg.end())
848 servicesMapCfg[srvCfg.m_uid] = &srvCfg;
849 servicesCfg.push_back(&srvCfg);
854 itDeferredObj->second.m_object = obj;
856 for(
const auto& connectCfg : itDeferredObj->second.m_proxyCnt)
858 this->connectProxy(connectCfg.first, connectCfg.second);
862 std::unordered_map<std::string, ::fwServices::IService::sptr> newServices;
864 for(
const auto& itService : servicesCfg)
866 auto srvCfg = itService;
868 auto& uid = srvCfg->m_uid;
870 bool createService =
true;
873 for(
const auto& objCfg : srvCfg->m_objects)
876 if(m_createdObjects.find(objCfg.m_uid) == m_createdObjects.end())
879 const auto itDeferredObj = m_deferredObjects.find(objCfg.m_uid);
880 SLM_ASSERT( this->msgHead() +
"Object '" + objCfg.m_uid +
"' used by service '" + uid +
881 "' has not been declared in this AppConfig.",
882 itDeferredObj != m_deferredObjects.end());
884 const auto object = itDeferredObj->second.m_object;
885 if(
object ==
nullptr)
887 if(!objCfg.m_optional)
889 createService =
false;
891 SLM_INFO( this->msgHead() +
"Service '" + uid +
"' has not been created because the " 892 "object" + objCfg.m_uid +
" is not available.");
897 ::fwServices::IService::sptr srv = ::fwServices::get(uid);
898 SLM_ASSERT(this->msgHead() +
"No service registered with UID \"" + uid +
"\".", srv);
901 if( objCfg.m_optional)
904 auto registeredObj = ::fwServices::OSR::getRegistered(objCfg.m_key, objCfg.m_access, srv);
905 if(registeredObj !=
nullptr)
908 if(registeredObj !=
object)
910 ::fwServices::OSR::unregisterService(objCfg.m_key, objCfg.m_access, srv);
914 if(registeredObj !=
object)
917 ::fwServices::OSR::registerService(
object, objCfg.m_key, objCfg.m_access, srv);
920 srv->swapKey(objCfg.m_key, ::fwData::Object::constCast(registeredObj)).wait();
924 createService =
false;
933 newServices.emplace(std::make_pair(uid, this->createService(*srvCfg)));
936 SLM_INFO( this->msgHead() +
"Service '" + uid +
"' has been automatically created because its " 937 "objects are all available.");
941 std::vector< ::fwServices::IService::SharedFutureType > futures;
944 for(
const auto& uid : m_deferredStartSrv)
946 auto itSrv = newServices.find(uid);
947 if( itSrv != newServices.end())
949 futures.push_back(itSrv->second->start());
950 m_startedSrv.push_back(itSrv->second);
953 SLM_INFO( this->msgHead() +
"Service '" + uid +
"' has been automatically started because its " 954 "objects are all available.");
958 ::boost::wait_for_all(futures.begin(), futures.end());
962 for(
const auto& uid : m_deferredUpdateSrv)
964 auto itSrv = newServices.find(uid);
965 if( itSrv != newServices.end())
967 futures.push_back(itSrv->second->update());
970 SLM_INFO( this->msgHead() +
"Service '" + uid +
"' has been automatically update because its " 971 "objects are all available.");
975 ::boost::wait_for_all(futures.begin(), futures.end());
980 void AppConfigManager::removeObjects(fwData::Object::sptr obj,
const std::string&
id)
982 FW_PROFILE(
"removeObjects");
985 const auto itDeferredObj = m_deferredObjects.find(
id);
986 if(itDeferredObj != m_deferredObjects.end())
988 for(
const auto& itProxy : itDeferredObj->second.m_proxyCnt)
990 this->destroyProxy(itProxy.first, itProxy.second,
id, itDeferredObj->second.m_object);
993 itDeferredObj->second.m_object.reset();
996 for(
const auto& srvCfg : itDeferredObj->second.m_servicesCfg)
1001 bool optional =
true;
1003 for(
const auto& objCfg : srvCfg.m_objects)
1005 if(
id == objCfg.m_uid)
1007 ::fwServices::IService::sptr srv = ::fwServices::get(srvCfg.m_uid);
1008 OSLM_ASSERT(
"No service registered with UID \"" << srvCfg.m_uid <<
"\".", srv);
1010 if(objCfg.m_optional)
1014 ::fwServices::OSR::unregisterService(objCfg.m_key, objCfg.m_access, srv);
1016 srv->swapKey(objCfg.m_key, obj).wait();
1029 ::fwServices::IService::sptr srv = ::fwServices::get(srvCfg.m_uid);
1030 OSLM_ASSERT(this->msgHead() +
"No service registered with UID \"" << srvCfg.m_uid <<
"\".", srv);
1032 OSLM_ASSERT(
"Service " << srv->getID() <<
" already stopped.", !srv->isStopped());
1035 for(
auto it = m_startedSrv.begin(); it != m_startedSrv.end(); ++it)
1037 if(it->lock() == srv)
1039 m_startedSrv.erase(it);
1045 OSLM_ASSERT(
"Service " << srv->getID() <<
" must be stopped before destruction.",
1047 ::fwServices::OSR::unregisterService(srv);
1049 for(
auto it = m_createdSrv.begin(); it != m_createdSrv.end(); ++it)
1051 if(it->lock() == srv)
1053 m_createdSrv.erase(it);
1058 ::fwServices::IService::wptr checkSrv = srv;
1061 SLM_ASSERT( this->msgHead() +
"The service '" + srvCfg.m_uid +
1062 "'' should have been destroyed, but someone " 1063 "still holds a reference which prevents to destroy it properly.",
1064 checkSrv.expired());
1066 SLM_INFO( this->msgHead() +
"Service '" + srvCfg.m_uid +
1067 "' has been stopped because the object " +
1068 id +
" is no longer available.");
1073 ::fwServices::IService::sptr srv = ::fwServices::get(srvCfg.m_uid);
1074 OSLM_ASSERT(this->msgHead() +
"No service registered with UID \"" << srvCfg.m_uid <<
"\".", srv);
1076 srv->autoDisconnect();
1086 void AppConfigManager::connectProxy(
const std::string& channel,
const ProxyConnections& connectCfg)
1090 for(
const auto& signalCfg : connectCfg.m_signals)
1093 if(sigSource ==
nullptr)
1096 auto itDeferredObj = m_deferredObjects.find(signalCfg.first);
1097 SLM_ASSERT( this->msgHead() +
"Object '" + signalCfg.first +
"' not found.",
1098 itDeferredObj != m_deferredObjects.end());
1100 sigSource = itDeferredObj->second.m_object;
1102 ::fwCom::HasSignals::sptr hasSignals = std::dynamic_pointer_cast<
::fwCom::HasSignals >(sigSource);
1103 SLM_ASSERT(this->msgHead() +
"Signal source not found '" + signalCfg.first +
"'", hasSignals);
1105 ::fwCom::SignalBase::sptr sig = hasSignals->signal(signalCfg.second);
1106 SLM_ASSERT(
"Signal '" + signalCfg.second +
"' not found in source '" + signalCfg.first +
"'.", sig);
1110 proxy->connect(channel, sig);
1112 catch (
const std::exception& e)
1114 SLM_ERROR(
"Signal '" + signalCfg.second +
"' from '" + signalCfg.first +
"' can not be connected to the " 1115 "channel '" + channel +
"': " + std::string(e.what()));
1119 for(
const auto& slotCfg : connectCfg.m_slots)
1122 ::fwCom::HasSlots::sptr hasSlots = std::dynamic_pointer_cast<
::fwCom::HasSlots >(slotDest);
1123 SLM_ASSERT(this->msgHead() +
"Slot destination not found '" + slotCfg.first +
"'", hasSlots);
1125 ::fwCom::SlotBase::sptr slot = hasSlots->slot(slotCfg.second);
1126 SLM_ASSERT(
"Slot '" + slotCfg.second +
"' not found in source '" + slotCfg.first +
"'.", slot);
1130 proxy->connect(channel, slot);
1132 catch (
const std::exception& e)
1134 SLM_ERROR(
"Slot '" + slotCfg.second +
"' from '" + slotCfg.first +
"' can not be connected to the " 1135 "channel '" + channel +
"': " + std::string(e.what()));
1142 std::string AppConfigManager::getUIDListAsString(
const std::vector<std::string>& uidList)
1144 std::string msg = uidList.size() == 1 ?
" '" :
"s '";
1146 for(
auto it = uidList.begin() + 1; it < uidList.end(); ++it)
1148 msg +=
"', '" + *it;
1150 msg = uidList.size() == 1 ? msg +
"' is " : msg +
"' are ";
virtual FWSERVICES_API void launch() override
Calls methods : create, start then update.
static FWSERVICES_API const std::string s_DEFAULT_OBJECT
FWSERVICES_API AppConfigManager()
Constructor. Do nothing.
#define OSLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
static FWSERVICES_API::fwServices::IService::Config parseService(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &srvElem, const std::string &errMsgHead)
Parse a service and return a service configuration.
Defines the extension class.
static FWSERVICES_API Proxy::sptr getDefault()
Returns an instance of Proxy.
::fwRuntime::ConfigurationElement::csptr m_cfgElem
XML Configuration tree.
virtual FWSERVICES_API void destroy() override
Destroys services specified in config.
Namespace fwServices is dedicated to (mimic) the dynamic affectation of methods to (pure data) object...
This class proposes a mapping between a SlotKeyType and a SlotBase.
virtual FWSERVICES_API void stopAndDestroy() override
Stops and destroys services specified in config, then resets the configRoot sptr. ...
#define OSLM_INFO(message)
virtual FWSERVICES_API void update() override
Updates services specified in config.
FWSERVICES_API std::string getRegistryInformation()
Wraps ObjectService::getRegistryInformation.
virtual FWSERVICES_API void setConfig(const std::string &configId, const FieldAdaptorType &replaceFields=FieldAdaptorType()) override
Set configuration.
virtual FWSERVICES_API::fwData::Object::sptr getConfigRoot() const override
Get config root.
#define SLM_ERROR(message)
virtual FWSERVICES_API void create() override
Creates objects and services from config.
#define SLM_FATAL(message)
virtual FWSERVICES_API void start() override
Starts services specified in config.
#define SLM_INFO_IF(message, cond)
#define SLM_ERROR_IF(message, cond)
static FWSERVICES_API ActiveWorkers::sptr getDefault()
Returns an instance of ActiveWorkers.
#define SLM_ASSERT(message, cond)
work like 'assert' from 'cassert', with in addition a message logged by spylog (with FATAL loglevel) ...
Helper class to register proxy connections.
virtual FWSERVICES_API void startBundle()
Starts the bundle associated to the config.
#define SLM_FATAL_IF(message, cond)
static FWSERVICES_API::fwThread::Worker::sptr getDefaultWorker()
Get the default registered worker.
virtual FWSERVICES_API ~AppConfigManager()
Destructor. Do nothing.
FWSERVICES_API void setIsUnitTest(bool isUnitTest)
Set it to true if we are testing the class.
static FWSERVICES_API AppConfig::sptr getDefault()
Return an instance of AppConfig.
static FWSERVICES_API ServiceFactory::sptr getDefault()
Return the unique Instance, create it if required at first access.
#define SLM_INFO(message)
FWSERVICES_API bool isRegistered(const ::fwServices::IService::KeyType &objKey,::fwServices::IService::AccessType access,::fwServices::IService::sptr service)
Return true if a key is registered for a given service.
static FWSERVICES_API ProxyConnections parseConnections2(const std::shared_ptr< const ::fwRuntime::ConfigurationElement > &connectionCfg, const std::string &errMsgHead, std::function< std::string()> generateChannelNameFn)
Parses "<connect>" tags from given configuration and return a structure containing the signal and slo...
Used to store a service configuration.
This class proposes a mapping between a SignalKeyType and a SignalBase.
ConfigState m_state
Running state of the app config manager.
virtual FWSERVICES_API void stop() override
Stops services specified in config.