Bundle isolation - use separate threads for activation
authorMarkus Jung <markus.jung@samsung.com>
Wed, 9 Sep 2015 06:17:29 +0000 (15:17 +0900)
committerMadan Lanka <lanka.madan@samsung.com>
Fri, 11 Sep 2015 02:30:39 +0000 (02:30 +0000)
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 <markus.jung@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2417
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
extlibs/boost/SConscript
service/resource-encapsulation/src/resourceContainer/SConscript
service/resource-encapsulation/src/resourceContainer/include/ResourceContainerImpl.h
service/resource-encapsulation/src/resourceContainer/src/BundleResource.cpp
service/resource-encapsulation/src/resourceContainer/src/ResourceContainerImpl.cpp
service/resource-encapsulation/src/resourceContainer/unittests/ResourceContainerTest.cpp

index 26f0c1e..c9fa5cf 100644 (file)
@@ -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')
index dd24342..ac63569 100644 (file)
@@ -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:
index 78314f5..221f9d0 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef RESOURCECONTAINERIMPL_H_
 #define RESOURCECONTAINERIMPL_H_
 
-
-
 #include "RCSResourceContainer.h"
 #include "ResourceContainerBundleAPI.h"
 #include "BundleInfoInternal.h"
 
 #include "DiscoverResourceUnit.h"
 
+#include <boost/thread.hpp>
+#include <boost/date_time.hpp>
+
 #if(JAVA_SUPPORT)
-    #include <jni.h>
+#include <jni.h>
 #endif
 
 #include <map>
 
+#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<string, string> 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<RCSBundleInfo *> listBundles();
+            std::list< RCSBundleInfo * > listBundles();
 
-                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);
+            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<string> 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; // <bundleID, bundleInfo>
-                map< std::string, RCSResourceObject::Ptr > m_mapServers; //<uri, serverPtr>
-                map< std::string, BundleResource * > m_mapResources; //<uri, resourcePtr>
-                map< std::string, list<string> > m_mapBundleResources; //<bundleID, vector<uri>>
-                map< std::string, list<DiscoverResourceUnit::Ptr>>
-                    m_mapDiscoverResourceUnits; //<uri, DiscoverUnit>
-                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; // <bundleID, bundleInfo>
+            map< std::string, RCSResourceObject::Ptr > m_mapServers; //<uri, serverPtr>
+            map< std::string, BundleResource * > m_mapResources; //<uri, resourcePtr>
+            map< std::string, list< string > > m_mapBundleResources; //<bundleID, vector<uri>>
+            map< std::string, list< DiscoverResourceUnit::Ptr > > m_mapDiscoverResourceUnits; //<uri, DiscoverUnit>
+            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<string, JavaVM *> m_bundleVM;
+            map<string, JavaVM *> 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
 
index b74f9fc..0de792d 100644 (file)
@@ -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);
         }
 
index 88fc1ea..4e3bec1 100644 (file)
 #include <dlfcn.h>
 #include <unistd.h>
 #include <string.h>
-#include <iostream>
 #include <fstream>
 #include <iostream>
 #include <fstream>
 #include <stdio.h>
+#include <thread>
+#include <mutex>
+
 
 #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<boost::thread>::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)
         {
index cbe1bcf..c1c8a66 100644 (file)
@@ -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());