Home | History | Annotate | Download | only in core
      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 {
     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 
     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 
     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
     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 ******************************************************************************/
    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 
    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 
    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 
    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 
    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 ******************************************************************************/
    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 ******************************************************************************/
    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 
    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 ******************************************************************************/
    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 
    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 
    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