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