changed SystemStatusOsObserver

to allow clients to subscribe before subscription obj arrives,
and also simplified ClientIndex and DataItemIndex implementation
significantly.

Change-Id: I092f344e688fa698aa98795b8a8f0c1ba8fcd9e4
CRs-Fixed: 2218519
diff --git a/sdm845/core/Android.mk b/sdm845/core/Android.mk
index 6d1dd11..b1fcc0d 100644
--- a/sdm845/core/Android.mk
+++ b/sdm845/core/Android.mk
@@ -30,9 +30,6 @@
     LocDualContext.cpp \
     loc_core_log.cpp \
     data-items/DataItemsFactoryProxy.cpp \
-    data-items/common/ClientIndex.cpp \
-    data-items/common/DataItemIndex.cpp \
-    data-items/common/IndexFactory.cpp \
     SystemStatusOsObserver.cpp \
     SystemStatus.cpp
 
diff --git a/sdm845/core/Makefile.am b/sdm845/core/Makefile.am
index dc540e9..77bc610 100644
--- a/sdm845/core/Makefile.am
+++ b/sdm845/core/Makefile.am
@@ -37,9 +37,6 @@
            LocDualContext.cpp \
            loc_core_log.cpp \
            data-items/DataItemsFactoryProxy.cpp \
-           data-items/common/ClientIndex.cpp \
-           data-items/common/DataItemIndex.cpp \
-           data-items/common/IndexFactory.cpp \
            SystemStatusOsObserver.cpp \
            SystemStatus.cpp
 
diff --git a/sdm845/core/SystemStatus.cpp b/sdm845/core/SystemStatus.cpp
index 6eb9968..e12d9f3 100644
--- a/sdm845/core/SystemStatus.cpp
+++ b/sdm845/core/SystemStatus.cpp
@@ -1694,9 +1694,7 @@
 
         // send networkinof dataitem to systemstatus observer clients
         SystemStatusNetworkInfo s(type, "", "", false, connected, false);
-        list<IDataItemCore*> dl(0);
-        dl.push_back(&s);
-        mSysStatusObsvr.notify(dl);
+        mSysStatusObsvr.notify({&s});
     }
     return true;
 }
diff --git a/sdm845/core/SystemStatusOsObserver.cpp b/sdm845/core/SystemStatusOsObserver.cpp
index 2fdd19f..0f6d228 100644
--- a/sdm845/core/SystemStatusOsObserver.cpp
+++ b/sdm845/core/SystemStatusOsObserver.cpp
@@ -32,28 +32,20 @@
 #include <SystemStatus.h>
 #include <SystemStatusOsObserver.h>
 #include <IDataItemCore.h>
-#include <IClientIndex.h>
-#include <IDataItemIndex.h>
-#include <IndexFactory.h>
 #include <DataItemsFactoryProxy.h>
 
 namespace loc_core
 {
-SystemStatusOsObserver::SystemStatusOsObserver(
-    SystemStatus* systemstatus, const MsgTask* msgTask) :
-    mSystemStatus(systemstatus),
-    mAddress("SystemStatusOsObserver"),
-#ifdef USE_GLIB
-    mBackHaulConnectReqCount(0),
-#endif
-    mClientIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createClientIndex()),
-    mDataItemIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createDataItemIndex())
-{
-    mContext.mMsgTask = msgTask;
+template <typename CINT, typename COUT>
+COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
+    COUT outContainer(0);
+    for (auto item : inContainer) {
+        outContainer.insert(outContainer.begin(), item);
+    }
+    return outContainer;
 }
 
-SystemStatusOsObserver::~SystemStatusOsObserver()
-{
+SystemStatusOsObserver::~SystemStatusOsObserver() {
     // Close data-item library handle
     DataItemsFactoryProxy::closeDataItemLibraryHandle();
 
@@ -65,290 +57,238 @@
     }
 
     mDataItemCache.clear();
-    delete mClientIndex;
-    delete mDataItemIndex;
 }
 
 void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
 {
-    mContext.mSubscriptionObj = subscriptionObj;
+    struct SetSubsObj : public LocMsg {
+        ObserverContext& mContext;
+        IDataItemSubscription* mSubsObj;
+        inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
+                mContext(context), mSubsObj(subscriptionObj) {}
+        void proc() const {
+            mContext.mSubscriptionObj = mSubsObj;
 
-    LOC_LOGD("Request cache size -  Subscribe:%zu RequestData:%zu",
-            mSubscribeReqCache.size(), mReqDataCache.size());
-
-    // we have received the subscription object. process cached requests
-    // process - subscribe request cache
-    for (auto each : mSubscribeReqCache) {
-        subscribe(each.second, each.first);
-    }
-    // process - requestData request cache
-    for (auto each : mReqDataCache) {
-        requestData(each.second, each.first);
-    }
-}
-
-// Helper to cache requests subscribe and requestData till subscription obj is obtained
-void SystemStatusOsObserver::cacheObserverRequest(ObserverReqCache& reqCache,
-        const list<DataItemId>& l, IDataItemObserver* client)
-{
-    ObserverReqCache::iterator dicIter = reqCache.find(client);
-    if (dicIter != reqCache.end()) {
-        // found
-        list<DataItemId> difference(0);
-        set_difference(l.begin(), l.end(),
-                dicIter->second.begin(), dicIter->second.end(),
-                inserter(difference, difference.begin()));
-        if (!difference.empty()) {
-            difference.sort();
-            dicIter->second.merge(difference);
-            dicIter->second.unique();
+            if (!mContext.mSSObserver->mDataItemToClients.empty()) {
+                list<DataItemId> dis(
+                        containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                mContext.mSSObserver->mDataItemToClients.getKeys()));
+                mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
+                mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
+            }
         }
-    }
-    else {
-        // not found
-        reqCache[client] = l;
+    };
+
+    if (nullptr == subscriptionObj) {
+        LOC_LOGw("subscriptionObj is NULL");
+    } else {
+        mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
     }
 }
 
 /******************************************************************************
  IDataItemSubscription Overrides
 ******************************************************************************/
-void SystemStatusOsObserver::subscribe(
-        const list<DataItemId>& l, IDataItemObserver* client)
+void SystemStatusOsObserver::subscribe(const list<DataItemId>& l, IDataItemObserver* client,
+                                       bool toRequestData)
 {
-    if (nullptr == mContext.mSubscriptionObj) {
-        LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__);
-        cacheObserverRequest(mSubscribeReqCache, l, client);
-        return;
-    }
-
     struct HandleSubscribeReq : public LocMsg {
-        HandleSubscribeReq(SystemStatusOsObserver* parent,
-                const list<DataItemId>& l, IDataItemObserver* client) :
-                mParent(parent), mClient(client), mDataItemList(l) {}
-        virtual ~HandleSubscribeReq() {}
+        inline HandleSubscribeReq(SystemStatusOsObserver* parent,
+                list<DataItemId>& l, IDataItemObserver* client, bool requestData) :
+                mParent(parent), mClient(client),
+                mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)),
+                mToRequestData(requestData) {}
+
         void proc() const {
+            unordered_set<DataItemId> dataItemsToSubscribe(0);
+            mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
+            mParent->mClientToDataItems.add(mClient, mDataItemSet);
 
-            if (mDataItemList.empty()) {
-                LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
-                return;
-            }
+            mParent->sendCachedDataItems(mDataItemSet, mClient);
 
-            // Handle First Response
-            list<DataItemId> pendingFirstResponseList(0);
-            mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList);
-
-            // Do not send first response for only pendingFirstResponseList,
-            // instead send for all the data items  (present in the cache) that
-            // have been subscribed for each time.
-            mParent->sendFirstResponse(mDataItemList, mClient);
-
-            list<DataItemId> yetToSubscribeDataItemsList(0);
-            mParent->mDataItemIndex->add(mClient, mDataItemList, yetToSubscribeDataItemsList);
-
-            // Send subscription list to framework
-            if (!yetToSubscribeDataItemsList.empty()) {
-                mParent->mContext.mSubscriptionObj->subscribe(yetToSubscribeDataItemsList, mParent);
+            // Send subscription set to framework
+            if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToSubscribe.empty()) {
                 LOC_LOGD("Subscribe Request sent to framework for the following");
-                mParent->logMe(yetToSubscribeDataItemsList);
+                mParent->logMe(dataItemsToSubscribe);
+
+                if (mToRequestData) {
+                    mParent->mContext.mSubscriptionObj->requestData(
+                            containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                    std::move(dataItemsToSubscribe)),
+                            mParent);
+                } else {
+                    mParent->mContext.mSubscriptionObj->subscribe(
+                            containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                    std::move(dataItemsToSubscribe)),
+                            mParent);
+                }
             }
         }
