Update snapshot(2018-01-17)
[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                 lock.~lock_guard();
137                 throw RCSInvalidParameterException {"[cancelResourceCache] CacheID is invaild"};
138             }
139
140             if (observeIns != observeCacheIDmap.end())
141             {
142                 try
143                 {
144                     (observeIns->second)->stopCache();
145                 }
146                 catch (...)
147                 {
148                     (observeIns->second).reset();
149                     observeCacheIDmap.erase(id);
150                     lock.~lock_guard();
151                     throw;
152                 }
153                 (observeIns->second).reset();
154                 observeCacheIDmap.erase(id);
155                 return;
156             }
157
158             DataCachePtr foundCacheHandler = findDataCache(id);
159             if (foundCacheHandler != nullptr)
160             {
161                 CacheID retID = foundCacheHandler->deleteSubscriber(id);
162                 if (retID == id)
163                 {
164                     cacheIDmap.erase(id);
165                 }
166                 if (foundCacheHandler->isEmptySubscriber())
167                 {
168                     s_cacheDataList->remove(foundCacheHandler);
169                 }
170             }
171         }
172
173         void ResourceCacheManager::updateResourceCache(CacheID updateId) const
174         {
175             SCOPE_LOG_F(DEBUG, TAG);
176
177             if (updateId == 0)
178             {
179                 throw RCSInvalidParameterException {"[updateResourceCache] CacheID is NULL"};
180             }
181
182             DataCachePtr foundCache = findDataCache(updateId);
183             if (foundCache == nullptr)
184             {
185                 throw RCSInvalidParameterException {"[updateResourceCache] CacheID is invaild"};
186             }
187             foundCache->requestGet();
188         }
189
190         const RCSResourceAttributes ResourceCacheManager::getCachedData(CacheID id) const
191         {
192             SCOPE_LOG_F(DEBUG, TAG);
193
194             if (id == 0)
195             {
196                 throw RCSInvalidParameterException {"[getCachedData] CacheID is NULL"};
197             }
198
199             auto observePtr = observeCacheIDmap.find(id);
200             if (observePtr != observeCacheIDmap.end())
201             {
202                 return (observePtr->second)->getCachedData();
203             }
204
205             DataCachePtr handler = findDataCache(id);
206             if (handler == nullptr)
207             {
208                 throw RCSInvalidParameterException {"[getCachedData] CacheID is invaild"};
209             }
210
211             if (handler->isCachedData() == false)
212             {
213                 throw HasNoCachedDataException {"[getCachedData] Cached Data is not stored"};
214             }
215
216             return handler->getCachedData();
217         }
218
219         CACHE_STATE ResourceCacheManager::getResourceCacheState(CacheID id) const
220         {
221             SCOPE_LOG_F(DEBUG, TAG);
222
223             if (id == 0)
224             {
225                 throw RCSInvalidParameterException {"[getResourceCacheState] CacheID is NULL"};
226             }
227
228             auto observePtr = observeCacheIDmap.find(id);
229             if (observePtr != observeCacheIDmap.end())
230             {
231                 return (observePtr->second)->getCacheState();
232             }
233
234             DataCachePtr handler = findDataCache(id);
235             if (handler == nullptr)
236             {
237                 return CACHE_STATE::NONE;
238             }
239             return handler->getCacheState();
240         }
241
242         bool ResourceCacheManager::isCachedData(CacheID id) const
243         {
244             SCOPE_LOG_F(DEBUG, TAG);
245
246             if (id == 0)
247             {
248                 throw RCSInvalidParameterException {"[isCachedData] CacheID is NULL"};
249             }
250
251             auto observePtr = observeCacheIDmap.find(id);
252             if (observePtr != observeCacheIDmap.end())
253             {
254                 return (observePtr->second)->isCachedData();
255             }
256
257             DataCachePtr handler = findDataCache(id);
258             if (handler == nullptr)
259             {
260                 throw RCSInvalidParameterException {"[isCachedData] CacheID is invaild"};
261             }
262             return handler->isCachedData();
263         }
264
265         void ResourceCacheManager::initializeResourceCacheManager()
266         {
267             SCOPE_LOG_F(DEBUG, TAG);
268
269             std::lock_guard<std::mutex> lock(s_mutex);
270             if (s_cacheDataList == nullptr)
271             {
272                 s_cacheDataList
273                     = std::unique_ptr<std::list<DataCachePtr>>(new std::list<DataCachePtr>);
274             }
275         }
276
277         DataCachePtr ResourceCacheManager::findDataCache(PrimitiveResourcePtr pResource) const
278         {
279             SCOPE_LOG_F(DEBUG, TAG);
280
281             DataCachePtr retHandler = nullptr;
282             std::lock_guard<std::mutex> lock(s_mutex);
283             for (auto &i : * s_cacheDataList)
284             {
285                 if (i->getPrimitiveResource()->getUri() == pResource->getUri() &&
286                     i->getPrimitiveResource()->getHost() == pResource->getHost())
287                 {
288                     retHandler = i;
289                     break;
290                 }
291             }
292             return retHandler;
293         }
294
295         DataCachePtr ResourceCacheManager::findDataCache(CacheID id) const
296         {
297             SCOPE_LOG_F(DEBUG, TAG);
298
299             DataCachePtr retHandler = nullptr;
300             for (auto it : cacheIDmap)
301             {
302                 if (it.first == id)
303                 {
304                     retHandler = it.second;
305                     break;
306                 }
307             }
308
309             return retHandler;
310         }
311     } // namespace Service
312 } // namespace OIC