From bf2332edcef7a78c9fdc9eaa2ee0b77eda1a9f7e Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Wed, 9 Sep 2015 15:17:29 +0900 Subject: [PATCH] Bundle isolation - use separate threads for activation The bundle activation is now triggered in a separate thread. If one bundle fails at activation other bundles can still succeed. When the resource container is started and the bundles are activated, the execution flow waits up to 10 secs to join the activators. If a bundle blocks its activation is not completed, but other bundles are not affected. Change-Id: Ie3f44639a4ae965941fcd1120497006830952987 Signed-off-by: Markus Jung Reviewed-on: https://gerrit.iotivity.org/gerrit/2417 Tested-by: jenkins-iotivity Reviewed-by: Madan Lanka --- extlibs/boost/SConscript | 7 +- .../src/resourceContainer/SConscript | 2 +- .../include/ResourceContainerImpl.h | 132 +++++++++++---------- .../src/resourceContainer/src/BundleResource.cpp | 1 - .../src/ResourceContainerImpl.cpp | 23 +++- .../unittests/ResourceContainerTest.cpp | 1 - 6 files changed, 96 insertions(+), 70 deletions(-) diff --git a/extlibs/boost/SConscript b/extlibs/boost/SConscript index 26f0c1e..c9fa5cf 100644 --- a/extlibs/boost/SConscript +++ b/extlibs/boost/SConscript @@ -4,7 +4,7 @@ Import('env') boost_env = env.Clone() -modules = ['thread','program_options'] +modules = ['thread','program_options', 'system', 'date_time'] target_os = env.get('TARGET_OS') target_arch = env.get('TARGET_ARCH') @@ -50,7 +50,10 @@ if 'android' == target_os : os.path.join(dep_src_dir, 'boost', 'config.hpp'), os.path.join(dep_src_dir, 'boost', 'variant.hpp'), os.path.join(dep_src_dir, 'boost', 'program_options.hpp'), - os.path.join(dep_src_dir, 'libboost_thread.a'), + os.path.join(dep_src_dir, 'boost', 'thread.hpp'), + os.path.join(dep_src_dir, 'boost', 'date_time.hpp'), + os.path.join(dep_src_dir, 'libboost_thread.a'), + os.path.join(dep_src_dir, 'libboost_date_time.a'), os.path.join(dep_src_dir, 'libboost_atomic.a'), os.path.join(dep_src_dir, 'libboost_system.a'), os.path.join(dep_src_dir, 'libboost_program_options.a') diff --git a/service/resource-encapsulation/src/resourceContainer/SConscript b/service/resource-encapsulation/src/resourceContainer/SConscript index dd24342..ac63569 100644 --- a/service/resource-encapsulation/src/resourceContainer/SConscript +++ b/service/resource-encapsulation/src/resourceContainer/SConscript @@ -102,7 +102,7 @@ except KeyError: resource_container_env.PrependUnique(LIBS = ['rcs_client', 'rcs_server', 'rcs_common', 'oc','octbstack', 'oc_logger', 'oc_logger_core', 'connectivity_abstraction']) -resource_container_env.AppendUnique(LIBS = ['dl']) +resource_container_env.AppendUnique(LIBS = ['dl', 'boost_system', 'boost_date_time', 'boost_thread']) if int(containerJavaSupport): try: diff --git a/service/resource-encapsulation/src/resourceContainer/include/ResourceContainerImpl.h b/service/resource-encapsulation/src/resourceContainer/include/ResourceContainerImpl.h index 78314f5..221f9d0 100644 --- a/service/resource-encapsulation/src/resourceContainer/include/ResourceContainerImpl.h +++ b/service/resource-encapsulation/src/resourceContainer/include/ResourceContainerImpl.h @@ -21,8 +21,6 @@ #ifndef RESOURCECONTAINERIMPL_H_ #define RESOURCECONTAINERIMPL_H_ - - #include "RCSResourceContainer.h" #include "ResourceContainerBundleAPI.h" #include "BundleInfoInternal.h" @@ -33,12 +31,17 @@ #include "DiscoverResourceUnit.h" +#include +#include + #if(JAVA_SUPPORT) - #include +#include #endif #include +#define BUNDLE_ACTIVATION_WAIT_SEC 10 + using namespace OIC::Service; namespace OIC @@ -48,84 +51,87 @@ namespace OIC class ResourceContainerImpl: public RCSResourceContainer, public ResourceContainerBundleAPI { - public: - ResourceContainerImpl(); - virtual ~ResourceContainerImpl(); - - // methods from ResourceContainer - void startContainer(const std::string &configFile); - void stopContainer(); - void activateBundle(RCSBundleInfo *bundleInfo); - void deactivateBundle(RCSBundleInfo *bundleInfo); - void activateBundle(const std::string &bundleId); - void deactivateBundle(const std::string &bundleId); - void registerBundle(RCSBundleInfo *bundleinfo); - void unregisterBundle(RCSBundleInfo *bundleinfo); - void unregisterBundleSo(const std::string &id); + public: + ResourceContainerImpl(); + virtual ~ResourceContainerImpl(); + // methods from ResourceContainer + void startContainer(const std::string &configFile); + void stopContainer(); + void activateBundle(RCSBundleInfo *bundleInfo); + void deactivateBundle(RCSBundleInfo *bundleInfo); + void activateBundle(const std::string &bundleId); + void deactivateBundle(const std::string &bundleId); + void registerBundle(RCSBundleInfo *bundleinfo); + void unregisterBundle(RCSBundleInfo *bundleinfo); + void unregisterBundleSo(const std::string &id); - // methods from ResourceContainerBundleAPI - void registerResource(BundleResource *resource); - void unregisterResource(BundleResource *resource); + // methods from ResourceContainerBundleAPI + void registerResource(BundleResource *resource); + void unregisterResource(BundleResource *resource); - void getBundleConfiguration(const std::string &bundleId, configInfo *configOutput); - void getResourceConfiguration(const std::string &bundleId, - std::vector< resourceInfo > *configOutput); + void getBundleConfiguration(const std::string &bundleId, configInfo *configOutput); + void getResourceConfiguration(const std::string &bundleId, + std::vector< resourceInfo > *configOutput); - RCSGetResponse getRequestHandler(const RCSRequest &request, - const RCSResourceAttributes &attributes); - RCSSetResponse setRequestHandler(const RCSRequest &request, - const RCSResourceAttributes &attributes); + RCSGetResponse getRequestHandler(const RCSRequest &request, + const RCSResourceAttributes &attributes); + RCSSetResponse setRequestHandler(const RCSRequest &request, + const RCSResourceAttributes &attributes); - void onNotificationReceived(const std::string &strResourceUri); + void onNotificationReceived(const std::string &strResourceUri); - static ResourceContainerImpl *getImplInstance(); - static RCSResourceObject::Ptr buildResourceObject(const std::string &strUri, const std::string &strResourceType); + static ResourceContainerImpl *getImplInstance(); + static RCSResourceObject::Ptr buildResourceObject(const std::string &strUri, + const std::string &strResourceType); - void startBundle(const std::string &bundleId); - void stopBundle(const std::string &bundleId); + void startBundle(const std::string &bundleId); + void stopBundle(const std::string &bundleId); - void addBundle(const std::string &bundleId, const std::string &bundleUri, const std::string &bundlePath, - std::map params); - void removeBundle(const std::string &bundleId); + void addBundle(const std::string &bundleId, const std::string &bundleUri, + const std::string &bundlePath, std::map< string, string > params); + void removeBundle(const std::string &bundleId); - std::list listBundles(); + std::list< RCSBundleInfo * > listBundles(); - void addResourceConfig(const std::string &bundleId, const std::string &resourceUri, std::map params); - void removeResourceConfig(const std::string &bundleId, const std::string &resourceUri); + void addResourceConfig(const std::string &bundleId, const std::string &resourceUri, + std::map< string, string > params); + void removeResourceConfig(const std::string &bundleId, const std::string &resourceUri); - std::list listBundleResources(const std::string &bundleId); + std::list< string > listBundleResources(const std::string &bundleId); #if(JAVA_SUPPORT) - JavaVM *getJavaVM(string bundleId); - void unregisterBundleJava(string id); + JavaVM *getJavaVM(string bundleId); + void unregisterBundleJava(string id); #endif - - private: - map< std::string, BundleInfoInternal * > m_bundles; // - map< std::string, RCSResourceObject::Ptr > m_mapServers; // - map< std::string, BundleResource * > m_mapResources; // - map< std::string, list > m_mapBundleResources; //> - map< std::string, list> - m_mapDiscoverResourceUnits; // - string m_configFile; - Configuration *m_config; - - void activateSoBundle(const std::string &bundleId); - void deactivateSoBundle(const std::string &bundleId); - void addSoBundleResource(const std::string &bundleId, resourceInfo newResourceInfo); - void removeSoBundleResource(const std::string &bundleId, const std::string &resourceUri); - void registerSoBundle(RCSBundleInfo *bundleInfo); - void discoverInputResource(const std::string & outputResourceUri); - void undiscoverInputResource(const std::string & outputResourceUri); + private: + map< std::string, BundleInfoInternal * > m_bundles; // + map< std::string, RCSResourceObject::Ptr > m_mapServers; // + map< std::string, BundleResource * > m_mapResources; // + map< std::string, list< string > > m_mapBundleResources; //> + map< std::string, list< DiscoverResourceUnit::Ptr > > m_mapDiscoverResourceUnits; // + string m_configFile; + Configuration *m_config; + vector< boost::thread > m_activators; // holds threads for bundle activation + std::mutex registrationLock; // used for synchronize the resource registration of multiple bundles + + void activateSoBundle(const std::string &bundleId); + void deactivateSoBundle(const std::string &bundleId); + void addSoBundleResource(const std::string &bundleId, resourceInfo newResourceInfo); + void removeSoBundleResource(const std::string &bundleId, + const std::string &resourceUri); + void registerSoBundle(RCSBundleInfo *bundleInfo); + void discoverInputResource(const std::string & outputResourceUri); + void undiscoverInputResource(const std::string & outputResourceUri); + void activateBundleThread(RCSBundleInfo *bundleInfo); #if(JAVA_SUPPORT) - map m_bundleVM; + map m_bundleVM; - void registerJavaBundle(RCSBundleInfo *bundleInfo); - void activateJavaBundle(string bundleId); - void deactivateJavaBundle(string bundleId); + void registerJavaBundle(RCSBundleInfo *bundleInfo); + void activateJavaBundle(string bundleId); + void deactivateJavaBundle(string bundleId); #endif diff --git a/service/resource-encapsulation/src/resourceContainer/src/BundleResource.cpp b/service/resource-encapsulation/src/resourceContainer/src/BundleResource.cpp index b74f9fc..0de792d 100644 --- a/service/resource-encapsulation/src/resourceContainer/src/BundleResource.cpp +++ b/service/resource-encapsulation/src/resourceContainer/src/BundleResource.cpp @@ -65,7 +65,6 @@ namespace OIC RCSResourceAttributes::Value BundleResource::getAttribute(const std::string &key) { - cout << "Bundle resource get attribute " << m_resourceAttributes.at(key).toString() << "|" << endl; return m_resourceAttributes.at(key); } diff --git a/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp b/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp index 88fc1ea..4e3bec1 100644 --- a/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp +++ b/service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp @@ -21,11 +21,13 @@ #include #include #include -#include #include #include #include #include +#include +#include + #include "ResourceContainerImpl.h" #include "BundleActivator.h" @@ -35,6 +37,7 @@ #include "oc_logger.hpp" #include "SoftSensorResource.h" + using OC::oc_log_stream; using namespace OIC::Service; @@ -126,7 +129,11 @@ namespace OIC info_logger() << "Init Bundle:" << bundles[i]["id"] << ";" << bundles[i]["path"] << endl; registerBundle(bundleInfo); - activateBundle(bundleInfo); + + auto f = std::bind(&ResourceContainerImpl::activateBundleThread, this, bundleInfo); + + boost::thread activator(f); + m_activators.push_back(std::move(activator)); } } else @@ -138,6 +145,11 @@ namespace OIC { info_logger() << "No configuration file for the container provided" << endl; } + vector::iterator activatorIterator; + + for(activatorIterator = m_activators.begin(); activatorIterator != m_activators.end(); activatorIterator++){ + activatorIterator->timed_join(boost::posix_time::seconds(BUNDLE_ACTIVATION_WAIT_SEC)); // wait for bundles to be activated + } } void ResourceContainerImpl::stopContainer() @@ -278,12 +290,14 @@ namespace OIC void ResourceContainerImpl::registerResource(BundleResource *resource) { + string strUri = resource->m_uri; string strResourceType = resource->m_resourceType; RCSResourceObject::Ptr server = nullptr; info_logger() << "Registration of resource " << strUri << "," << strResourceType << endl; + registrationLock.lock(); if (m_mapResources.find(strUri) == m_mapResources.end()) { server = buildResourceObject(strUri, strResourceType); @@ -317,6 +331,7 @@ namespace OIC { error_logger() << "resource with " << strUri << " already exists." << endl; } + registrationLock.unlock(); } void ResourceContainerImpl::unregisterResource(BundleResource *resource) @@ -766,6 +781,10 @@ namespace OIC } } + void ResourceContainerImpl::activateBundleThread(RCSBundleInfo* rcsBundleInfo){ + activateBundle(rcsBundleInfo); + } + #if(JAVA_SUPPORT) JavaVM *ResourceContainerImpl::getJavaVM(string bundleId) { diff --git a/service/resource-encapsulation/src/resourceContainer/unittests/ResourceContainerTest.cpp b/service/resource-encapsulation/src/resourceContainer/unittests/ResourceContainerTest.cpp index cbe1bcf..c1c8a66 100644 --- a/service/resource-encapsulation/src/resourceContainer/unittests/ResourceContainerTest.cpp +++ b/service/resource-encapsulation/src/resourceContainer/unittests/ResourceContainerTest.cpp @@ -112,7 +112,6 @@ class ResourceContainerTest: public TestWithMock TEST_F(ResourceContainerTest, BundleRegisteredWhenContainerStartedWithValidConfigFile) { m_pResourceContainer->startContainer(m_strConfigPath); - EXPECT_GT(m_pResourceContainer->listBundles().size(), (unsigned int) 0); EXPECT_STREQ("oic.bundle.test", (*m_pResourceContainer->listBundles().begin())->getID().c_str()); -- 2.7.4