-        SystemStatusOsObserver* mParent;
+        mutable SystemStatusOsObserver* mParent;
         IDataItemObserver* mClient;
-        const list<DataItemId> mDataItemList;
+        const unordered_set<DataItemId> mDataItemSet;
+        bool mToRequestData;
     };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleSubscribeReq(this, l, client));
+
+    if (l.empty() || nullptr == client) {
+        LOC_LOGw("Data item set is empty or client is nullptr");
+    } else {
+        mContext.mMsgTask->sendMsg(
+                new HandleSubscribeReq(this, (list<DataItemId>&)l, client, toRequestData));
+    }
 }
 
 void SystemStatusOsObserver::updateSubscription(
         const list<DataItemId>& l, IDataItemObserver* client)
 {
-    if (nullptr == mContext.mSubscriptionObj) {
-        LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
-        return;
-    }
-
     struct HandleUpdateSubscriptionReq : public LocMsg {
         HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
-                const list<DataItemId>& l, IDataItemObserver* client) :
-                mParent(parent), mClient(client), mDataItemList(l) {}
-        virtual ~HandleUpdateSubscriptionReq() {}
+                                    list<DataItemId>& l, IDataItemObserver* client) :
+                mParent(parent), mClient(client),
+                mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
+
         void proc() const {
-            if (mDataItemList.empty()) {
-                LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
-                return;
-            }
-
-            list<DataItemId> currentlySubscribedList(0);
-            mParent->mClientIndex->getSubscribedList(mClient, currentlySubscribedList);
-
-            list<DataItemId> removeDataItemList(0);
-            set_difference(currentlySubscribedList.begin(), currentlySubscribedList.end(),
-                    mDataItemList.begin(), mDataItemList.end(),
-                    inserter(removeDataItemList,removeDataItemList.begin()));
-
-            // Handle First Response
-            list<DataItemId> pendingFirstResponseList(0);
-            mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList);
+            unordered_set<DataItemId> dataItemsToSubscribe(0);
+            unordered_set<DataItemId> dataItemsToUnsubscribe(0);
+            unordered_set<IDataItemObserver*> clients({mClient});
+            // below removes clients from all entries keyed with the return of the
+            // mClientToDataItems.update() call. If leaving an empty set of clients as the
+            // result, the entire entry will be removed. dataItemsToUnsubscribe will be
+            // populated to keep the keys of the removed entries.
+            mParent->mDataItemToClients.trimOrRemove(
+                    // this call updates <IDataItemObserver*, DataItemId> map; removes
+                    // the DataItemId's that are not new to the clietn from mDataItemSet;
+                    // and returns a set of mDataItemSet's that are no longer used by client.
+                    // This unused set of mDataItemSet's is passed to trimOrRemove method of
+                    // <DataItemId, IDataItemObserver*> map to remove the client from the
+                    // corresponding entries, and gets a set of the entries that are
+                    // removed from the <DataItemId, IDataItemObserver*> map as a result.
+                    mParent->mClientToDataItems.update(mClient,
+                                                       (unordered_set<DataItemId>&)mDataItemSet),
+                    clients, &dataItemsToUnsubscribe, nullptr);
+            // below adds mClient to <DataItemId, IDataItemObserver*> map, and populates
+            // new keys added to that map, which are DataItemIds to be subscribed.
+            mParent->mDataItemToClients.add(mDataItemSet, clients, &dataItemsToSubscribe);
 
             // Send First Response
-            mParent->sendFirstResponse(pendingFirstResponseList, mClient);
+            mParent->sendCachedDataItems(mDataItemSet, mClient);
 
-            list<DataItemId> yetToSubscribeDataItemsList(0);
-            mParent->mDataItemIndex->add(
-                    mClient, mDataItemList, yetToSubscribeDataItemsList);
+            if (nullptr != mParent->mContext.mSubscriptionObj) {
+                // Send subscription set to framework
+                if (!dataItemsToSubscribe.empty()) {
+                    LOC_LOGD("Subscribe Request sent to framework for the following");
+                    mParent->logMe(dataItemsToSubscribe);
 
-            // Send subscription list to framework
-            if (!yetToSubscribeDataItemsList.empty()) {
-                mParent->mContext.mSubscriptionObj->subscribe(
-                        yetToSubscribeDataItemsList, mParent);
-                LOC_LOGD("Subscribe Request sent to framework for the following");
-                mParent->logMe(yetToSubscribeDataItemsList);
-            }
+                    mParent->mContext.mSubscriptionObj->subscribe(
+                            containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                    std::move(dataItemsToSubscribe)),
+                            mParent);
+                }
 
-            list<DataItemId> unsubscribeList(0);
-            list<DataItemId> unused(0);
-            mParent->mClientIndex->remove(mClient, removeDataItemList, unused);
-
-            if (!mParent->mClientIndex->isSubscribedClient(mClient)) {
-                mParent->mDataItemIndex->remove(
-                        list<IDataItemObserver*> (1,mClient), unsubscribeList);
-            }
-            if (!unsubscribeList.empty()) {
                 // Send unsubscribe to framework
-                mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
-                LOC_LOGD("Unsubscribe Request sent to framework for the following");
-                mParent->logMe(unsubscribeList);
+                if (!dataItemsToUnsubscribe.empty()) {
+                    LOC_LOGD("Unsubscribe Request sent to framework for the following");
+                    mParent->logMe(dataItemsToUnsubscribe);
+
+                    mParent->mContext.mSubscriptionObj->unsubscribe(
+                            containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                    std::move(dataItemsToUnsubscribe)),
+                            mParent);
+                }
             }
         }
         SystemStatusOsObserver* mParent;
         IDataItemObserver* mClient;
-        const list<DataItemId> mDataItemList;
+        unordered_set<DataItemId> mDataItemSet;
     };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleUpdateSubscriptionReq(this, l, client));
-}
 
