Modify resourceCache to handle datacache releasing exception
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceCache / src / DataCache.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 <memory>
22 #include <cstdlib>
23 #include <functional>
24 #include <map>
25 #include <utility>
26 #include <ctime>
27
28 #include "DataCache.h"
29
30 #include "ResponseStatement.h"
31 #include "RCSResourceAttributes.h"
32 #include "ExpiryTimer.h"
33
34 namespace OIC
35 {
36     namespace Service
37     {
38         DataCache::DataCache()
39         {
40             subscriberList = std::unique_ptr<SubscriberInfo>(new SubscriberInfo());
41
42             sResource = nullptr;
43
44             state = CACHE_STATE::READY_YET;
45             mode = CACHE_MODE::FREQUENCY;
46
47             networkTimeOutHandle = 0;
48             pollingHandle = 0;
49
50             pObserveCB = (ObserveCB)(std::bind(&DataCache::onObserve, this,
51                                                std::placeholders::_1, std::placeholders::_2,
52                                                std::placeholders::_3, std::placeholders::_4));
53             pGetCB = (GetCB)(std::bind(&DataCache::onGet, this,
54                                        std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
55             pTimerCB = (TimerCB)(std::bind(&DataCache::onTimeOut, this, std::placeholders::_1));
56             pPollingCB = (TimerCB)(std::bind(&DataCache::onPollingOut, this, std::placeholders::_1));
57
58         }
59
60         DataCache::~DataCache()
61         {
62             state = CACHE_STATE::DESTROYED;
63
64             if (subscriberList != nullptr)
65             {
66                 subscriberList->clear();
67                 subscriberList.release();
68             }
69
70             if(mode == CACHE_MODE::OBSERVE)
71             {
72                 try
73                 {
74                     sResource->cancelObserve();
75                 } catch (...)
76                 {
77                     // ignore the exception because data cache was released.
78                 }
79             }
80         }
81
82         void DataCache::initializeDataCache(PrimitiveResourcePtr pResource)
83         {
84             sResource = pResource;
85
86             sResource->requestGet(pGetCB);
87             if (sResource->isObservable())
88             {
89                 sResource->requestObserve(pObserveCB);
90             }
91             networkTimeOutHandle = networkTimer.postTimer(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
92         }
93
94         CacheID DataCache::addSubscriber(CacheCB func, REPORT_FREQUENCY rf, long repeatTime)
95         {
96             Report_Info newItem;
97             newItem.rf = rf;
98             newItem.repeatTime = repeatTime;
99             newItem.timerID = 0;
100
101             newItem.reportID = generateCacheID();
102
103             if (subscriberList != nullptr)
104             {
105                 subscriberList->insert(
106                     std::make_pair(newItem.reportID, std::make_pair(newItem, func)));
107             }
108
109             return newItem.reportID;
110         }
111
112         CacheID DataCache::deleteSubscriber(CacheID id)
113         {
114             CacheID ret = 0;
115
116             SubscriberInfoPair pair = findSubscriber(id);
117             if (pair.first != 0)
118             {
119                 ret = pair.first;
120                 subscriberList->erase(pair.first);
121             }
122
123             return ret;
124         }
125
126         SubscriberInfoPair DataCache::findSubscriber(CacheID id)
127         {
128             SubscriberInfoPair ret;
129
130             for (auto &i : *subscriberList)
131             {
132                 if (i.first == id)
133                 {
134                     ret = std::make_pair(i.first, std::make_pair((Report_Info)i.second.first,
135                                          (CacheCB)i.second.second));
136                     break;
137                 }
138             }
139
140             return ret;
141         }
142
143         const PrimitiveResourcePtr DataCache::getPrimitiveResource() const
144         {
145             return (sResource != nullptr) ? sResource : nullptr;
146         }
147
148         const RCSResourceAttributes DataCache::getCachedData() const
149         {
150             if (state != CACHE_STATE::READY || attributes.empty())
151             {
152                 return RCSResourceAttributes();
153             }
154             const RCSResourceAttributes retAtt = attributes;
155             return retAtt;
156         }
157
158         void DataCache::onObserve(
159             const HeaderOptions &_hos, const ResponseStatement &_rep, int _result, int _seq)
160         {
161
162             if (_result != OC_STACK_OK || _rep.getAttributes().empty())
163             {
164                 return;
165             }
166
167             if (state != CACHE_STATE::READY)
168             {
169                 state = CACHE_STATE::READY;
170             }
171
172             if (mode != CACHE_MODE::OBSERVE)
173             {
174                 mode = CACHE_MODE::OBSERVE;
175             }
176
177             networkTimer.cancelTimer(networkTimeOutHandle);
178             networkTimeOutHandle = networkTimer.postTimer(CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
179
180             notifyObservers(_rep.getAttributes());
181         }
182
183         void DataCache::onGet(const HeaderOptions &_hos,
184                               const ResponseStatement &_rep, int _result)
185         {
186             if (_result != OC_STACK_OK || _rep.getAttributes().empty())
187             {
188                 return;
189             }
190
191             if (state != CACHE_STATE::READY)
192             {
193                 state = CACHE_STATE::READY;
194             }
195
196             if (!sResource->isObservable())
197             {
198                 networkTimer.cancelTimer(networkTimeOutHandle);
199                 networkTimeOutHandle = networkTimer.postTimer(
200                                            CACHE_DEFAULT_EXPIRED_MILLITIME, pTimerCB);
201
202                 pollingHandle = pollingTimer.postTimer(CACHE_DEFAULT_REPORT_MILLITIME, pPollingCB);
203             }
204
205             notifyObservers(_rep.getAttributes());
206         }
207
208         void DataCache::notifyObservers(RCSResourceAttributes Att)
209         {
210             if (attributes == Att)
211             {
212                 return;
213             }
214
215             attributes = Att;
216
217             RCSResourceAttributes retAtt = Att;
218             for (auto &i : * subscriberList)
219             {
220                 if (i.second.first.rf == REPORT_FREQUENCY::UPTODATE)
221                 {
222                     i.second.second(this->sResource, retAtt);
223                 }
224             }
225         }
226
227         CACHE_STATE DataCache::getCacheState() const
228         {
229             return state;
230         }
231
232         void DataCache::onTimeOut(unsigned int timerID)
233         {
234             state = CACHE_STATE::LOST_SIGNAL;
235             return;
236         }
237         void DataCache::onPollingOut(const unsigned int timerID)
238         {
239             if (sResource != nullptr)
240             {
241                 mode = CACHE_MODE::FREQUENCY;
242                 sResource->requestGet(pGetCB);
243             }
244             return;
245         }
246
247         CacheID DataCache::generateCacheID()
248         {
249             CacheID retID = 0;
250             srand(time(NULL));
251
252             while (1)
253             {
254                 if (findSubscriber(retID).first == 0 && retID != 0)
255                 {
256                     break;
257                 }
258                 retID = rand();
259             }
260
261             return retID;
262         }
263
264         void DataCache::requestGet()
265         {
266             state = CACHE_STATE::UPDATING;
267             if (sResource != nullptr)
268             {
269                 sResource->requestGet(pGetCB);
270             }
271         }
272
273         bool DataCache::isEmptySubscriber() const
274         {
275             return (subscriberList != nullptr) ? subscriberList->empty() : true;
276         }
277     } // namespace Service
278 } // namespace OIC