Add discovery by multiple resource types.
authorChaJiwon <jw_wonny.cha@samsung.com>
Fri, 15 Jan 2016 04:39:03 +0000 (13:39 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 29 Jan 2016 08:21:02 +0000 (08:21 +0000)
Change-Id: I9e95a0488880b10fce744a2dd4eed464297bedc6
Signed-off-by: ChaJiwon <jw_wonny.cha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4805
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/resource-encapsulation/include/RCSDiscoveryManager.h
service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp
service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.cpp
service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.h
service/resource-encapsulation/unittests/DiscoveryManagerTest.cpp

index 663e787..3aaf3d0 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <memory>
 #include <functional>
+#include <vector>
 
 namespace OIC
 {
@@ -147,7 +148,27 @@ namespace OIC
                     const std::string& resourceType, ResourceDiscoveredCallback cb);
 
             /**
-             * Discovers resources of interest by resource type with provided relativeUri.
+             * Discovers resources of interest by resource type.
+             * It is Consistently discovering resources until the discovery task is canceled.
+             *
+             * @param address          A RCSAddress object
+             * @param resourceTypes    List of Resource Types
+             * @param cb               A callback to obtain discovered resource
+             *
+             * @throws InvalidParameterException If cb is empty.
+             * @throws InvalidParameterException If resourceType's size is than 2,
+             * at least one of resource type is empty.
+             *
+             * @note The callback will be invoked in an internal thread.
+             * @note If resourceTypes is empty, discovers resource by all resource types.
+             *
+             */
+            DiscoveryTask::Ptr discoverResourceByTypes(const RCSAddress& address,
+                    const std::vector< std::string >& resourceTypes,
+                    ResourceDiscoveredCallback cb);
+
+            /**
+             * Discovers resources of interest by resource types with provided relativeUri.
              * It is Consistently discovering resources until the discovery task is canceled.
              *
              * @param address          A RCSAddress object
@@ -164,7 +185,30 @@ namespace OIC
                     const std::string& relativeUri, const std::string& resourceType,
                     ResourceDiscoveredCallback cb);
 
+            /**
+             * Discovers resources of interest by resource types with provided relativeUri.
+             * It is Consistently discovering resources until the discovery task is canceled.
+             *
+             * @param address          A RCSAddress object
+             * @param relativeUri      The relative uri of resource to be searched
+             * @param resourceTypes     List of Resource Types
+             * @param cb               A callback to obtain discovered resource
+             *
+             * @throws InvalidParameterException If cb is empty.
+             * @throws InvalidParameterException If resourceType's size is than 2,
+             * at least one of resource type is empty.
+             *
+             * @note The callback will be invoked in an internal thread.
+             * @note If resourceTypes is empty, discovers resource by all resource types.
+             *
+             */
+            DiscoveryTask::Ptr discoverResourceByTypes(const RCSAddress& address,
+                    const std::string& relativeUri,
+                    const std::vector< std::string >& resourceTypes,
+                    ResourceDiscoveredCallback cb);
+
         private:
+
             RCSDiscoveryManager() = default;
             ~RCSDiscoveryManager() = default;
         };
index eebbd83..b658a7d 100755 (executable)
 
 #include "RCSDiscoveryManagerImpl.h"
 
+namespace
+{
+    constexpr char ALL_RESOURCE_TYPES[] = "";
+}
+
 namespace OIC
 {
     namespace Service
@@ -52,14 +57,15 @@ namespace OIC
         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResource(
                 const RCSAddress& address, ResourceDiscoveredCallback cb)
         {
-            return discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, "", std::move(cb));
+            return discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, ALL_RESOURCE_TYPES,
+                    std::move(cb));
         }
 
         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResource(
                 const RCSAddress& address, const std::string& relativeUri,
                 ResourceDiscoveredCallback cb)
         {
-            return discoverResourceByType(address, relativeUri, "", std::move(cb));
+            return discoverResourceByType(address, relativeUri, ALL_RESOURCE_TYPES, std::move(cb));
         }
 
         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByType(
@@ -70,12 +76,30 @@ namespace OIC
                     std::move(cb));
         }
 
