Add api about non-iterated request get at cache.
[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 namespace OIC
26 {
27     namespace Service
28     {
29         ResourceCacheManager *ResourceCacheManager::s_instance = NULL;
30         std::mutex ResourceCacheManager::s_mutexForCreation;
31         std::mutex ResourceCacheManager::s_mutex;
32         std::unique_ptr<std::list<DataCachePtr>> ResourceCacheManager::s_cacheDataList(nullptr);
33
34         ResourceCacheManager::~ResourceCacheManager()
35         {
36             std::lock_guard<std::mutex> lock(s_mutex);
37             if (s_cacheDataList != nullptr)
38             {
39                 s_cacheDataList->clear();
40             }
41         }
42
43         ResourceCacheManager *ResourceCacheManager::getInstance()
44         {
45             if (s_instance == nullptr)
46             {
47                 s_mutexForCreation.lock();
48                 if (s_instance == nullptr)
49                 {
50                     s_instance = new ResourceCacheManager();
51                     s_instance->initializeResourceCacheManager();
52                 }
53                 s_mutexForCreation.unlock();
54             }
55             return s_instance;
56         }
57
58         CacheID ResourceCacheManager::requestResourceCache(
59             PrimitiveResourcePtr pResource, CacheCB func, CACHE_METHOD cm,
60             REPORT_FREQUENCY rf, long reportTime)
61         {
62             if (pResource == nullptr)
63             {
64                 throw RCSInvalidParameterException {"[requestResourceCache] Primitive Resource is invaild"};
65             }
66
67             CacheID retID = 0;
68
69             if (cm == CACHE_METHOD::OBSERVE_ONLY)
70             {
71                 if (func == NULL || func == nullptr)
72                 {
73                     throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
74                 }
75
76                 std::lock_guard<std::mutex> lock(s_mutex);
77                 retID = OCGetRandom();
78                 while(observeCacheIDmap.find(retID) != observeCacheIDmap.end())
79                 {
80                     retID = OCGetRandom();
81                 }
82
83                 auto newHandler = std::make_shared<ObserveCache>(pResource);
84                 newHandler->startCache(std::move(func));
85                 m_observeCacheList.push_back(newHandler);
86
87                 observeCacheIDmap.insert(std::make_pair(retID, newHandler));
88                 return retID;
89             }
90
91             if (rf != REPORT_FREQUENCY::NONE)
92             {
93                 if (func == NULL || func == nullptr)
94                 {
95                     throw RCSInvalidParameterException {"[requestResourceCache] CacheCB is invaild"};
96                 }
97                 if (!reportTime)
98                 {
99                     // default setting
100                     reportTime = CACHE_DEFAULT_REPORT_MILLITIME;
101                 }
102             }
103
104             DataCachePtr newHandler = findDataCache(pResource);
105             if (newHandler == nullptr)
106             {
107                 std::lock_guard<std::mutex> lock(s_mutex);
108                 newHandler.reset(new DataCache());
109                 newHandler->initializeDataCache(pResource);
110                 s_cacheDataList->push_back(newHandler);
111             }
112             retID = newHandler->addSubscriber(func, rf, reportTime);
113
114             cacheIDmap.insert(std::make_pair(retID, newHandler));
115
116             return retID;
117         }
118
119         void ResourceCacheManager::cancelResourceCache(CacheID id)
120         {
121             auto observeIns = observeCacheIDmap.find(id);
122             auto dataCacheIns = cacheIDmap.find(id);
123             if ((dataCacheIns == cacheIDmap.end() && observeIns == observeCacheIDmap.end())
124                 || id == 0)
125             {
126                 throw RCSInvalidParameterException {"[cancelResourceCache] CacheID is invaild"};
127             }
128
129             if (observeIns != observeCacheIDmap.end())
130             {
131                 (observeIns->second)->stopCache();
132                 (observeIns->second).reset();
133                 observeCacheIDmap.erase(observeIns);
134                 return;
135             }
136
137             DataCachePtr foundCacheHandler = findDataCache(id);
138             if (foundCacheHandler != nullptr)
139             {
140                 CacheID retID = foundCacheHandler->deleteSubscriber(id);
141                 if (retID == id)
142                 {
143                     cacheIDmap.erase(id);
144                 }
145                 std::lock_guard<std::mutex> lock(s_mutex);
146                 if (foundCacheHandler->isEmptySubscriber())
147                 {
148                     s_cacheDataList->remove(foundCacheHandler);
149                 }
150             }
151         }
152
153         void ResourceCacheManager::updateResourceCache(CacheID updateId) const
154         {
155             if (updateId == 0)
156             {
157                 throw RCSInvalidParameterException {"[getCachedData] CacheID is NULL"};
158             }
159
160             DataCachePtr foundCache = findDataCache(updateId);
161             if (foundCache == nullptr)
162             {
163                 throw RCSInvalidParameterException {"[getCachedData] CacheID is invaild"};
164             }
165             foundCache->requestGet();
166         }
167
168         const RCSResourceAttributes ResourceCacheManager::getCachedData(CacheID id) const
169         {
170             if (id == 0)
171             {
172                 throw RCSInvalidParameterException {"[getCachedData] CacheID is NULL"};
173             }
174
175             auto observePtr = observeCacheIDmap.find(id);
176             if (observePtr != observeCacheIDmap.end())
177             {
178                 return (observePtr->second)->getCachedData();
179             }
180
181             DataCachePtr handler = findDataCache(id);
182             if (handler == nullptr)
183             {
184                 throw RCSInvalidParameterException {"[getCachedData] CacheID is invaild"};
185             }
186
187             if (handler->isCachedData() == false)
188             {
189                 throw HasNoCachedDataException {"[getCachedData] Cached Data is not stored"};
190             }
191
192             return handler->getCachedData();
193         }
194
195         CACHE_STATE ResourceCacheManager::getResourceCacheState(CacheID id) const
196         {
197             if (id == 0)
198             {
199                 throw RCSInvalidParameterException {"[getResourceCacheState] CacheID is NULL"};
200             }
201
202             auto observePtr = observeCacheIDmap.find(id);
203             if (observePtr != observeCacheIDmap.end())
204             {
205                 return (observePtr->second)->getCacheState();
206             }
207
208             DataCachePtr handler = findDataCache(id);
209             if (handler == nullptr)
210             {
211                 return CACHE_STATE::NONE;
212             }
213             return handler->getCacheState();
214         }
215
216         bool ResourceCacheManager::isCachedData(CacheID id) const
217         {
218             if (id == 0)
219             {
220                 throw RCSInvalidParameterException {"[isCachedData] CacheID is NULL"};
221             }
222
223             auto observePtr = observeCacheIDmap.find(id);
224             if (observePtr != observeCacheIDmap.end())
225             {
226                 return (observePtr->second)->isCachedData();
227             }
228
229             DataCachePtr handler = findDataCache(id);
230             if (handler == nullptr)
231             {
232                 throw RCSInvalidParameterException {"[isCachedData] CacheID is invaild"};
233             }
234             return handler->isCachedData();
235         }
236
237         void ResourceCacheManager::initializeResourceCacheManager()
238         {
239             std::lock_guard<std::mutex> lock(s_mutex);
240             if (s_cacheDataList == nullptr)
241             {
242                 s_cacheDataList
243                     = std::unique_ptr<std::list<DataCachePtr>>(new std::list<DataCachePtr>);
244             }
245         }
246
247         DataCachePtr ResourceCacheManager::findDataCache(PrimitiveResourcePtr pResource) const
248         {
249             DataCachePtr retHandler = nullptr;
250             std::lock_guard<std::mutex> lock(s_mutex);
251             for (auto &i : * s_cacheDataList)
252             {
253                 if (i->getPrimitiveResource()->getUri() == pResource->getUri() &&
254                     i->getPrimitiveResource()->getHost() == pResource->getHost())
255                 {
256                     retHandler = i;
257                     break;
258                 }
259             }
260             return retHandler;
261         }
262
263         DataCachePtr ResourceCacheManager::findDataCache(CacheID id) const
264         {
265             DataCachePtr retHandler = nullptr;
266             for (auto it : cacheIDmap)
267             {
268                 if (it.first == id)
269                 {
270                     retHandler = it.second;
271                     break;
272                 }
273             }
274
275             return retHandler;
276         }
277     } // namespace Service
278 } // namespace OIC