Update snapshot(2018-01-17)
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceCache / src / ResourceCacheManager.cpp
index 32c4782..8272570 100644 (file)
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 #include "ResourceCacheManager.h"
+#include "RCSException.h"
+#include "ocrandom.h"
+
+#include "ScopeLogger.h"
+
+#define TAG PCF("RCSResourceCacheManager")
 
 namespace OIC
 {
@@ -26,10 +32,12 @@ namespace OIC
     {
         ResourceCacheManager *ResourceCacheManager::s_instance = NULL;
         std::mutex ResourceCacheManager::s_mutexForCreation;
+        std::mutex ResourceCacheManager::s_mutex;
         std::unique_ptr<std::list<DataCachePtr>> ResourceCacheManager::s_cacheDataList(nullptr);
 
         ResourceCacheManager::~ResourceCacheManager()
         {
+            std::lock_guard<std::mutex> lock(s_mutex);
             if (s_cacheDataList != nullptr)
             {
                 s_cacheDataList->clear();
@@ -52,21 +60,44 @@ namespace OIC
         }
 
         CacheID ResourceCacheManager::requestResourceCache(
-            PrimitiveResourcePtr pResource, CacheCB func,
+            PrimitiveResourcePtr pResource, CacheCB func, CACHE_METHOD cm,
             REPORT_FREQUENCY rf, long reportTime)
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
             if (pResource == nullptr)
             {
-                throw InvalidParameterException {"[requestResourceCache] Primitive Resource is invaild"};
+                throw RCSInvalidParameterException {"[requestResourceCache] Primitive Resource is invaild"};
             }
 
             CacheID retID = 0;
 
+            if (cm == CACHE_METHOD::OBSERVE_ONLY)
+            {
+                if (func == NULL || func == nullptr)
+                {
+                    throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
+                }
+
+                std::lock_guard<std::mutex> lock(s_mutex);
+                retID = OCGetRandom();
+                while(observeCacheIDmap.find(retID) != observeCacheIDmap.end())
+                {
+                    retID = OCGetRandom();
+                }
+
+                auto newHandler = std::make_shared<ObserveCache>(pResource);
+                newHandler->startCache(std::move(func));
+
+                observeCacheIDmap.insert(std::make_pair(retID, newHandler));
+                return retID;
+            }
+
             if (rf != REPORT_FREQUENCY::NONE)
             {
                 if (func == NULL || func == nullptr)
                 {
-                    throw InvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
+                    throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
                 }
                 if (!reportTime)
                 {
@@ -78,10 +109,13 @@ namespace OIC
             DataCachePtr newHandler = findDataCache(pResource);
             if (newHandler == nullptr)
             {
+                std::lock_guard<std::mutex> lock(s_mutex);
                 newHandler.reset(new DataCache());
                 newHandler->initializeDataCache(pResource);
                 s_cacheDataList->push_back(newHandler);
             }
+
+            std::lock_guard<std::mutex> lock(s_mutex);
             retID = newHandler->addSubscriber(func, rf, reportTime);
 
             cacheIDmap.insert(std::make_pair(retID, newHandler));
@@ -91,9 +125,34 @@ namespace OIC
 
         void ResourceCacheManager::cancelResourceCache(CacheID id)
         {
-            if (id == 0 || cacheIDmap.find(id) == cacheIDmap.end())
+            SCOPE_LOG_F(DEBUG, TAG);
+            std::lock_guard<std::mutex> lock(s_mutex);
+
+            auto observeIns = observeCacheIDmap.find(id);
+            auto dataCacheIns = cacheIDmap.find(id);
+            if ((dataCacheIns == cacheIDmap.end() && observeIns == observeCacheIDmap.end())
+                || id == 0)
             {
-                throw InvalidParameterException {"[cancelResourceCache] CacheID is invaild"};
+                lock.~lock_guard();
+                throw RCSInvalidParameterException {"[cancelResourceCache] CacheID is invaild"};
+            }
+
+            if (observeIns != observeCacheIDmap.end())
+            {
+                try
+                {
+                    (observeIns->second)->stopCache();
+                }
+                catch (...)
+                {
+                    (observeIns->second).reset();
+                    observeCacheIDmap.erase(id);
+                    lock.~lock_guard();
+                    throw;
+                }
+                (observeIns->second).reset();
+                observeCacheIDmap.erase(id);
+                return;
             }
 
             DataCachePtr foundCacheHandler = findDataCache(id);
@@ -107,82 +166,72 @@ namespace OIC
                 if (foundCacheHandler->isEmptySubscriber())
                 {
                     s_cacheDataList->remove(foundCacheHandler);
-                    foundCacheHandler.reset();
                 }
             }
         }
 
-        void ResourceCacheManager::updateResourceCache(PrimitiveResourcePtr pResource) const
-        {
-            if (pResource == nullptr)
-            {
-                throw InvalidParameterException
-                {"[updateResourceCache] Primitive Resource is invaild"};
-            }
-
-            DataCachePtr foundCache = findDataCache(pResource);
-            if (foundCache == nullptr)
-            {
-                throw InvalidParameterException
-                {"[updateResourceCache] Primitive Resource is invaild"};
-            }
-            foundCache->requestGet();
-        }
         void ResourceCacheManager::updateResourceCache(CacheID updateId) const
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
             if (updateId == 0)
             {
-                throw InvalidParameterException {"[getCachedData] CacheID is invaild"};
+                throw RCSInvalidParameterException {"[updateResourceCache] CacheID is NULL"};
             }
 
             DataCachePtr foundCache = findDataCache(updateId);
             if (foundCache == nullptr)
             {
-                throw InvalidParameterException {"[getCachedData] CacheID is invaild"};
+                throw RCSInvalidParameterException {"[updateResourceCache] CacheID is invaild"};
             }
             foundCache->requestGet();
         }
 
-        const ResourceAttributes ResourceCacheManager::getCachedData(
-            PrimitiveResourcePtr pResource) const
+        const RCSResourceAttributes ResourceCacheManager::getCachedData(CacheID id) const
         {
-            if (pResource == nullptr)
-            {
-                throw InvalidParameterException {"[getCachedData] Primitive Resource is invaild"};
-            }
+            SCOPE_LOG_F(DEBUG, TAG);
 
-            DataCachePtr handler = findDataCache(pResource);
-            if (handler == nullptr)
+            if (id == 0)
             {
-                throw InvalidParameterException {"[getCachedData] Primitive Resource is invaild"};
+                throw RCSInvalidParameterException {"[getCachedData] CacheID is NULL"};
             }
-            return handler->getCachedData();
-        }
 
-        const ResourceAttributes ResourceCacheManager::getCachedData(CacheID id) const
-        {
-            if (id == 0)
+            auto observePtr = observeCacheIDmap.find(id);
+            if (observePtr != observeCacheIDmap.end())
             {
-                throw InvalidParameterException {"[getCachedData] CacheID is invaild"};
+                return (observePtr->second)->getCachedData();
             }
 
             DataCachePtr handler = findDataCache(id);
             if (handler == nullptr)
             {
-                throw InvalidParameterException {"[getCachedData] CacheID is invaild"};
+                throw RCSInvalidParameterException {"[getCachedData] CacheID is invaild"};
+            }
+
+            if (handler->isCachedData() == false)
+            {
+                throw HasNoCachedDataException {"[getCachedData] Cached Data is not stored"};
             }
+
             return handler->getCachedData();
         }
 
-        CACHE_STATE ResourceCacheManager::getResourceCacheState(
-            PrimitiveResourcePtr pResource) const
+        CACHE_STATE ResourceCacheManager::getResourceCacheState(CacheID id) const
         {
-            if (pResource == nullptr)
+            SCOPE_LOG_F(DEBUG, TAG);
+
+            if (id == 0)
+            {
+                throw RCSInvalidParameterException {"[getResourceCacheState] CacheID is NULL"};
+            }
+
+            auto observePtr = observeCacheIDmap.find(id);
+            if (observePtr != observeCacheIDmap.end())
             {
-                throw InvalidParameterException {"[getResourceCacheState] Primitive Resource is invaild"};
+                return (observePtr->second)->getCacheState();
             }
 
-            DataCachePtr handler = findDataCache(pResource);
+            DataCachePtr handler = findDataCache(id);
             if (handler == nullptr)
             {
                 return CACHE_STATE::NONE;
@@ -190,23 +239,34 @@ namespace OIC
             return handler->getCacheState();
         }
 
-        CACHE_STATE ResourceCacheManager::getResourceCacheState(CacheID id) const
+        bool ResourceCacheManager::isCachedData(CacheID id) const
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
             if (id == 0)
             {
-                throw InvalidParameterException {"[getResourceCacheState] CacheID is invaild"};
+                throw RCSInvalidParameterException {"[isCachedData] CacheID is NULL"};
+            }
+
+            auto observePtr = observeCacheIDmap.find(id);
+            if (observePtr != observeCacheIDmap.end())
+            {
+                return (observePtr->second)->isCachedData();
             }
 
             DataCachePtr handler = findDataCache(id);
             if (handler == nullptr)
             {
-                return CACHE_STATE::NONE;
+                throw RCSInvalidParameterException {"[isCachedData] CacheID is invaild"};
             }
-            return handler->getCacheState();
+            return handler->isCachedData();
         }
 
         void ResourceCacheManager::initializeResourceCacheManager()
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
+            std::lock_guard<std::mutex> lock(s_mutex);
             if (s_cacheDataList == nullptr)
             {
                 s_cacheDataList
@@ -216,7 +276,10 @@ namespace OIC
 
         DataCachePtr ResourceCacheManager::findDataCache(PrimitiveResourcePtr pResource) const
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
             DataCachePtr retHandler = nullptr;
+            std::lock_guard<std::mutex> lock(s_mutex);
             for (auto &i : * s_cacheDataList)
             {
                 if (i->getPrimitiveResource()->getUri() == pResource->getUri() &&
@@ -231,6 +294,8 @@ namespace OIC
 
         DataCachePtr ResourceCacheManager::findDataCache(CacheID id) const
         {
+            SCOPE_LOG_F(DEBUG, TAG);
+
             DataCachePtr retHandler = nullptr;
             for (auto it : cacheIDmap)
             {