-void SystemStatusOsObserver::requestData(
-        const list<DataItemId>& l, IDataItemObserver* client)
-{
-    if (nullptr == mContext.mSubscriptionObj) {
-        LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__);
-        cacheObserverRequest(mReqDataCache, l, client);
-        return;
+    if (l.empty() || nullptr == client) {
+        LOC_LOGw("Data item set is empty or client is nullptr");
+    } else {
+        mContext.mMsgTask->sendMsg(
+                new HandleUpdateSubscriptionReq(this, (list<DataItemId>&)l, client));
     }
-
-    struct HandleRequestData : public LocMsg {
-        HandleRequestData(SystemStatusOsObserver* parent,
-                const list<DataItemId>& l, IDataItemObserver* client) :
-                mParent(parent), mClient(client), mDataItemList(l) {}
-        virtual ~HandleRequestData() {}
-        void proc() const {
-            if (mDataItemList.empty()) {
-                LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
-                return;
-            }
-
-            list<DataItemId> yetToSubscribeDataItemsList(0);
-            mParent->mClientIndex->add(
-                    mClient, mDataItemList, yetToSubscribeDataItemsList);
-            mParent->mDataItemIndex->add(
-                    mClient, mDataItemList, yetToSubscribeDataItemsList);
-
-            // Send subscription list to framework
-            if (!mDataItemList.empty()) {
-                mParent->mContext.mSubscriptionObj->requestData(mDataItemList, mParent);
-                LOC_LOGD("Subscribe Request sent to framework for the following");
-                mParent->logMe(yetToSubscribeDataItemsList);
-            }
-        }
-        SystemStatusOsObserver* mParent;
-        IDataItemObserver* mClient;
-        const list<DataItemId> mDataItemList;
-    };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleRequestData(this, l, client));
 }
 
 void SystemStatusOsObserver::unsubscribe(
         const list<DataItemId>& l, IDataItemObserver* client)
 {
-    if (nullptr == mContext.mSubscriptionObj) {
-        LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
-        return;
-    }
     struct HandleUnsubscribeReq : public LocMsg {
         HandleUnsubscribeReq(SystemStatusOsObserver* parent,
-                const list<DataItemId>& l, IDataItemObserver* client) :
-                mParent(parent), mClient(client), mDataItemList(l) {}
-        virtual ~HandleUnsubscribeReq() {}
+                list<DataItemId>& l, IDataItemObserver* client) :
+                mParent(parent), mClient(client),
+                mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
+
         void proc() const {
-            if (mDataItemList.empty()) {
-                LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
-                return;
-            }
+            unordered_set<DataItemId> dataItemsUnusedByClient(0);
+            unordered_set<IDataItemObserver*> clientToRemove(0);
+            mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet,  &clientToRemove,
+                                                     &dataItemsUnusedByClient);
+            unordered_set<DataItemId> dataItemsToUnsubscribe(0);
+            mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
+                                                     &dataItemsToUnsubscribe, nullptr);
 
-            list<DataItemId> unsubscribeList(0);
-            list<DataItemId> unused(0);
-            mParent->mClientIndex->remove(mClient, mDataItemList, unused);
-
-            for (auto each : mDataItemList) {
-                list<IDataItemObserver*> clientListSubs(0);
-                list<IDataItemObserver*> clientListOut(0);
-                mParent->mDataItemIndex->remove(
-                        each, list<IDataItemObserver*> (1,mClient), clientListOut);
-                // check if there are any other subscribed client for this data item id
-                mParent->mDataItemIndex->getListOfSubscribedClients(each, clientListSubs);
-                if (clientListSubs.empty())
-                {
-                    LOC_LOGD("Client list subscribed is empty for dataitem - %d", each);
-                    unsubscribeList.push_back(each);
-                }
-            }
-
-            if (!unsubscribeList.empty()) {
-                // Send unsubscribe to framework
-                mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
+            if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
                 LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
-                mParent->logMe(unsubscribeList);
+                mParent->logMe(dataItemsToUnsubscribe);
+
+                // Send unsubscribe to framework
+                mParent->mContext.mSubscriptionObj->unsubscribe(
+                        containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                  std::move(dataItemsToUnsubscribe)),
+                        mParent);
             }
         }
         SystemStatusOsObserver* mParent;
         IDataItemObserver* mClient;
-        const list<DataItemId> mDataItemList;
+        unordered_set<DataItemId> mDataItemSet;
     };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeReq(this, l, client));
+
+    if (l.empty() || nullptr == client) {
+        LOC_LOGw("Data item set is empty or client is nullptr");
+    } else {
+        mContext.mMsgTask->sendMsg(new HandleUnsubscribeReq(this, (list<DataItemId>&)l, client));
+    }
 }
 
 void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
 {
-    if (nullptr == mContext.mSubscriptionObj) {
-        LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
-        return;
-    }
-
     struct HandleUnsubscribeAllReq : public LocMsg {
         HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
                 IDataItemObserver* client) :
                 mParent(parent), mClient(client) {}
-        virtual ~HandleUnsubscribeAllReq() {}
-        void proc() const {
-            list<IDataItemObserver*> clients(1, mClient);
-            list<DataItemId> unsubscribeList(0);
-            if(0 == mParent->mClientIndex->remove(mClient)) {
-                return;
-            }
-            mParent->mDataItemIndex->remove(clients, unsubscribeList);
 
-            if (!unsubscribeList.empty()) {
-                // Send unsubscribe to framework
-                mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
-                LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
-                mParent->logMe(unsubscribeList);
+        void proc() const {
+            unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
+            if (!diByClient.empty()) {
+                unordered_set<DataItemId> dataItemsToUnsubscribe;
+                mParent->mClientToDataItems.remove(mClient);
+                mParent->mDataItemToClients.trimOrRemove(diByClient, {mClient},
+                                                         &dataItemsToUnsubscribe, nullptr);
+
+                if (!dataItemsToUnsubscribe.empty() &&
+                    nullptr != mParent->mContext.mSubscriptionObj) {
+
+                    LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
+                    mParent->logMe(dataItemsToUnsubscribe);
+
+                    // Send unsubscribe to framework
+                    mParent->mContext.mSubscriptionObj->unsubscribe(
+                            containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+                                    std::move(dataItemsToUnsubscribe)),
+                            mParent);
+                }
             }
         }
         SystemStatusOsObserver* mParent;
         IDataItemObserver* mClient;
     };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeAllReq(this, client));