+        RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByTypes(
+                const RCSAddress& address, const std::vector< std::string >& resourceTypes,
+                ResourceDiscoveredCallback cb)
+        {
+            return discoverResourceByTypes(address, OC_RSRVD_WELL_KNOWN_URI, resourceTypes,
+                    std::move(cb));
+        }
+
         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByType(
                 const RCSAddress& address, const std::string& relativeUri,
                 const std::string& resourceType, ResourceDiscoveredCallback cb)
         {
+            return discoverResourceByTypes(address,
+                    relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri,
+                    std::vector< std::string >
+                    { resourceType }, std::move(cb));
+        }
+
+        RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByTypes(
+                const RCSAddress& address, const std::string& relativeUri,
+                const std::vector< std::string >& resourceTypes, ResourceDiscoveredCallback cb)
+        {
             return RCSDiscoveryManagerImpl::getInstance()->startDiscovery(address,
-                    relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri, resourceType,
+                    relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri, resourceTypes,
                     std::move(cb));
         }
     }
index 6ed5e90..a44399f 100755 (executable)
@@ -28,6 +28,7 @@
 
 namespace
 {
+    constexpr char ALL_RESOURCE_TYPE[] = "";
     constexpr unsigned int POLLING_INTERVAL_TIME = 60000;
 
     std::string makeResourceId(const std::shared_ptr< OIC::Service::PrimitiveResource >& resource)
@@ -46,7 +47,8 @@ namespace OIC
         {
             subscribePresenceWithMuticast();
 
-            m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
+            m_timer.post(POLLING_INTERVAL_TIME,
+                    std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
         }
 
         RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
@@ -55,11 +57,12 @@ namespace OIC
             return &instance;
         }
 
-        void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr<PrimitiveResource> resource,
-                ID discoveryId, const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
+        void RCSDiscoveryManagerImpl::onResourceFound(
+                std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
+                const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
         {
             {
-                std::lock_guard< std::mutex > lock(m_mutex);
+                std::lock_guard < std::mutex > lock(m_mutex);
                 auto it = m_discoveryMap.find(discoveryId);
 
                 if (it == m_discoveryMap.end()) return;
@@ -67,32 +70,42 @@ namespace OIC
 
                 it->second.addKnownResource(resource);
             }
-            discoverCB(std::make_shared< RCSRemoteResourceObject > (resource));
+            discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
         }
 
         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
                 const RCSAddress& address, const std::string& relativeUri,
-                const std::string& resourceType, RCSDiscoveryManager::ResourceDiscoveredCallback cb)
+                const std::vector< std::string >& resourceTypes,
+                RCSDiscoveryManager::ResourceDiscoveredCallback cb)
         {
             if (!cb)
             {
                 throw RCSInvalidParameterException{ "Callback is empty" };
             }
 
+            for(const auto& it : resourceTypes)
+            {
+                if (it.compare(ALL_RESOURCE_TYPE) == 0)
+                {
+                    throw RCSInvalidParameterException{ "ResourceType is duplicated!" };
+                }
+            }
+
             const ID discoveryId = createId();
 
-            DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceType,
+            DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceTypes,
                     std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
                             std::placeholders::_1, discoveryId, std::move(cb)));
+
             discoveryInfo.discover();
 
             {
-                std::lock_guard< std::mutex > lock(m_mutex);
+                std::lock_guard < std::mutex > lock(m_mutex);
                 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
             }
 
-            return std::unique_ptr< RCSDiscoveryManager::DiscoveryTask >(
-                    new RCSDiscoveryManager::DiscoveryTask(discoveryId));
+            return std::unique_ptr < RCSDiscoveryManager::DiscoveryTask
+                    > (new RCSDiscoveryManager::DiscoveryTask(discoveryId));
         }
 
         void RCSDiscoveryManagerImpl::subscribePresenceWithMuticast()
