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