1 /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 #define LOG_TAG "LocSvc_SystemStatusOsObserver"
30
31 #include <algorithm>
32 #include <SystemStatus.h>
33 #include <SystemStatusOsObserver.h>
34 #include <IDataItemCore.h>
35 #include <IClientIndex.h>
36 #include <IDataItemIndex.h>
37 #include <IndexFactory.h>
38 #include <DataItemsFactoryProxy.h>
39
40 namespace loc_core
41 {
SystemStatusOsObserver(const MsgTask * msgTask)42 SystemStatusOsObserver::SystemStatusOsObserver(const MsgTask* msgTask) :
43 mAddress("SystemStatusOsObserver"),
44 mClientIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createClientIndex()),
45 mDataItemIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createDataItemIndex())
46 {
47 mContext.mMsgTask = msgTask;
48 }
49
~SystemStatusOsObserver()50 SystemStatusOsObserver::~SystemStatusOsObserver()
51 {
52 // Close data-item library handle
53 DataItemsFactoryProxy::closeDataItemLibraryHandle();
54
55 // Destroy cache
56 for (auto each : mDataItemCache) {
57 if (nullptr != each.second) {
58 delete each.second;
59 }
60 }
61
62 mDataItemCache.clear();
63 delete mClientIndex;
64 delete mDataItemIndex;
65 }
66
setSubscriptionObj(IDataItemSubscription * subscriptionObj)67 void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
68 {
69 mContext.mSubscriptionObj = subscriptionObj;
70
71 LOC_LOGD("Request cache size - Subscribe:%zu RequestData:%zu",
72 mSubscribeReqCache.size(), mReqDataCache.size());
73
74 // we have received the subscription object. process cached requests
75 // process - subscribe request cache
76 for (auto each : mSubscribeReqCache) {
77 subscribe(each.second, each.first);
78 }
79 // process - requestData request cache
80 for (auto each : mReqDataCache) {
81 requestData(each.second, each.first);
82 }
83 }
84
85 // Helper to cache requests subscribe and requestData till subscription obj is obtained
cacheObserverRequest(ObserverReqCache & reqCache,const list<DataItemId> & l,IDataItemObserver * client)86 void SystemStatusOsObserver::cacheObserverRequest(ObserverReqCache& reqCache,
87 const list<DataItemId>& l, IDataItemObserver* client)
88 {
89 ObserverReqCache::iterator dicIter = reqCache.find(client);
90 if (dicIter != reqCache.end()) {
91 // found
92 list<DataItemId> difference(0);
93 set_difference(l.begin(), l.end(),
94 dicIter->second.begin(), dicIter->second.end(),
95 inserter(difference, difference.begin()));
96 if (!difference.empty()) {
97 difference.sort();
98 dicIter->second.merge(difference);
99 dicIter->second.unique();
100 }
101 }
102 else {
103 // not found
104 reqCache[client] = l;
105 }
106 }
107
108 /******************************************************************************
109 IDataItemSubscription Overrides
110 ******************************************************************************/
subscribe(const list<DataItemId> & l,IDataItemObserver * client)111 void SystemStatusOsObserver::subscribe(
112 const list<DataItemId>& l, IDataItemObserver* client)
113 {
114 if (nullptr == mContext.mSubscriptionObj) {
115 LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__);
116 cacheObserverRequest(mSubscribeReqCache, l, client);
117 return;
118 }
119
120 struct HandleSubscribeReq : public LocMsg {
121 HandleSubscribeReq(SystemStatusOsObserver* parent,
122 const list<DataItemId>& l, IDataItemObserver* client) :
123 mParent(parent), mClient(client), mDataItemList(l) {}
124 virtual ~HandleSubscribeReq() {}
125 void proc() const {
126
127 if (mDataItemList.empty()) {
128 LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
129 return;
130 }
131
132 // Handle First Response
133 list<DataItemId> pendingFirstResponseList(0);
134 mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList);
135
136 // Do not send first response for only pendingFirstResponseList,
137 // instead send for all the data items (present in the cache) that
138 // have been subscribed for each time.
139 mParent->sendFirstResponse(mDataItemList, mClient);
140
141 list<DataItemId> yetToSubscribeDataItemsList(0);
142 mParent->mDataItemIndex->add(mClient, mDataItemList, yetToSubscribeDataItemsList);
143
144 // Send subscription list to framework
145 if (!yetToSubscribeDataItemsList.empty()) {
146 mParent->mContext.mSubscriptionObj->subscribe(yetToSubscribeDataItemsList, mParent);
147 LOC_LOGD("Subscribe Request sent to framework for the following");
148 mParent->logMe(yetToSubscribeDataItemsList);
149 }
150 }
151 SystemStatusOsObserver* mParent;
152 IDataItemObserver* mClient;
153 const list<DataItemId> mDataItemList;
154 };
155 mContext.mMsgTask->sendMsg(new (nothrow) HandleSubscribeReq(this, l, client));
156 }
157
updateSubscription(const list<DataItemId> & l,IDataItemObserver * client)158 void SystemStatusOsObserver::updateSubscription(
159 const list<DataItemId>& l, IDataItemObserver* client)
160 {
161 if (nullptr == mContext.mSubscriptionObj) {
162 LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
163 return;
164 }
165
166 struct HandleUpdateSubscriptionReq : public LocMsg {
167 HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
168 const list<DataItemId>& l, IDataItemObserver* client) :
169 mParent(parent), mClient(client), mDataItemList(l) {}
170 virtual ~HandleUpdateSubscriptionReq() {}
171 void proc() const {
172 if (mDataItemList.empty()) {
173 LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
174 return;
175 }
176
177 list<DataItemId> currentlySubscribedList(0);
178 mParent->mClientIndex->getSubscribedList(mClient, currentlySubscribedList);
179
180 list<DataItemId> removeDataItemList(0);
181 set_difference(currentlySubscribedList.begin(), currentlySubscribedList.end(),
182 mDataItemList.begin(), mDataItemList.end(),
183 inserter(removeDataItemList,removeDataItemList.begin()));
184
185 // Handle First Response
186 list<DataItemId> pendingFirstResponseList(0);
187 mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList);
188
189 // Send First Response
190 mParent->sendFirstResponse(pendingFirstResponseList, mClient);
191
192 list<DataItemId> yetToSubscribeDataItemsList(0);
193 mParent->mDataItemIndex->add(
194 mClient, mDataItemList, yetToSubscribeDataItemsList);
195
196 // Send subscription list to framework
197 if (!yetToSubscribeDataItemsList.empty()) {
198 mParent->mContext.mSubscriptionObj->subscribe(
199 yetToSubscribeDataItemsList, mParent);
200 LOC_LOGD("Subscribe Request sent to framework for the following");
201 mParent->logMe(yetToSubscribeDataItemsList);
202 }
203
204 list<DataItemId> unsubscribeList(0);
205 list<DataItemId> unused(0);
206 mParent->mClientIndex->remove(mClient, removeDataItemList, unused);
207
208 if (!mParent->mClientIndex->isSubscribedClient(mClient)) {
209 mParent->mDataItemIndex->remove(
210 list<IDataItemObserver*> (1,mClient), unsubscribeList);
211 }
212 if (!unsubscribeList.empty()) {
213 // Send unsubscribe to framework
214 mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
215 LOC_LOGD("Unsubscribe Request sent to framework for the following");
216 mParent->logMe(unsubscribeList);
217 }
218 }
219 SystemStatusOsObserver* mParent;
220 IDataItemObserver* mClient;
221 const list<DataItemId> mDataItemList;
222 };
223 mContext.mMsgTask->sendMsg(new (nothrow) HandleUpdateSubscriptionReq(this, l, client));
224 }
225
requestData(const list<DataItemId> & l,IDataItemObserver * client)226 void SystemStatusOsObserver::requestData(
227 const list<DataItemId>& l, IDataItemObserver* client)
228 {
229 if (nullptr == mContext.mSubscriptionObj) {
230 LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__);
231 cacheObserverRequest(mReqDataCache, l, client);
232 return;
233 }
234
235 struct HandleRequestData : public LocMsg {
236 HandleRequestData(SystemStatusOsObserver* parent,
237 const list<DataItemId>& l, IDataItemObserver* client) :
238 mParent(parent), mClient(client), mDataItemList(l) {}
239 virtual ~HandleRequestData() {}
240 void proc() const {
241 if (mDataItemList.empty()) {
242 LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
243 return;
244 }
245
246 list<DataItemId> yetToSubscribeDataItemsList(0);
247 mParent->mClientIndex->add(
248 mClient, mDataItemList, yetToSubscribeDataItemsList);
249 mParent->mDataItemIndex->add(
250 mClient, mDataItemList, yetToSubscribeDataItemsList);
251
252 // Send subscription list to framework
253 if (!mDataItemList.empty()) {
254 mParent->mContext.mSubscriptionObj->requestData(mDataItemList, mParent);
255 LOC_LOGD("Subscribe Request sent to framework for the following");
256 mParent->logMe(yetToSubscribeDataItemsList);
257 }
258 }
259 SystemStatusOsObserver* mParent;
260 IDataItemObserver* mClient;
261 const list<DataItemId> mDataItemList;
262 };
263 mContext.mMsgTask->sendMsg(new (nothrow) HandleRequestData(this, l, client));
264 }
265
unsubscribe(const list<DataItemId> & l,IDataItemObserver * client)266 void SystemStatusOsObserver::unsubscribe(
267 const list<DataItemId>& l, IDataItemObserver* client)
268 {
269 if (nullptr == mContext.mSubscriptionObj) {
270 LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
271 return;
272 }
273 struct HandleUnsubscribeReq : public LocMsg {
274 HandleUnsubscribeReq(SystemStatusOsObserver* parent,
275 const list<DataItemId>& l, IDataItemObserver* client) :
276 mParent(parent), mClient(client), mDataItemList(l) {}
277 virtual ~HandleUnsubscribeReq() {}
278 void proc() const {
279 if (mDataItemList.empty()) {
280 LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
281 return;
282 }
283
284 list<DataItemId> unsubscribeList(0);
285 list<DataItemId> unused(0);
286 mParent->mClientIndex->remove(mClient, mDataItemList, unused);
287
288 for (auto each : mDataItemList) {
289 list<IDataItemObserver*> clientListSubs(0);
290 list<IDataItemObserver*> clientListOut(0);
291 mParent->mDataItemIndex->remove(
292 each, list<IDataItemObserver*> (1,mClient), clientListOut);
293 // check if there are any other subscribed client for this data item id
294 mParent->mDataItemIndex->getListOfSubscribedClients(each, clientListSubs);
295 if (clientListSubs.empty())
296 {
297 LOC_LOGD("Client list subscribed is empty for dataitem - %d", each);
298 unsubscribeList.push_back(each);
299 }
300 }
301
302 if (!unsubscribeList.empty()) {
303 // Send unsubscribe to framework
304 mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
305 LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
306 mParent->logMe(unsubscribeList);
307 }
308 }
309 SystemStatusOsObserver* mParent;
310 IDataItemObserver* mClient;
311 const list<DataItemId> mDataItemList;
312 };
313 mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeReq(this, l, client));
314 }
315
unsubscribeAll(IDataItemObserver * client)316 void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
317 {
318 if (nullptr == mContext.mSubscriptionObj) {
319 LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
320 return;
321 }
322
323 struct HandleUnsubscribeAllReq : public LocMsg {
324 HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
325 IDataItemObserver* client) :
326 mParent(parent), mClient(client) {}
327 virtual ~HandleUnsubscribeAllReq() {}
328 void proc() const {
329 list<IDataItemObserver*> clients(1, mClient);
330 list<DataItemId> unsubscribeList(0);
331 if(0 == mParent->mClientIndex->remove(mClient)) {
332 return;
333 }
334 mParent->mDataItemIndex->remove(clients, unsubscribeList);
335
336 if (!unsubscribeList.empty()) {
337 // Send unsubscribe to framework
338 mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
339 LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
340 mParent->logMe(unsubscribeList);
341 }
342 }
343 SystemStatusOsObserver* mParent;
344 IDataItemObserver* mClient;
345 };
346 mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeAllReq(this, client));
347 }
348
349 /******************************************************************************
350 IDataItemObserver Overrides
351 ******************************************************************************/
notify(const list<IDataItemCore * > & dlist)352 void SystemStatusOsObserver::notify(const list<IDataItemCore*>& dlist)
353 {
354 list<IDataItemCore*> dataItemList(0);
355
356 for (auto each : dlist) {
357 string dv;
358 each->stringify(dv);
359 LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
360
361 IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
362 if (nullptr == di) {
363 LOC_LOGE("Unable to create dataitem:%d", each->getId());
364 return;
365 }
366
367 // Copy contents into the newly created data item
368 di->copy(each);
369 dataItemList.push_back(di);
370 // Request systemstatus to record this dataitem in its cache
371 SystemStatus* systemstatus = SystemStatus::getInstance(mContext.mMsgTask);
372 if(nullptr != systemstatus) {
373 systemstatus->eventDataItemNotify(di);
374 }
375 }
376
377 struct HandleNotify : public LocMsg {
378 HandleNotify(SystemStatusOsObserver* parent, const list<IDataItemCore*>& l) :
379 mParent(parent), mDList(l) {}
380 virtual ~HandleNotify() {
381 for (auto each : mDList) {
382 delete each;
383 }
384 }
385 void proc() const {
386 // Update Cache with received data items and prepare
387 // list of data items to be sent.
388 list<DataItemId> dataItemIdsToBeSent(0);
389 for (auto item : mDList) {
390 bool dataItemUpdated = false;
391 mParent->updateCache(item, dataItemUpdated);
392 if (dataItemUpdated) {
393 dataItemIdsToBeSent.push_back(item->getId());
394 }
395 }
396
397 // Send data item to all subscribed clients
398 list<IDataItemObserver*> clientList(0);
399 for (auto each : dataItemIdsToBeSent) {
400 list<IDataItemObserver*> clients(0);
401 mParent->mDataItemIndex->getListOfSubscribedClients(each, clients);
402 for (auto each_cient: clients) {
403 clientList.push_back(each_cient);
404 }
405 }
406 clientList.unique();
407
408 for (auto client : clientList) {
409 list<DataItemId> dataItemIdsSubscribedByThisClient(0);
410 list<DataItemId> dataItemIdsToBeSentForThisClient(0);
411 mParent->mClientIndex->getSubscribedList(
412 client, dataItemIdsSubscribedByThisClient);
413 dataItemIdsSubscribedByThisClient.sort();
414 dataItemIdsToBeSent.sort();
415
416 set_intersection(dataItemIdsToBeSent.begin(),
417 dataItemIdsToBeSent.end(),
418 dataItemIdsSubscribedByThisClient.begin(),
419 dataItemIdsSubscribedByThisClient.end(),
420 inserter(dataItemIdsToBeSentForThisClient,
421 dataItemIdsToBeSentForThisClient.begin()));
422
423 mParent->sendCachedDataItems(dataItemIdsToBeSentForThisClient, client);
424 dataItemIdsSubscribedByThisClient.clear();
425 dataItemIdsToBeSentForThisClient.clear();
426 }
427 }
428 SystemStatusOsObserver* mParent;
429 const list<IDataItemCore*> mDList;
430 };
431 mContext.mMsgTask->sendMsg(new (nothrow) HandleNotify(this, dataItemList));
432 }
433
434 /******************************************************************************
435 IFrameworkActionReq Overrides
436 ******************************************************************************/
turnOn(DataItemId dit,int timeOut)437 void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
438 {
439 if (nullptr == mContext.mFrameworkActionReqObj) {
440 LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
441 return;
442 }
443
444 // Check if data item exists in mActiveRequestCount
445 map<DataItemId, int>::iterator citer = mActiveRequestCount.find(dit);
446 if (citer == mActiveRequestCount.end()) {
447 // Data item not found in map
448 // Add reference count as 1 and add dataitem to map
449 pair<DataItemId, int> cpair(dit, 1);
450 mActiveRequestCount.insert(cpair);
451 LOC_LOGD("Sending turnOn request");
452
453 // Send action turn on to framework
454 struct HandleTurnOnMsg : public LocMsg {
455 HandleTurnOnMsg(IFrameworkActionReq* framework,
456 DataItemId dit, int timeOut) :
457 mFrameworkActionReqObj(framework), mDataItemId(dit), mTimeOut(timeOut) {}
458 virtual ~HandleTurnOnMsg() {}
459 void proc() const {
460 mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut);
461 }
462 IFrameworkActionReq* mFrameworkActionReqObj;
463 DataItemId mDataItemId;
464 int mTimeOut;
465 };
466 mContext.mMsgTask->sendMsg(new (nothrow) HandleTurnOnMsg(this, dit, timeOut));
467 }
468 else {
469 // Found in map, update reference count
470 citer->second++;
471 LOC_LOGD("turnOn - Data item:%d Num_refs:%d", dit, citer->second);
472 }
473 }
474
turnOff(DataItemId dit)475 void SystemStatusOsObserver::turnOff(DataItemId dit)
476 {
477 if (nullptr == mContext.mFrameworkActionReqObj) {
478 LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
479 return;
480 }
481
482 // Check if data item exists in mActiveRequestCount
483 map<DataItemId, int>::iterator citer = mActiveRequestCount.find(dit);
484 if (citer != mActiveRequestCount.end()) {
485 // found
486 citer->second--;
487 LOC_LOGD("turnOff - Data item:%d Remaining:%d", dit, citer->second);
488 if(citer->second == 0) {
489 // if this was last reference, remove item from map and turn off module
490 mActiveRequestCount.erase(citer);
491
492 // Send action turn off to framework
493 struct HandleTurnOffMsg : public LocMsg {
494 HandleTurnOffMsg(IFrameworkActionReq* framework, DataItemId dit) :
495 mFrameworkActionReqObj(framework), mDataItemId(dit) {}
496 virtual ~HandleTurnOffMsg() {}
497 void proc() const {
498 mFrameworkActionReqObj->turnOff(mDataItemId);
499 }
500 IFrameworkActionReq* mFrameworkActionReqObj;
501 DataItemId mDataItemId;
502 };
503 mContext.mMsgTask->sendMsg(
504 new (nothrow) HandleTurnOffMsg(mContext.mFrameworkActionReqObj, dit));
505 }
506 }
507 }
508
509 /******************************************************************************
510 Helpers
511 ******************************************************************************/
sendFirstResponse(const list<DataItemId> & l,IDataItemObserver * to)512 void SystemStatusOsObserver::sendFirstResponse(
513 const list<DataItemId>& l, IDataItemObserver* to)
514 {
515 if (l.empty()) {
516 LOC_LOGV("list is empty. Nothing to do. Exiting");
517 return;
518 }
519
520 string clientName;
521 to->getName(clientName);
522 list<IDataItemCore*> dataItems(0);
523
524 for (auto each : l) {
525 map<DataItemId, IDataItemCore*>::const_iterator citer = mDataItemCache.find(each);
526 if (citer != mDataItemCache.end()) {
527 string dv;
528 citer->second->stringify(dv);
529 LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
530 dataItems.push_back(citer->second);
531 }
532 }
533 if (dataItems.empty()) {
534 LOC_LOGV("No items to notify. Nothing to do. Exiting");
535 return;
536 }
537 to->notify(dataItems);
538 }
539
sendCachedDataItems(const list<DataItemId> & l,IDataItemObserver * to)540 void SystemStatusOsObserver::sendCachedDataItems(
541 const list<DataItemId>& l, IDataItemObserver* to)
542 {
543 string clientName;
544 to->getName(clientName);
545 list<IDataItemCore*> dataItems(0);
546
547 for (auto each : l) {
548 string dv;
549 IDataItemCore* di = mDataItemCache[each];
550 di->stringify(dv);
551 LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
552 dataItems.push_back(di);
553 }
554 to->notify(dataItems);
555 }
556
updateCache(IDataItemCore * d,bool & dataItemUpdated)557 void SystemStatusOsObserver::updateCache(IDataItemCore* d, bool& dataItemUpdated)
558 {
559 if (nullptr == d) {
560 return;
561 }
562
563 // Check if data item exists in cache
564 map<DataItemId, IDataItemCore*>::iterator citer =
565 mDataItemCache.find(d->getId());
566 if (citer == mDataItemCache.end()) {
567 // New data item; not found in cache
568 IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
569 if (nullptr == dataitem) {
570 return;
571 }
572
573 // Copy the contents of the data item
574 dataitem->copy(d);
575 pair<DataItemId, IDataItemCore*> cpair(d->getId(), dataitem);
576 // Insert in mDataItemCache
577 mDataItemCache.insert(cpair);
578 dataItemUpdated = true;
579 }
580 else {
581 // Found in cache; Update cache if necessary
582 if(0 == citer->second->copy(d, &dataItemUpdated)) {
583 return;
584 }
585 }
586
587 if (dataItemUpdated) {
588 LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
589 }
590 }
591
592 } // namespace loc_core
593
594