summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/Android.mk3
-rw-r--r--core/Makefile.am3
-rw-r--r--core/SystemStatus.cpp4
-rw-r--r--core/SystemStatusOsObserver.cpp635
-rw-r--r--core/SystemStatusOsObserver.h94
-rw-r--r--core/data-items/common/ClientIndex.cpp172
-rw-r--r--core/data-items/common/DataItemIndex.cpp203
-rw-r--r--core/data-items/common/IClientIndex.h83
-rw-r--r--core/data-items/common/IDataItemIndex.h94
-rw-r--r--core/data-items/common/IndexFactory.cpp64
-rw-r--r--core/data-items/common/IndexFactory.h48
-rw-r--r--utils/LocListMap.h70
-rw-r--r--utils/LocUnorderedSetMap.h196
13 files changed, 494 insertions, 1175 deletions
diff --git a/core/Android.mk b/core/Android.mk
index d922766..1a4f51a 100644
--- a/core/Android.mk
+++ b/core/Android.mk
@@ -30,9 +30,6 @@ LOCAL_SRC_FILES += \
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/core/Makefile.am b/core/Makefile.am
index 78ae76b..cf8d9ff 100644
--- a/core/Makefile.am
+++ b/core/Makefile.am
@@ -38,9 +38,6 @@ libloc_core_la_c_sources = \
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/core/SystemStatus.cpp b/core/SystemStatus.cpp
index 6eb9968..e12d9f3 100644
--- a/core/SystemStatus.cpp
+++ b/core/SystemStatus.cpp
@@ -1694,9 +1694,7 @@ bool SystemStatus::eventConnectionStatus(bool connected, int8_t type)
// 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/core/SystemStatusOsObserver.cpp b/core/SystemStatusOsObserver.cpp
index 2fdd19f..0f6d228 100644
--- a/core/SystemStatusOsObserver.cpp
+++ b/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 @@ SystemStatusOsObserver::~SystemStatusOsObserver()
}
mDataItemCache.clear();
- delete mClientIndex;
- delete mDataItemIndex;
}
void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
{
- mContext.mSubscriptionObj = subscriptionObj;
-
- 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();
+ struct SetSubsObj : public LocMsg {
+ ObserverContext& mContext;
+ IDataItemSubscription* mSubsObj;
+ inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
+ mContext(context), mSubsObj(subscriptionObj) {}
+ void proc() const {
+ mContext.mSubscriptionObj = mSubsObj;
+
+ 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() {}
- void proc() const {
+ 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) {}
- if (mDataItemList.empty()) {
- LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
- return;
- }
-
- // 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);
+ void proc() const {
+ unordered_set<DataItemId> dataItemsToSubscribe(0);
+ mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
+ mParent->mClientToDataItems.add(mClient, mDataItemSet);
- list<DataItemId> yetToSubscribeDataItemsList(0);
- mParent->mDataItemIndex->add(mClient, mDataItemList, yetToSubscribeDataItemsList);
+ mParent->sendCachedDataItems(mDataItemSet, mClient);
- // 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() {}
- void proc() const {
- if (mDataItemList.empty()) {
- LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
- return;
- }
+ list<DataItemId>& l, IDataItemObserver* client) :
+ mParent(parent), mClient(client),
+ mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
- 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);
+ void proc() const {
+ 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);
-
- list<DataItemId> yetToSubscribeDataItemsList(0);
- mParent->mDataItemIndex->add(
- mClient, mDataItemList, yetToSubscribeDataItemsList);
-
- // 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);
- }
-
- list<DataItemId> unsubscribeList(0);
- list<DataItemId> unused(0);
- mParent->mClientIndex->remove(mClient, removeDataItemList, unused);
+ mParent->sendCachedDataItems(mDataItemSet, mClient);
+
+ 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);
+
+ mParent->mContext.mSubscriptionObj->subscribe(
+ containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
+ std::move(dataItemsToSubscribe)),
+ mParent);
+ }
- 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() {}
- void proc() const {
- if (mDataItemList.empty()) {
- LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
- return;
- }
+ list<DataItemId>& l, IDataItemObserver* client) :
+ mParent(parent), mClient(client),
+ mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
- 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);
- }
- }
+ void proc() const {
+ 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);
+
+ if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
+ LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
+ mParent->logMe(dataItemsToUnsubscribe);
- 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);
+ 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::unsubscribeAll(IDataItemObserver* client)
******************************************************************************/
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();
-
- set_intersection(dataItemIdsToBeSent.begin(),
- dataItemIdsToBeSent.end(),
- dataItemIdsSubscribedByThisClient.begin(),
- dataItemIdsSubscribedByThisClient.end(),
- inserter(dataItemIdsToBeSentForThisClient,
- dataItemIdsToBeSentForThisClient.begin()));
-
- mParent->sendCachedDataItems(dataItemIdsToBeSentForThisClient, client);
- dataItemIdsSubscribedByThisClient.clear();
- dataItemIdsToBeSentForThisClient.clear();
+
+ 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);
+ }
+ }
+
+ 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 @@ void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
}
// 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 @@ void SystemStatusOsObserver::turnOff(DataItemId dit)
}
// 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 @@ bool SystemStatusOsObserver::disconnectBackhaul()
/******************************************************************************
Helpers
******************************************************************************/
-void SystemStatusOsObserver::sendFirstResponse(
- const list<DataItemId>& l, IDataItemObserver* to)
+void SystemStatusOsObserver::sendCachedDataItems(
+ const unordered_set<DataItemId>& s, 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 (nullptr == to) {
+ LOC_LOGv("client pointer is NULL.");
+ } else {
+ string clientName;
+ to->getName(clientName);
+ list<IDataItemCore*> dataItems(0);
+
+ 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. Nothing to do. Exiting");
- return;
- }
- to->notify(dataItems);
-}
-void SystemStatusOsObserver::sendCachedDataItems(
- const list<DataItemId>& l, IDataItemObserver* to)
-{
- 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);
+ 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;
- }
-
- // 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;
+ bool dataItemUpdated = false;
+
+ // 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/core/SystemStatusOsObserver.h b/core/SystemStatusOsObserver.h
index 930ddc1..fd60606 100644
--- a/core/SystemStatusOsObserver.h
+++ b/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 @@ namespace loc_core
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 @@ public:
}
// 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 @@ private:
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/core/data-items/common/ClientIndex.cpp b/core/data-items/common/ClientIndex.cpp
deleted file mode 100644
index d4bd11e..0000000
--- a/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/core/data-items/common/DataItemIndex.cpp b/core/data-items/common/DataItemIndex.cpp
deleted file mode 100644
index 462bf74..0000000
--- a/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/core/data-items/common/IClientIndex.h b/core/data-items/common/IClientIndex.h
deleted file mode 100644
index 0272e7b..0000000
--- a/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/core/data-items/common/IDataItemIndex.h b/core/data-items/common/IDataItemIndex.h
deleted file mode 100644
index 9185582..0000000
--- a/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/core/data-items/common/IndexFactory.cpp b/core/data-items/common/IndexFactory.cpp
deleted file mode 100644
index cf49475..0000000
--- a/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/core/data-items/common/IndexFactory.h b/core/data-items/common/IndexFactory.h
deleted file mode 100644
index 9a2070e..0000000
--- a/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/utils/LocListMap.h b/utils/LocListMap.h
deleted file mode 100644
index feccb05..0000000
--- a/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/utils/LocUnorderedSetMap.h b/utils/LocUnorderedSetMap.h
index d72e89e..8748134 100644
--- a/utils/LocUnorderedSetMap.h
+++ b/utils/LocUnorderedSetMap.h
@@ -26,45 +26,167 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-
-#ifndef __DATAITEMINDEX_H__
-#define __DATAITEMINDEX_H__
-
-#include <list>
-#include <map>
-#include <IDataItemIndex.h>
-
-using loc_core::IDataItemIndex;
-
-namespace loc_core
-{
-
-template <typename CT, typename DIT>
-
-class DataItemIndex : public IDataItemIndex <CT, DIT> {
+#ifndef __LOC_UNORDERDED_SETMAP_H__
+#define __LOC_UNORDERDED_SETMAP_H__
+
+#include <algorithm>
+#include <unordered_set>
+#include <unordered_map>
+
+using std::unordered_set;
+using std::unordered_map;
+
+namespace loc_util {
+
+// 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);
+ }
+ }
+}
+
+// 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;
+}
+
+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:
-
- DataItemIndex ();
-
- ~DataItemIndex ();
-
- void getListOfSubscribedClients (DIT id, std :: list <CT> & out);
-
- int remove (DIT id);
-
- void remove (const std :: list <CT> & r, std :: list <DIT> & out);
-
- void remove (DIT id, const std :: list <CT> & r, std :: list <CT> & out);
-
- void add (DIT id, const std :: list <CT> & l, std :: list <CT> & out);
-
- void add (CT client, const std :: list <DIT> & l, std :: list <DIT> & out);
-
-private:
- std :: map < DIT, std :: list <CT> > mClientsPerDataItemMap;
+ inline LocUnorderedSetMap() {}
+ inline LocUnorderedSetMap(size_t size) : mMap(size) {}
+
+ inline bool empty() { return mMap.empty(); }
+
+ // 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;
+ }
+
+ // 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);
+ }
+
+ // 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;
+ }
+
+ inline bool remove(const KEY& key) {
+ return mMap.erase(key) > 0;
+ }
+
+ // 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);
+ }
+ }
+ }
+
+ // 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;
+ }
+
+ // 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);
+ }
+ }
+ }
+
+ // 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__