From b07bda79dfab08bb8a5c8ecc1b359484082bbec3 Mon Sep 17 00:00:00 2001 From: ChaJiwon Date: Fri, 15 Jan 2016 13:39:03 +0900 Subject: [PATCH] Add discovery by multiple resource types. Change-Id: I9e95a0488880b10fce744a2dd4eed464297bedc6 Signed-off-by: ChaJiwon Reviewed-on: https://gerrit.iotivity.org/gerrit/4805 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi --- .../include/RCSDiscoveryManager.h | 46 +++++++++++++++- .../src/resourceClient/RCSDiscoveryManager.cpp | 30 +++++++++-- .../src/resourceClient/RCSDiscoveryManagerImpl.cpp | 61 +++++++++++++++------- .../src/resourceClient/RCSDiscoveryManagerImpl.h | 11 ++-- .../unittests/DiscoveryManagerTest.cpp | 57 ++++++++++++++++++++ 5 files changed, 176 insertions(+), 29 deletions(-) diff --git a/service/resource-encapsulation/include/RCSDiscoveryManager.h b/service/resource-encapsulation/include/RCSDiscoveryManager.h index 663e787..3aaf3d0 100644 --- a/service/resource-encapsulation/include/RCSDiscoveryManager.h +++ b/service/resource-encapsulation/include/RCSDiscoveryManager.h @@ -31,6 +31,7 @@ #include #include +#include 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; }; diff --git a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp index eebbd83..b658a7d 100755 --- a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp +++ b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManager.cpp @@ -21,6 +21,11 @@ #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)); } } diff --git a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.cpp b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.cpp index 6ed5e90..a44399f 100755 --- a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.cpp +++ b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.cpp @@ -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 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; } } } diff --git a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.h b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.h index 0637aeb..b9f3d9d 100644 --- a/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.h +++ b/service/resource-encapsulation/src/resourceClient/RCSDiscoveryManagerImpl.h @@ -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 resource, ID discoveryId, + void onResourceFound(std::shared_ptr< PrimitiveResource > resource, ID discoveryId, const RCSDiscoveryManager::ResourceDiscoveredCallback& cb); /** diff --git a/service/resource-encapsulation/unittests/DiscoveryManagerTest.cpp b/service/resource-encapsulation/unittests/DiscoveryManagerTest.cpp index 361bfc1..4eedc82 100644 --- a/service/resource-encapsulation/unittests/DiscoveryManagerTest.cpp +++ b/service/resource-encapsulation/unittests/DiscoveryManagerTest.cpp @@ -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 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 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(); -- 2.7.4