@@ -110,14 +123,15 @@ namespace OIC
         void RCSDiscoveryManagerImpl::onPolling()
         {
             {
-                std::lock_guard< std::mutex > lock(m_mutex);
+                std::lock_guard < std::mutex > lock(m_mutex);
 
                 for (const auto& it : m_discoveryMap)
                 {
                     it.second.discover();
                 }
             }
-            m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
+            m_timer.post(POLLING_INTERVAL_TIME,
+                    std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
         }
 
         void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
@@ -125,7 +139,7 @@ namespace OIC
         {
             if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
 
-            std::lock_guard< std::mutex > lock(m_mutex);
+            std::lock_guard < std::mutex > lock(m_mutex);
             for (const auto& it : m_discoveryMap)
             {
                 if (it.second.isMatchedAddress(address))
@@ -139,7 +153,7 @@ namespace OIC
         {
             static ID s_nextId = INVALID_ID + 1;
 
-            std::lock_guard< std::mutex > lock(m_mutex);
+            std::lock_guard < std::mutex > lock(m_mutex);
 
             while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
             {
@@ -153,24 +167,31 @@ namespace OIC
 
         void RCSDiscoveryManagerImpl::cancel(ID id)
         {
-            std::lock_guard< std::mutex > lock(m_mutex);
+            std::lock_guard < std::mutex > lock(m_mutex);
             m_discoveryMap.erase(id);
         }
 
         DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
-                const std::string& relativeUri, const std::string& resourceType,
+                const std::string& relativeUri, const std::vector< std::string >& resourceTypes,
                 DiscoverCallback cb) :
                 m_address{ address },
                 m_relativeUri{ relativeUri },
-                m_resourceType{ resourceType },
+                m_resourceTypes{ resourceTypes },
                 m_knownResourceIds{ },
                 m_discoverCb{ std::move(cb) }
         {
+            if (m_resourceTypes.empty())
+            {
+                m_resourceTypes.push_back(ALL_RESOURCE_TYPE);
+            }
         }
 
         void DiscoveryRequestInfo::discover() const
         {
-            discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType, m_discoverCb);
+            for (const auto& it : m_resourceTypes)
+            {
+                discoverResource(m_address, m_relativeUri + "?rt=" + it, m_discoverCb);
+            }
         }
 
         bool DiscoveryRequestInfo::isKnownResource(
@@ -187,8 +208,8 @@ namespace OIC
 
         bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
         {
-            return RCSAddressDetail::getDetail(m_address)->isMulticast() ||
-                    RCSAddressDetail::getDetail(m_address)->getAddress() == address;
+            return RCSAddressDetail::getDetail(m_address)->isMulticast()
+                    || RCSAddressDetail::getDetail(m_address)->getAddress() == address;
         }
     }
 }
index 0637aeb..b9f3d9d 100644 (file)
@@ -52,8 +52,8 @@ namespace OIC
         class DiscoveryRequestInfo
         {
             public:
-                DiscoveryRequestInfo(const RCSAddress&, const std::string&, const std::string&,
-                        DiscoverCallback);
+                DiscoveryRequestInfo(const RCSAddress&, const std::string&,
+                        const std::vector< std::string >&, DiscoverCallback);
 
             public:
                 void discover() const;
@@ -64,7 +64,7 @@ namespace OIC
             private:
                 RCSAddress m_address;
                 std::string m_relativeUri;
-                std::string m_resourceType;
+                std::vector< std::string > m_resourceTypes;
                 std::unordered_set< std::string > m_knownResourceIds;
                 DiscoverCallback m_discoverCb;
         };
@@ -107,7 +107,8 @@ namespace OIC
                  * @see RCSDiscoveryManager
                  */
                 RCSDiscoveryManager::DiscoveryTask::Ptr startDiscovery(const RCSAddress& address,
-                        const std::string& relativeURI,const std::string& resourceType,
+                        const std::string& relativeURI,
+                        const std::vector< std::string >& resourceTypes,
                         RCSDiscoveryManager::ResourceDiscoveredCallback cb);
 
                 void cancel(ID);
@@ -127,7 +128,7 @@ namespace OIC
                  *
                  * @see PrimitiveResource
                  */
-                void onResourceFound(std::shared_ptr<PrimitiveResource> resource, ID discoveryId,
+                void onResourceFound(std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
                         const RCSDiscoveryManager::ResourceDiscoveredCallback& cb);
 
                 /**
index 361bfc1..4eedc82 100644 (file)
@@ -34,10 +34,18 @@ using namespace OIC::Service;
 using namespace OC::OCPlatform;
 
 constexpr char RESOURCEURI[]{ "/a/TemperatureSensor" };
+constexpr char SECOND_RESOURCEURI[]{ "/a/Light" };
 constexpr char RESOURCETYPE[]{ "resource.type" };
+constexpr char SECOND_RESOURCETYPE[]{ "resource.type.second" };
 constexpr char RESOURCEINTERFACE[]{ "oic.if.baseline" };
 constexpr int DEFAULT_DISCOVERYTASK_DELAYTIME = 3000;
 
+int callTimes = 0;
+
+void resourceDiscoveredForTwoTimesCall(RCSRemoteResourceObject::Ptr)
+{
+    callTimes++;
+}
 void resourceDiscoveredForCall(RCSRemoteResourceObject::Ptr) {}
 void resourceDiscoveredForNeverCall(RCSRemoteResourceObject::Ptr) {}
 
@@ -77,11 +85,25 @@ public:
         server = RCSResourceObject::Builder(RESOURCEURI, RESOURCETYPE, RESOURCEINTERFACE).build();
     }
 
+    void createSecondResource()
+    {
+        secondServer = RCSResourceObject::Builder(SECOND_RESOURCEURI, SECOND_RESOURCETYPE, RESOURCEINTERFACE).build();
+    }
+
     void proceed()
     {
         cond.notify_all();
     }
 
+    void proceed_on_condition()
+    {
+        cond.notify_all();
+        if(callTimes != 2)
+        {
+            waitForDiscoveryTask();
+        }
+    }
+
     void waitForDiscoveryTask(int waitingTime = DEFAULT_DISCOVERYTASK_DELAYTIME)
     {
         std::unique_lock< std::mutex > lock{ mutex };
@@ -93,6 +115,7 @@ private:
     std::condition_variable cond;
     std::mutex mutex;
     RCSResourceObject::Ptr server;
+    RCSResourceObject::Ptr secondServer;
     RCSRemoteResourceObject::Ptr object;
     DiscoveryTaskPtr discoveryTask;
 };
@@ -143,6 +166,40 @@ TEST_F(DiscoveryManagerTest, resourceIsSupportedPresenceAndAfterDiscovering)
     stopPresence();
 }
 
+TEST_F(DiscoveryManagerTest, discoveryRequestByMultipleResourceTypesAndFindResourcesOfTwoResourceTypes)
+{
+    std::vector<std::string> resourceTypes{RESOURCETYPE, SECOND_RESOURCETYPE};
+    const std::string uri  = "/oic/res";
+    callTimes = 0;
+
+    createResource();
+    createSecondResource();
+
+    mocks.ExpectCallFunc(resourceDiscoveredForTwoTimesCall).Do(
+        [this](RCSRemoteResourceObject::Ptr){ proceed_on_condition(); });
+
+    RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
+            uri, resourceTypes, resourceDiscoveredForTwoTimesCall);
+
+    waitForDiscoveryTask();
+}
+
+TEST_F(DiscoveryManagerTest, discoveryRequestByMultipleResourceTypesAndFindResourceOfOneResourceType)
+{
+    std::vector<std::string> resourceTypes{RESOURCETYPE, SECOND_RESOURCETYPE};
+    const std::string uri  = "/oic/res";
+
+    createSecondResource();
+
+    mocks.ExpectCallFunc(resourceDiscoveredForCall).Do(
+        [this](RCSRemoteResourceObject::Ptr){ proceed();});
+
+    RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
+            uri, resourceTypes, resourceDiscoveredForCall);
+
+    waitForDiscoveryTask();
+}
+
 TEST_F(DiscoveryManagerTest, cancelDiscoveryTaskAfterDiscoveryResource)
 {
     startDiscovery();