8a3f0201994cbdbb0b7f236108fc5d0e179e302f
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceCache / src / ResourceCacheManager.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "ResourceCacheManager.h"
22 #include "RCSException.h"
23 #include "ocrandom.h"
24
25 #include "ScopeLogger.h"
26
27 #define TAG PCF("RCSResourceCacheManager")
28
29 namespace OIC
30 {
31     namespace Service
32     {
33         ResourceCacheManager *ResourceCacheManager::s_instance = NULL;
34         std::mutex ResourceCacheManager::s_mutexForCreation;
35         std::mutex ResourceCacheManager::s_mutex;
36         std::unique_ptr<std::list<DataCachePtr>> ResourceCacheManager::s_cacheDataList(nullptr);
37
38         ResourceCacheManager::~ResourceCacheManager()
39         {
40             std::lock_guard<std::mutex> lock(s_mutex);
41             if (s_cacheDataList != nullptr)
42             {
43                 s_cacheDataList->clear();
44             }
45         }
46
47         ResourceCacheManager *ResourceCacheManager::getInstance()
48         {
49             if (s_instance == nullptr)
50             {
51                 s_mutexForCreation.lock();
52                 if (s_instance == nullptr)
53                 {
54                     s_instance = new ResourceCacheManager();
55                     s_instance->initializeResourceCacheManager();
56                 }
57                 s_mutexForCreation.unlock();
58             }
59             return s_instance;
60         }
61
62         CacheID ResourceCacheManager::requestResourceCache(
63             PrimitiveResourcePtr pResource, CacheCB func, CACHE_METHOD cm,
64             REPORT_FREQUENCY rf, long reportTime)
65         {
66             SCOPE_LOG_F(DEBUG, TAG);
67
68             if (pResource == nullptr)
69             {
70                 throw RCSInvalidParameterException {"[requestResourceCache] Primitive Resource is invaild"};
71             }
72
73             CacheID retID = 0;
74
75             if (cm == CACHE_METHOD::OBSERVE_ONLY)
76             {
77                 if (func == NULL || func == nullptr)
78                 {
79                     throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
80                 }
81
82                 std::lock_guard<std::mutex> lock(s_mutex);
83                 retID = OCGetRandom();
84                 while(observeCacheIDmap.find(retID) != observeCacheIDmap.end())
85                 {
86                     retID = OCGetRandom();
87                 }
88
89                 auto newHandler = std::make_shared<ObserveCache>(pResource);
90                 newHandler->startCache(std::move(func));
91
92                 observeCacheIDmap.insert(std::make_pair(retID, newHandler));
93                 return retID;
94             }
95
96             if (rf != REPORT_FREQUENCY::NONE)
97             {
98                 if (func == NULL || func == nullptr)
99                 {
100                     throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
101                 }
102                 if (!reportTime)
103                 {
104                     // default setting
105                     reportTime = CACHE_DEFAULT_REPORT_MILLITIME;
106                 }
107             }
108
109             DataCachePtr newHandler = findDataCache(pResource);
110             if (newHandler == nullptr)
111             {
112                 std::lock_guard<std::mutex> lock(s_mutex);
113                 newHandler.reset(new DataCache());
114                 newHandler->initializeDataCache(pResource);
115                 s_cacheDataList->push_back(newHandler);
116             }
117
118             std::lock_guard<std::mutex> lock(s_mutex);
119             retID = newHandler->addSubscriber(func, rf, reportTime);
120
121             cacheIDmap.insert(std::make_pair(retID, newHandler));
122
123             return retID;
124         }
125
126         void ResourceCacheManager::cancelResourceCache(CacheID id)
127         {
128             SCOPE_LOG_F(DEBUG, TAG);
129             std::lock_guard<std::mutex> lock(s_mutex);
130
131             auto observeIns = observeCacheIDmap.find(id);
132             auto dataCacheIns = cacheIDmap.find(id);
133             if ((dataCacheIns == cacheIDmap.end() && observeIns == observeCacheIDmap.end())
134                 || id == 0)
135             {
136                 throw RCSInvalidParameterException {"[cancelResourceCache] CacheID is invaild"};
137             }
138
139             if (observeIns != observeCacheIDmap.end())
140             {
141                 try
142                 {
143                     (observeIns->second)->stopCache();
144                 }
145                 catch (...)
146                 {
147                     (observeIns->second).reset();
148                     observeCacheIDmap.erase(id);
149                     throw;
150                 }
151                 (observeIns->second).reset();
152                 observeCacheIDmap.erase(id);
153                 return;
154             }
155
156             DataCachePtr foundCacheHandler = findDataCache(id);
157             if (foundCacheHandler != nullptr)
158             {
159                 CacheID retID = foundCacheHandler->deleteSubscriber(id);
160                 if (retID == id)
161                 {
162                     cacheIDmap.erase(id);
163                 }
164                 if (foundCacheHandler->isEmptySubscriber())
165                 {
166                     s_cacheDataList->remove(foundCacheHandler);
167                 }
168             }
169         }
170
171         void ResourceCacheManager::updateResourceCache(CacheID updateId) const
172         {
173             SCOPE_LOG_F(DEBUG, TAG);
174
175             if (updateId == 0)
176             {
177                 throw RCSInvalidParameterException {"[updateResourceCache] CacheID is NULL"};
178             }
179
180             DataCachePtr foundCache = findDataCache(updateId);
181             if (foundCache == nullptr)
182             {
183                 throw RCSInvalidParameterException {"[updateResourceCache] CacheID is invaild"};
184             }
185             foundCache->requestGet();
186         }
187
188         const RCSResourceAttributes ResourceCacheManager::getCachedData(CacheID id) const
189         {
190             SCOPE_LOG_F(DEBUG, TAG);
191
192             if (id == 0)
193             {
194                 throw RCSInvalidParameterException {"[getCachedData] CacheID is NULL"};
195             }
196
197             auto observePtr = observeCacheIDmap.find(id);
198             if (observePtr != observeCacheIDmap.end())
199             {
200                 return (observePtr->second)->getCachedData();
201             }
202
203             DataCachePtr handler = findDataCache(id);
204             if (handler == nullptr)
205             {
206                 throw RCSInvalidParameterException {"[getCachedData] CacheID is invaild"};
207             }
208
209             if (handler->isCachedData() == false)
210             {
211                 throw HasNoCachedDataException {"[getCachedData] Cached Data is not stored"};
212             }
213
214             return handler->getCachedData();
215         }
216
217         CACHE_STATE ResourceCacheManager::getResourceCacheState(CacheID id) const
218         {
219             SCOPE_LOG_F(DEBUG, TAG);
220
221             if (id == 0)
222             {
223                 throw RCSInvalidParameterException {"[getResourceCacheState] CacheID is NULL"};
224             }
225
226             auto observePtr = observeCacheIDmap.find(id);
227             if (observePtr != observeCacheIDmap.end())
228             {
229                 return (observePtr->second)->getCacheState();
230             }
231
232             DataCachePtr handler = findDataCache(id);
233             if (handler == nullptr)
234             {
235                 return CACHE_STATE::NONE;
236             }
237             return handler->getCacheState();
238         }
239
240         bool ResourceCacheManager::isCachedData(CacheID id) const
241         {
242             SCOPE_LOG_F(DEBUG, TAG);
243
244             if (id == 0)
245             {
246                 throw RCSInvalidParameterException {"[isCachedData] CacheID is NULL"};
247             }
248
249             auto observePtr = observeCacheIDmap.find(id);
250             if (observePtr != observeCacheIDmap.end())
251             {
252                 return (observePtr->second)->isCachedData();
253             }
254
255             DataCachePtr handler = findDataCache(id);
256             if (handler == nullptr)
257             {
258                 throw RCSInvalidParameterException {"[isCachedData] CacheID is invaild"};
259             }
260             return handler->isCachedData();
261         }
262
263         void ResourceCacheManager::initializeResourceCacheManager()
264         {
265             SCOPE_LOG_F(DEBUG, TAG);
266
267             std::lock_guard<std::mutex> lock(s_mutex);
268             if (s_cacheDataList == nullptr)
269             {
270                 s_cacheDataList
271                     = std::unique_ptr<std::list<DataCachePtr>>(new std::list<DataCachePtr>);
272             }
273         }
274
275         DataCachePtr ResourceCacheManager::findDataCache(PrimitiveResourcePtr pResource) const
276         {
277             SCOPE_LOG_F(DEBUG, TAG);
278
279             DataCachePtr retHandler = nullptr;
280             std::lock_guard<std::mutex> lock(s_mutex);
281             for (auto &i : * s_cacheDataList)
282             {
283                 if (i->getPrimitiveResource()->getUri() == pResource->getUri() &&
284                     i->getPrimitiveResource()->getHost() == pResource->getHost())
285                 {
286                     retHandler = i;
287                     break;
288                 }
289             }
290             return retHandler;
291         }
292
293         DataCachePtr ResourceCacheManager::findDataCache(CacheID id) const
294         {
295             SCOPE_LOG_F(DEBUG, TAG);
296
297             DataCachePtr retHandler = nullptr;
298             for (auto it : cacheIDmap)
299             {
300                 if (it.first == id)
301                 {
302                     retHandler = it.second;
303                     break;
304                 }
305             }
306
307             return retHandler;
308         }
309     } // namespace Service
310 } // namespace OIC