+
+    if (nullptr == client) {
+        LOC_LOGw("Data item set is empty or client is nullptr");
+    } else {
+        mContext.mMsgTask->sendMsg(new HandleUnsubscribeAllReq(this, client));
+    }
 }
 
 /******************************************************************************
@@ -356,84 +296,78 @@
 ******************************************************************************/
 void SystemStatusOsObserver::notify(const list<IDataItemCore*>& dlist)
 {
-    list<IDataItemCore*> dataItemList(0);
-
-    for (auto each : dlist) {
-        string dv;
-        each->stringify(dv);
-        LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
-
-        IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
-        if (nullptr == di) {
-            LOC_LOGE("Unable to create dataitem:%d", each->getId());
-            return;
-        }
-
-        // Copy contents into the newly created data item
-        di->copy(each);
-
-        // Request systemstatus to record this dataitem in its cache
-        if (mSystemStatus->eventDataItemNotify(di)) {
-            // add this dataitem if updated from last one
-            dataItemList.push_back(di);
-        }
-    }
-
     struct HandleNotify : public LocMsg {
-        HandleNotify(SystemStatusOsObserver* parent, const list<IDataItemCore*>& l) :
-            mParent(parent), mDList(l) {}
-        virtual ~HandleNotify() {
-            for (auto each : mDList) {
-                delete each;
+        HandleNotify(SystemStatusOsObserver* parent, vector<IDataItemCore*>& v) :
+                mParent(parent), mDiVec(std::move(v)) {}
+
+        inline virtual ~HandleNotify() {
+            for (auto item : mDiVec) {
+                delete item;
             }
         }
+
         void proc() const {
             // Update Cache with received data items and prepare
             // list of data items to be sent.
-            list<DataItemId> dataItemIdsToBeSent(0);
-            for (auto item : mDList) {
-                bool dataItemUpdated = false;
-                mParent->updateCache(item, dataItemUpdated);
-                if (dataItemUpdated) {
-                    dataItemIdsToBeSent.push_back(item->getId());
+            unordered_set<DataItemId> dataItemIdsToBeSent(0);
+            for (auto item : mDiVec) {
+                if (mParent->updateCache(item)) {
+                    dataItemIdsToBeSent.insert(item->getId());
                 }
             }
 
             // Send data item to all subscribed clients
-            list<IDataItemObserver*> clientList(0);
+            unordered_set<IDataItemObserver*> clientSet(0);
             for (auto each : dataItemIdsToBeSent) {
-                list<IDataItemObserver*> clients(0);
-                mParent->mDataItemIndex->getListOfSubscribedClients(each, clients);
-                for (auto each_cient: clients) {
-                    clientList.push_back(each_cient);
+                auto clients = mParent->mDataItemToClients.getValSetPtr(each);
+                if (nullptr != clients) {
+                    clientSet.insert(clients->begin(), clients->end());
                 }
             }
-            clientList.unique();
 
-            for (auto client : clientList) {
-                list<DataItemId> dataItemIdsSubscribedByThisClient(0);
-                list<DataItemId> dataItemIdsToBeSentForThisClient(0);
-                mParent->mClientIndex->getSubscribedList(
-                        client, dataItemIdsSubscribedByThisClient);
-                dataItemIdsSubscribedByThisClient.sort();
-                dataItemIdsToBeSent.sort();
+            for (auto client : clientSet) {
+                unordered_set<DataItemId> dataItemIdsForThisClient(
+                        mParent->mClientToDataItems.getValSet(client));
+                for (auto id : dataItemIdsForThisClient) {
+                    if (dataItemIdsToBeSent.find(id) == dataItemIdsToBeSent.end()) {
+                        dataItemIdsForThisClient.erase(id);
+                    }
+                }
 
-                set_intersection(dataItemIdsToBeSent.begin(),
-                        dataItemIdsToBeSent.end(),
-                        dataItemIdsSubscribedByThisClient.begin(),
-                        dataItemIdsSubscribedByThisClient.end(),
-                        inserter(dataItemIdsToBeSentForThisClient,
-                        dataItemIdsToBeSentForThisClient.begin()));
-
-                mParent->sendCachedDataItems(dataItemIdsToBeSentForThisClient, client);
-                dataItemIdsSubscribedByThisClient.clear();
-                dataItemIdsToBeSentForThisClient.clear();
+                mParent->sendCachedDataItems(dataItemIdsForThisClient, client);
             }
         }
         SystemStatusOsObserver* mParent;
-        const list<IDataItemCore*> mDList;
+        const vector<IDataItemCore*> mDiVec;
     };
-    mContext.mMsgTask->sendMsg(new (nothrow) HandleNotify(this, dataItemList));
+
+    if (!dlist.empty()) {
+        vector<IDataItemCore*> dataItemVec(dlist.size());
+
+        for (auto each : dlist) {
+            IF_LOC_LOGD {
+                string dv;
+                each->stringify(dv);
+                LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
+            }
+
+            IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
+            if (nullptr == di) {
+                LOC_LOGw("Unable to create dataitem:%d", each->getId());
+                continue;
+            }
+
+            // Copy contents into the newly created data item
+            di->copy(each);
+
+            // add this dataitem if updated from last one
+            dataItemVec.push_back(di);
+        }
+
+        if (!dataItemVec.empty()) {
+            mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
+        }
+    }
 }
 
 /******************************************************************************
@@ -447,7 +381,7 @@
     }
 
     // Check if data item exists in mActiveRequestCount
-    map<DataItemId, int>::iterator citer = mActiveRequestCount.find(dit);
+    DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
     if (citer == mActiveRequestCount.end()) {
         // Data item not found in map
         // Add reference count as 1 and add dataitem to map
@@ -485,7 +419,7 @@
     }
 
     // Check if data item exists in mActiveRequestCount
-    map<DataItemId, int>::iterator citer = mActiveRequestCount.find(dit);
+    DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
     if (citer != mActiveRequestCount.end()) {
         // found
         citer->second--;
@@ -573,84 +507,65 @@
 /******************************************************************************
  Helpers
 ******************************************************************************/
-void SystemStatusOsObserver::sendFirstResponse(
-        const list<DataItemId>& l, IDataItemObserver* to)
-{
-    if (l.empty()) {
-        LOC_LOGV("list is empty. Nothing to do. Exiting");
-        return;
-    }
-
-    string clientName;
-    to->getName(clientName);
-    list<IDataItemCore*> dataItems(0);
-
-    for (auto each : l) {
-        map<DataItemId, IDataItemCore*>::const_iterator citer = mDataItemCache.find(each);
-        if (citer != mDataItemCache.end()) {
-            string dv;
-            citer->second->stringify(dv);
-            LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
-            dataItems.push_back(citer->second);
-        }
-    }
-    if (dataItems.empty()) {
-        LOC_LOGV("No items to notify. Nothing to do. Exiting");
-        return;
-    }
-    to->notify(dataItems);
-}
-
 void SystemStatusOsObserver::sendCachedDataItems(
-        const list<DataItemId>& l, IDataItemObserver* to)
+        const unordered_set<DataItemId>& s, IDataItemObserver* to)
 {
-    string clientName;
-    to->getName(clientName);
-    list<IDataItemCore*> dataItems(0);
+    if (nullptr == to) {
+        LOC_LOGv("client pointer is NULL.");
+    } else {
+        string clientName;
+        to->getName(clientName);
+        list<IDataItemCore*> dataItems(0);
 
-    for (auto each : l) {
-        string dv;
-        IDataItemCore* di = mDataItemCache[each];
-        di->stringify(dv);
-        LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
-        dataItems.push_back(di);
+        for (auto each : s) {
+            auto citer = mDataItemCache.find(each);
+            if (citer != mDataItemCache.end()) {
+                string dv;
+                citer->second->stringify(dv);
+                LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
+                dataItems.push_front(citer->second);
+            }
+        }
+
+        if (dataItems.empty()) {
+            LOC_LOGv("No items to notify.");
+        } else {
+            to->notify(dataItems);
+        }
     }
-    to->notify(dataItems);
 }
 
-void SystemStatusOsObserver::updateCache(IDataItemCore* d, bool& dataItemUpdated)
+bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
 {
-    if (nullptr == d) {
-        return;
-    }
+    bool dataItemUpdated = false;
 
-    // Check if data item exists in cache
-    map<DataItemId, IDataItemCore*>::iterator citer =
-            mDataItemCache.find(d->getId());
-    if (citer == mDataItemCache.end()) {
-        // New data item; not found in cache
-        IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
-        if (nullptr == dataitem) {
-            return;
+    // Request systemstatus to record this dataitem in its cache
+    // if the return is false, it means that SystemStatus is not
+    // handling it, so SystemStatusOsObserver also doesn't.
+    // So it has to be true to proceed.
+    if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
+        auto citer = mDataItemCache.find(d->getId());
+        if (citer == mDataItemCache.end()) {
+            // New data item; not found in cache
+            IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
+            if (nullptr != dataitem) {
+                // Copy the contents of the data item
+                dataitem->copy(d);
+                // Insert in mDataItemCache
+                mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
+                dataItemUpdated = true;
+            }
+        } else {
+            // Found in cache; Update cache if necessary
+            citer->second->copy(d, &dataItemUpdated);
         }
 
-        // Copy the contents of the data item
-        dataitem->copy(d);
-        pair<DataItemId, IDataItemCore*> cpair(d->getId(), dataitem);
-        // Insert in mDataItemCache
-        mDataItemCache.insert(cpair);
-        dataItemUpdated = true;
-    }
-    else {
-        // Found in cache; Update cache if necessary
-        if(0 == citer->second->copy(d, &dataItemUpdated)) {
-            return;
+        if (dataItemUpdated) {
+            LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
         }
     }
 
-    if (dataItemUpdated) {
-        LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
-    }
+    return dataItemUpdated;
 }
 
 } // namespace loc_core
diff --git a/sdm845/core/SystemStatusOsObserver.h b/sdm845/core/SystemStatusOsObserver.h
index 930ddc1..fd60606 100644
--- a/sdm845/core/SystemStatusOsObserver.h
+++ b/sdm845/core/SystemStatusOsObserver.h
@@ -41,6 +41,7 @@
 #include <IOsObserver.h>
 #include <loc_pla.h>
 #include <log_util.h>
+#include <LocUnorderedSetMap.h>
 
 namespace loc_core
 {
@@ -48,39 +49,57 @@
  SystemStatusOsObserver
 ******************************************************************************/
 using namespace std;
+using namespace loc_util;
 
 // Forward Declarations
 class IDataItemCore;
-template<typename CT, typename DIT> class IClientIndex;
-template<typename CT, typename DIT> class IDataItemIndex;
+class SystemStatus;
+class SystemStatusOsObserver;
+typedef map<IDataItemObserver*, list<DataItemId>> ObserverReqCache;
+typedef LocUnorderedSetMap<IDataItemObserver*, DataItemId> ClientToDataItems;
+typedef LocUnorderedSetMap<DataItemId, IDataItemObserver*> DataItemToClients;
+typedef unordered_map<DataItemId, IDataItemCore*> DataItemIdToCore;
+typedef unordered_map<DataItemId, int> DataItemIdToInt;
 
-struct SystemContext {
+struct ObserverContext {
     IDataItemSubscription* mSubscriptionObj;
     IFrameworkActionReq* mFrameworkActionReqObj;
     const MsgTask* mMsgTask;
+    SystemStatusOsObserver* mSSObserver;
 
-    inline SystemContext() :
-        mSubscriptionObj(NULL),
-        mFrameworkActionReqObj(NULL),
-        mMsgTask(NULL) {}
+    inline ObserverContext(const MsgTask* msgTask, SystemStatusOsObserver* observer) :
+            mSubscriptionObj(NULL), mFrameworkActionReqObj(NULL),
+            mMsgTask(msgTask), mSSObserver(observer) {}
 };
 
-typedef map<IDataItemObserver*, list<DataItemId>> ObserverReqCache;
-
 // Clients wanting to get data from OS/Framework would need to
 // subscribe with OSObserver using IDataItemSubscription interface.
 // Such clients would need to implement IDataItemObserver interface
 // to receive data when it becomes available.
-class SystemStatus;
 class SystemStatusOsObserver : public IOsObserver {
 
 public:
     // ctor
-    SystemStatusOsObserver(
-            SystemStatus* systemstatus, const MsgTask* msgTask);
+    inline SystemStatusOsObserver(SystemStatus* systemstatus, const MsgTask* msgTask) :
+            mSystemStatus(systemstatus), mContext(msgTask, this),
+            mAddress("SystemStatusOsObserver"),
+            mClientToDataItems(MAX_DATA_ITEM_ID), mDataItemToClients(MAX_DATA_ITEM_ID)
+#ifdef USE_GLIB
+            , mBackHaulConnectReqCount(0)
+#endif
+    {
+    }
+
     // dtor
     ~SystemStatusOsObserver();
 
+    template <typename CINT, typename COUT>
+    static COUT containerTransfer(CINT& s);
+    template <typename CINT, typename COUT>
+    inline static COUT containerTransfer(CINT&& s) {
+        return containerTransfer<CINT, COUT>(s);
+    }
+
     // To set the subscription object
     virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj);
 
@@ -96,38 +115,40 @@
     }
 
     // IDataItemSubscription Overrides
-    virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client);
-    virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client);
-    virtual void requestData(const list<DataItemId>& l, IDataItemObserver* client);
-    virtual void unsubscribe(const list<DataItemId>& l, IDataItemObserver* client);
-    virtual void unsubscribeAll(IDataItemObserver* client);
+    inline virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client) override {
+        subscribe(l, client, false);
+    }
+    virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client) override;
+    inline virtual void requestData(const list<DataItemId>& l, IDataItemObserver* client) override {
+        subscribe(l, client, true);
+    }
+    virtual void unsubscribe(const list<DataItemId>& l, IDataItemObserver* client) override;
+    virtual void unsubscribeAll(IDataItemObserver* client) override;
 
     // IDataItemObserver Overrides
-    virtual void notify(const list<IDataItemCore*>& dlist);
-    inline virtual void getName(string& name) {
+    virtual void notify(const list<IDataItemCore*>& dlist) override;
+    inline virtual void getName(string& name) override {
         name = mAddress;
     }
 
     // IFrameworkActionReq Overrides
-    virtual void turnOn(DataItemId dit, int timeOut = 0);
-    virtual void turnOff(DataItemId dit);
+    virtual void turnOn(DataItemId dit, int timeOut = 0) override;
+    virtual void turnOff(DataItemId dit) override;
 #ifdef USE_GLIB
-    virtual bool connectBackhaul();
+    virtual bool connectBackhaul() override;
     virtual bool disconnectBackhaul();
 #endif
 
 private:
     SystemStatus*                                    mSystemStatus;
-    SystemContext                                    mContext;
+    ObserverContext                                  mContext;
     const string                                     mAddress;
-    IClientIndex<IDataItemObserver*, DataItemId>*    mClientIndex;
-    IDataItemIndex<IDataItemObserver*, DataItemId>*  mDataItemIndex;
-    map<DataItemId, IDataItemCore*>                  mDataItemCache;
-    map<DataItemId, int>                             mActiveRequestCount;
+    ClientToDataItems                                mClientToDataItems;
+    DataItemToClients                                mDataItemToClients;
+    DataItemIdToCore                                 mDataItemCache;
+    DataItemIdToInt                                  mActiveRequestCount;
 
     // Cache the subscribe and requestData till subscription obj is obtained
-    ObserverReqCache mSubscribeReqCache;
-    ObserverReqCache mReqDataCache;
     void cacheObserverRequest(ObserverReqCache& reqCache,
             const list<DataItemId>& l, IDataItemObserver* client);
 #ifdef USE_GLIB
@@ -135,13 +156,16 @@
     int         mBackHaulConnectReqCount;
 #endif
 
+    void subscribe(const list<DataItemId>& l, IDataItemObserver* client, bool toRequestData);
+
     // Helpers
-    void sendFirstResponse(const list<DataItemId>& l, IDataItemObserver* to);
-    void sendCachedDataItems(const list<DataItemId>& l, IDataItemObserver* to);
-    void updateCache(IDataItemCore* d, bool& dataItemUpdated);
-    inline void logMe(const list<DataItemId>& l) {
-        for (auto id : l) {
-            LOC_LOGD("DataItem %d", id);
+    void sendCachedDataItems(const unordered_set<DataItemId>& s, IDataItemObserver* to);
+    bool updateCache(IDataItemCore* d);
+    inline void logMe(const unordered_set<DataItemId>& l) {
+        IF_LOC_LOGD {
+            for (auto id : l) {
+                LOC_LOGD("DataItem %d", id);
+            }
         }
     }
 };
diff --git a/sdm845/core/data-items/common/ClientIndex.cpp b/sdm845/core/data-items/common/ClientIndex.cpp
deleted file mode 100644
index d4bd11e..0000000
--- a/sdm845/core/data-items/common/ClientIndex.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#include <algorithm>
-#include <iterator>
-#include <string>
-#include <loc_pla.h>
-#include <log_util.h>
-#include <ClientIndex.h>
-#include <IDataItemObserver.h>
-#include <DataItemId.h>
-
-using namespace std;
-using namespace loc_core;
-
-template <typename CT, typename DIT>
-inline ClientIndex <CT,DIT> :: ClientIndex () {}
-
-template <typename CT, typename DIT>
-inline ClientIndex <CT,DIT> :: ~ClientIndex () {}
-
-template <typename CT, typename DIT>
-bool ClientIndex <CT,DIT> :: isSubscribedClient (CT client) {
-    bool result = false;
-    ENTRY_LOG ();
-    typename map < CT, list <DIT> > :: iterator it =
-        mDataItemsPerClientMap.find (client);
-    if (it != mDataItemsPerClientMap.end ()) {
-        result = true;
-    }
-    EXIT_LOG_WITH_ERROR ("%d",result);
-    return result;
-}
-
-template <typename CT, typename DIT>
-void ClientIndex <CT,DIT> :: getSubscribedList (CT client, list <DIT> & out) {
-    ENTRY_LOG ();
-    typename map < CT, list <DIT> > :: iterator it =
-        mDataItemsPerClientMap.find (client);
-    if (it != mDataItemsPerClientMap.end ()) {
-        out = it->second;
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-int ClientIndex <CT,DIT> :: remove (CT client) {
-    int result = 0;
-    ENTRY_LOG ();
-    mDataItemsPerClientMap.erase (client);
-    EXIT_LOG_WITH_ERROR ("%d",result);
-    return result;
-}
-
-template <typename CT, typename DIT>
-void ClientIndex <CT,DIT> :: remove (const list <DIT> & r, list <CT> & out) {
-    ENTRY_LOG ();
-    typename map < CT, list <DIT> > :: iterator dicIter =
-        mDataItemsPerClientMap.begin ();
-    while (dicIter != mDataItemsPerClientMap.end()) {
-        typename list <DIT> :: const_iterator it = r.begin ();
-        for (; it != r.end (); ++it) {
-            typename list <DIT> :: iterator iter =
-                find (dicIter->second.begin (), dicIter->second.end (), *it);
-            if (iter != dicIter->second.end ()) {
-                dicIter->second.erase (iter);
-            }
-        }
-        if (dicIter->second.empty ()) {
-            out.push_back (dicIter->first);
-            // Post-increment operator increases the iterator but returns the
-            // prevous one that will be invalidated by erase()
-            mDataItemsPerClientMap.erase (dicIter++);
-        } else {
-            ++dicIter;
-        }
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-void ClientIndex <CT,DIT> :: remove
-(
-    CT client,
-    const list <DIT> & r,
-    list <DIT> & out
-)
-{
-    ENTRY_LOG ();
-    typename map < CT, list <DIT> > :: iterator dicIter =
-        mDataItemsPerClientMap.find (client);
-    if (dicIter != mDataItemsPerClientMap.end ()) {
-        set_intersection (dicIter->second.begin (), dicIter->second.end (),
-                         r.begin (), r.end (),
-                         inserter (out,out.begin ()));
-        if (!out.empty ()) {
-            typename list <DIT> :: iterator it = out.begin ();
-            for (; it != out.end (); ++it) {
-                dicIter->second.erase (find (dicIter->second.begin (),
-                                            dicIter->second.end (),
-                                            *it));
-            }
-        }
-        if (dicIter->second.empty ()) {
-            mDataItemsPerClientMap.erase (dicIter);
-            EXIT_LOG_WITH_ERROR ("%d",0);
-        }
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-void ClientIndex <CT,DIT> :: add
-(
-    CT client,
-    const list <DIT> & l,
-    list <DIT> & out
-)
-{
-    ENTRY_LOG ();
-    list <DIT> difference;
-    typename map < CT, list <DIT> > :: iterator dicIter =
-        mDataItemsPerClientMap.find (client);
-    if (dicIter != mDataItemsPerClientMap.end ()) {
-        set_difference (l.begin (), l.end (),
-                       dicIter->second.begin (), dicIter->second.end (),
-                       inserter (difference,difference.begin ()));
-        if (!difference.empty ()) {
-            difference.sort ();
-            out = difference;
-            dicIter->second.merge (difference);
-            dicIter->second.unique ();
-        }
-    } else {
-        out = l;
-        pair < CT, list <DIT> > dicnpair (client, out);
-        mDataItemsPerClientMap.insert (dicnpair);
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-// Explicit instantiation must occur in same namespace where class is defined
-namespace loc_core
-{
-  template class ClientIndex <IDataItemObserver *, DataItemId>;
-  template class ClientIndex <string, DataItemId>;
-}
diff --git a/sdm845/core/data-items/common/DataItemIndex.cpp b/sdm845/core/data-items/common/DataItemIndex.cpp
deleted file mode 100644
index 462bf74..0000000
--- a/sdm845/core/data-items/common/DataItemIndex.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <string>
-#include <algorithm>
-#include <iterator>
-#include <DataItemIndex.h>
-#include <loc_pla.h>
-#include <log_util.h>
-#include <IDataItemObserver.h>
-#include <DataItemId.h>
-
-using namespace std;
-using namespace loc_core;
-
-template <typename CT, typename DIT>
-inline DataItemIndex <CT,DIT> :: DataItemIndex () {}
-
-template <typename CT, typename DIT>
-inline DataItemIndex <CT,DIT> :: ~DataItemIndex () {}
-
-template <typename CT, typename DIT>
-void DataItemIndex <CT,DIT> :: getListOfSubscribedClients
- (
-    DIT id,
-    list <CT> & out
-)
-{
-    typename map < DIT, list <CT> > :: iterator cdiIter =
-        mClientsPerDataItemMap.find (id);
-    if (cdiIter != mClientsPerDataItemMap.end ()) {
-        out = cdiIter->second;
-    }
-}
-
-
-template <typename CT, typename DIT>
-int DataItemIndex <CT,DIT> :: remove (DIT id) {
-    int result = 0;
-    ENTRY_LOG ();
-    mClientsPerDataItemMap.erase (id);
-    EXIT_LOG_WITH_ERROR ("%d",result);
-    return result;
-}
-
-template <typename CT, typename DIT>
-void DataItemIndex <CT,DIT> :: remove (const list <CT> & r, list <DIT> & out) {
-    ENTRY_LOG ();
-    typename map < DIT, list <CT> > :: iterator cdiIter =
-        mClientsPerDataItemMap.begin ();
-    while (cdiIter != mClientsPerDataItemMap.end()) {
-        typename list <CT> :: const_iterator it = r.begin ();
-        for (; it != r.end (); ++it) {
-            typename list <CT> :: iterator iter =
-                find
-                (
-                    cdiIter->second.begin (),
-                    cdiIter->second.end (),
-                    *it
-                );
-            if (iter != cdiIter->second.end ()) {
-                cdiIter->second.erase (iter);
-            }
-        }
-
-        if (cdiIter->second.empty ()) {
-            out.push_back (cdiIter->first);
-            // Post-increment operator increases the iterator but returns the
-            // prevous one that will be invalidated by erase()
-            mClientsPerDataItemMap.erase (cdiIter++);
-        } else {
-            ++cdiIter;
-        }
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-void DataItemIndex <CT,DIT> :: remove
-(
-    DIT id,
-    const list <CT> & r,
-    list <CT> & out
-)
-{
-    ENTRY_LOG ();
-
-    typename map < DIT, list <CT> > :: iterator cdiIter =
-        mClientsPerDataItemMap.find (id);
-    if (cdiIter != mClientsPerDataItemMap.end ()) {
-        set_intersection (cdiIter->second.begin (), cdiIter->second.end (),
-                         r.begin (), r.end (),
-                         inserter (out, out.begin ()));
-        if (!out.empty ()) {
-            typename list <CT> :: iterator it = out.begin ();
-            for (; it != out.end (); ++it) {
-                cdiIter->second.erase (find (cdiIter->second.begin (),
-                                            cdiIter->second.end (),
-                                            *it));
-            }
-        }
-        if (cdiIter->second.empty ()) {
-            mClientsPerDataItemMap.erase (cdiIter);
-            EXIT_LOG_WITH_ERROR ("%d",0);
-        }
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-void DataItemIndex <CT,DIT> :: add
-(
-    DIT id,
-    const list <CT> & l,
-    list <CT> & out
-)
-{
-    ENTRY_LOG ();
-    list <CT> difference;
-    typename map < DIT, list <CT> > :: iterator cdiIter =
-        mClientsPerDataItemMap.find (id);
-    if (cdiIter != mClientsPerDataItemMap.end ()) {
-        set_difference (l.begin (), l.end (),
-                       cdiIter->second.begin (), cdiIter->second.end (),
-                       inserter (difference, difference.begin ()));
-        if (!difference.empty ()) {
-            difference.sort ();
-            out = difference;
-            cdiIter->second.merge (difference);
-        }
-    } else {
-        out = l;
-        pair < DIT, list <CT> > cndipair (id, out);
-        mClientsPerDataItemMap.insert (cndipair);
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-template <typename CT, typename DIT>
-void DataItemIndex <CT,DIT> :: add
-(
-    CT client,
-    const list <DIT> & l,
-    list <DIT> & out
-)
-{
-    ENTRY_LOG ();
-    typename map < DIT, list <CT> > :: iterator cdiIter;
-    typename list <DIT> :: const_iterator it = l.begin ();
-    for (; it != l.end (); ++it) {
-        cdiIter = mClientsPerDataItemMap.find (*it);
-        if (cdiIter == mClientsPerDataItemMap.end ()) {
-            out.push_back (*it);
-            pair < DIT, list <CT> > cndiPair (*it, list <CT> (1, client));
-            mClientsPerDataItemMap.insert (cndiPair);
-        } else {
-          typename list<CT> :: iterator clientIter =
-              find
-              (
-                cdiIter->second.begin (),
-                cdiIter->second.end (),
-                client
-              );
-            if (clientIter == cdiIter->second.end()) {
-              cdiIter->second.push_back (client);
-            }
-        }
-    }
-    EXIT_LOG_WITH_ERROR ("%d",0);
-}
-
-// Explicit instantiation must occur in same namespace where class is defined
-namespace loc_core
-{
-  template class DataItemIndex <IDataItemObserver *, DataItemId>;
-  template class DataItemIndex <string, DataItemId>;
-}
diff --git a/sdm845/core/data-items/common/IClientIndex.h b/sdm845/core/data-items/common/IClientIndex.h
deleted file mode 100644
index 0272e7b..0000000
--- a/sdm845/core/data-items/common/IClientIndex.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef __ICLIENTINDEX_H__
-#define __ICLIENTINDEX_H__
-
-#include <list>
-
-namespace loc_core
-{
-
-template  <typename CT, typename DIT>
-
-class IClientIndex {
-public:
-
-    // Checks if client is subscribed
-    virtual bool isSubscribedClient (CT client) = 0;
-
-    // gets subscription list
-    virtual void getSubscribedList (CT client, std :: list <DIT> & out) = 0;
-
-    // removes an entry
-    virtual int remove (CT client) = 0;
-
-    // removes std :: list of data items and returns a list of clients
-    // removed if any.
-    virtual void remove
-    (
-        const std :: list <DIT> & r,
-        std :: list <CT> & out
-    ) = 0;
-
-    // removes list of data items indexed by client and returns list
-    // of data items removed if any.
-    virtual void remove
-    (
-        CT client,
-        const std :: list <DIT> & r,
-        std :: list <DIT> & out
-    ) = 0;
-
-    // adds/modifies entry in  map and returns new data items added.
-    virtual void add
-    (
-        CT client,
-        const std :: list <DIT> & l,
-        std :: list <DIT> & out
-    ) = 0;
-
-    // dtor
-    virtual ~IClientIndex () {}
-};
-
-} // namespace loc_core
-
-#endif // #ifndef __ICLIENTINDEX_H__
diff --git a/sdm845/core/data-items/common/IDataItemIndex.h b/sdm845/core/data-items/common/IDataItemIndex.h
deleted file mode 100644
index 9185582..0000000
--- a/sdm845/core/data-items/common/IDataItemIndex.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef __IDATAITEMINDEX_H__
-#define __IDATAITEMINDEX_H__
-
-#include <list>
-
-namespace loc_core
-{
-
-template <typename CT, typename DIT>
-
-class IDataItemIndex {
-
-public:
-
-    // gets std :: list of subscribed clients
-    virtual void getListOfSubscribedClients
-    (
-        DIT id,
-        std :: list <CT> & out
-    ) = 0;
-
-    // removes an entry from
-    virtual int remove (DIT id) = 0;
-
-    // removes list of clients and returns a list of data items
-    // removed if any.
-    virtual void remove
-    (
-        const std :: list <CT> & r,
-        std :: list <DIT> & out
-    ) = 0;
-
-    // removes list of clients indexed by data item and returns list of
-    // clients removed if any.
-    virtual void remove
-    (
-        DIT id,
-        const std :: list <CT> & r,
-        std :: list <CT> & out
-    ) = 0;
-
-    // adds/modifies entry and returns new clients added
-    virtual void add
-    (
-        DIT id,
-        const std :: list <CT> & l,
-        std :: list <CT> & out
-    ) = 0;
-
-    // adds/modifies entry and returns yet to subscribe list of data items
-    virtual void add
-    (
-        CT client,
-        const std :: list <DIT> & l,
-        std :: list <DIT> & out
-    ) = 0;
-
-    // dtor
-    virtual ~IDataItemIndex () {}
-};
-
-} // namespace loc_core
-
-#endif // #ifndef __IDATAITEMINDEX_H__
-
diff --git a/sdm845/core/data-items/common/IndexFactory.cpp b/sdm845/core/data-items/common/IndexFactory.cpp
deleted file mode 100644
index cf49475..0000000
--- a/sdm845/core/data-items/common/IndexFactory.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <string>
-#include <IndexFactory.h>
-#include <IClientIndex.h>
-#include <ClientIndex.h>
-#include <IDataItemIndex.h>
-#include <DataItemIndex.h>
-#include <IDataItemObserver.h>
-#include <DataItemId.h>
-
-using namespace std;
-using loc_core::IClientIndex;
-using loc_core::IDataItemIndex;
-using loc_core::IDataItemObserver;
-using namespace loc_core;
-
-template <typename CT, typename DIT>
-inline IClientIndex <CT, DIT> * IndexFactory <CT, DIT> :: createClientIndex
-()
-{
-    return new (nothrow) ClientIndex <CT, DIT> ();
-}
-
-template <typename CT, typename DIT>
-inline IDataItemIndex <CT, DIT> * IndexFactory <CT, DIT> :: createDataItemIndex
-()
-{
-    return new (nothrow) DataItemIndex <CT, DIT> ();
-}
-
-// Explicit instantiation must occur in same namespace where class is defined
-namespace loc_core
-{
-  template class IndexFactory <IDataItemObserver *, DataItemId>;
-  template class IndexFactory <string, DataItemId>;
-}
diff --git a/sdm845/core/data-items/common/IndexFactory.h b/sdm845/core/data-items/common/IndexFactory.h
deleted file mode 100644
index 9a2070e..0000000
--- a/sdm845/core/data-items/common/IndexFactory.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef __INDEXFACTORY_H__
-#define __INDEXFACTORY_H__
-
-#include <IClientIndex.h>
-#include <IDataItemIndex.h>
-
-namespace loc_core
-{
-template <typename CT, typename DIT>
-class IndexFactory {
-
-public:
-    static IClientIndex <CT, DIT> * createClientIndex ();
-    static IDataItemIndex <CT, DIT> * createDataItemIndex ();
-};
-
-} // namespace loc_core
-
-#endif // #ifndef __INDEXFACTORY_H__
diff --git a/sdm845/utils/LocListMap.h b/sdm845/utils/LocListMap.h
deleted file mode 100644
index feccb05..0000000
--- a/sdm845/utils/LocListMap.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation, nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#ifndef __CLIENTINDEX_H__
-#define __CLIENTINDEX_H__
-
-#include <list>
-#include <map>
-#include <IClientIndex.h>
-
-using loc_core::IClientIndex;
-
-namespace loc_core
-{
-
-template <typename CT, typename DIT>
-
-class ClientIndex : public IClientIndex  <CT, DIT> {
-
-public:
-
-    ClientIndex ();
-
-    ~ClientIndex ();
-
-    bool isSubscribedClient (CT client);
-
-    void getSubscribedList (CT client, std :: list <DIT> & out);
-
-    int remove (CT client);
-
-    void remove (const std :: list <DIT> & r, std :: list <CT> & out);
-
-    void remove (CT client, const std :: list <DIT> & r, std :: list <DIT> & out);
-
-    void add (CT client, const std :: list <DIT> & l, std :: list <DIT> & out);
-
-private:
-    //Data members
-    std :: map < CT , std :: list <DIT> > mDataItemsPerClientMap;
-};
-
-} // namespace loc_core
-
-#endif // #ifndef __CLIENTINDEX_H__
diff --git a/sdm845/utils/LocUnorderedSetMap.h b/sdm845/utils/LocUnorderedSetMap.h
index d72e89e..8748134 100644
--- a/sdm845/utils/LocUnorderedSetMap.h
+++ b/sdm845/utils/LocUnorderedSetMap.h
@@ -26,45 +26,167 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
+#ifndef __LOC_UNORDERDED_SETMAP_H__
+#define __LOC_UNORDERDED_SETMAP_H__
 
-#ifndef __DATAITEMINDEX_H__
-#define __DATAITEMINDEX_H__
+#include <algorithm>
+#include <unordered_set>
+#include <unordered_map>
 
-#include <list>
-#include <map>
-#include <IDataItemIndex.h>
+using std::unordered_set;
+using std::unordered_map;
 
-using loc_core::IDataItemIndex;
+namespace loc_util {
 
-namespace loc_core
-{
+// Trim from *fromSet* any elements that also exist in *rVals*.
+// The optional *goneVals*, if not null, will be populated with removed elements.
+template <typename T>
+inline static void trimSet(unordered_set<T>& fromSet, const unordered_set<T>& rVals,
+                           unordered_set<T>* goneVals) {
+    for (auto val : rVals) {
+        if (fromSet.erase(val) > 0 && nullptr != goneVals) {
+            goneVals->insert(val);
+        }
+    }
+}
 
-template <typename CT, typename DIT>
+// this method is destructive to the input unordered_sets.
+// the return set is the interset extracted out from the two input sets, *s1* and *s2*.
+// *s1* and *s2* will be left with the intersect removed from them.
+template <typename T>
+static unordered_set<T> removeAndReturnInterset(unordered_set<T>& s1, unordered_set<T>& s2) {
+    unordered_set<T> common(0);
+    for (auto b = s2.begin(); b != s2.end(); b++) {
+        auto a = find(s1.begin(), s1.end(), *b);
+        if (a != s1.end()) {
+            // this is a common item of both l1 and l2, remove from both
+            // but after we add to common
+            common.insert(*a);
+            s1.erase(a);
+            s2.erase(b);
+        }
+    }
+    return common;
+}
 
-class DataItemIndex : public IDataItemIndex  <CT, DIT> {
+template <typename KEY, typename VAL>
+class LocUnorderedSetMap {
+    unordered_map<KEY, unordered_set<VAL>> mMap;
+
+
+    // Trim the VALs pointed to by *iter*, with everything that also exist in *rVals*.
+    // If the set becomes empty, remove the map entry. *goneVals*, if not null, records
+    // the trimmed VALs.
+    bool trimOrRemove(typename unordered_map<KEY, unordered_set<VAL>>::iterator iter,
+                      const unordered_set<VAL>& rVals, unordered_set<VAL>* goneVals) {
+        trimSet<VAL>(iter->second, rVals, goneVals);
+        bool removeEntry = (iter->second.empty());
+        if (removeEntry) {
+            mMap.erase(iter);
+        }
+        return removeEntry;
+    }
 
 public:
+    inline LocUnorderedSetMap() {}
+    inline LocUnorderedSetMap(size_t size) : mMap(size) {}
 
-    DataItemIndex ();
+    inline bool empty() { return mMap.empty(); }
 
-    ~DataItemIndex ();
+    // This gets the raw pointer to the VALs pointed to by *key*
+    // If the entry is not in the map, nullptr will be returned.
+    inline unordered_set<VAL>* getValSetPtr(const KEY& key) {
+        auto entry = mMap.find(key);
+        return (entry != mMap.end()) ? &(entry->second) : nullptr;
+    }
 
-    void getListOfSubscribedClients (DIT id, std :: list <CT> & out);
+    //  This gets a copy of VALs pointed to by *key*
+    // If the entry is not in the map, an empty set will be returned.
+    inline unordered_set<VAL> getValSet(const KEY& key) {
+        auto entry = mMap.find(key);
+        return (entry != mMap.end()) ? entry->second : unordered_set<VAL>(0);
+    }
 
-    int remove (DIT id);
+    // This gets all the KEYs from the map
+    inline unordered_set<KEY> getKeys() {
+        unordered_set<KEY> keys(0);
+        for (auto entry : mMap) {
+            keys.insert(entry.first);
+        }
+        return keys;
+    }
 
-    void remove (const std :: list <CT> & r, std :: list <DIT> & out);
+    inline bool remove(const KEY& key) {
+        return mMap.erase(key) > 0;
+    }
 
-    void remove (DIT id, const std :: list <CT> & r, std :: list <CT> & out);
+    // This looks into all the entries keyed by *keys*. Remove any VALs from the entries
+    // that also exist in *rVals*. If the entry is left with an empty set, the entry will
+    // be removed. The optional parameters *goneKeys* and *goneVals* will record the KEYs
+    // (or entries) and the collapsed VALs removed from the map, respectively.
+    inline void trimOrRemove(unordered_set<KEY>&& keys, const unordered_set<VAL>& rVals,
+                             unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
+        trimOrRemove(keys, rVals, goneKeys, goneVals);
+    }
+    inline void trimOrRemove(unordered_set<KEY>& keys, const unordered_set<VAL>& rVals,
+                             unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
+        for (auto key : keys) {
+            auto iter = mMap.find(key);
+            if (iter != mMap.end() && trimOrRemove(iter, rVals, goneVals) && nullptr != goneKeys) {
+                goneKeys->insert(iter->first);
+            }
+        }
+    }
 
-    void add (DIT id, const std :: list <CT> & l, std :: list <CT> & out);
+    // This adds all VALs from *newVals* to the map entry keyed by *key*. Or if it
+    // doesn't exist yet, add the set to the map.
+    bool add(const KEY& key, const unordered_set<VAL>& newVals) {
+        bool newEntryAdded = false;
+        if (!newVals.empty()) {
+            auto iter = mMap.find(key);
+            if (iter != mMap.end()) {
+                iter->second.insert(newVals.begin(), newVals.end());
+            } else {
+                mMap[key] = newVals;
+                newEntryAdded = true;
+            }
+        }
+        return newEntryAdded;
+    }
 
-    void add (CT client, const std :: list <DIT> & l, std :: list <DIT> & out);
+    // This adds to each of entries in the map keyed by *keys* with the VALs in the
+    // *enwVals*. If there new entries added (new key in *keys*), *newKeys*, if not
+    // null, would be populated with those keys.
+    inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>&& newVals,
+                    unordered_set<KEY>* newKeys) {
+        add(keys, newVals, newKeys);
+    }
+    inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>& newVals,
+                    unordered_set<KEY>* newKeys) {
+        for (auto key : keys) {
+            if (add(key, newVals) && nullptr != newKeys) {
+                newKeys->insert(key);
+            }
+        }
+    }
 
-private:
-    std :: map < DIT, std :: list <CT> > mClientsPerDataItemMap;
+    // This puts *newVals* into the map keyed by *key*, and returns the VALs that are
+    // in effect removed from the keyed VAL set in the map entry.
+    // This call would also remove those same VALs from *newVals*.
+    inline unordered_set<VAL> update(const KEY& key, unordered_set<VAL>& newVals) {
+        unordered_set<VAL> goneVals(0);
+
+        if (newVals.empty()) {
+            mMap.erase(key);
+        } else {
+            auto curVals = mMap[key];
+            mMap[key] = newVals;
+            goneVals = removeAndReturnInterset(curVals, newVals);
+        }
+        return goneVals;
+    }
 };
 
-} // namespace loc_core
+} // namespace loc_util
 
-#endif // #ifndef __DATAITEMINDEX_H__
+#endif // #ifndef __LOC_UNORDERDED_SETMAP_H__