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
This commit is contained in:
parent
86e1b52c81
commit
36da980fea
13 changed files with 473 additions and 1154 deletions
|
@ -30,9 +30,6 @@ LOCAL_SRC_FILES += \
|
||||||
LocDualContext.cpp \
|
LocDualContext.cpp \
|
||||||
loc_core_log.cpp \
|
loc_core_log.cpp \
|
||||||
data-items/DataItemsFactoryProxy.cpp \
|
data-items/DataItemsFactoryProxy.cpp \
|
||||||
data-items/common/ClientIndex.cpp \
|
|
||||||
data-items/common/DataItemIndex.cpp \
|
|
||||||
data-items/common/IndexFactory.cpp \
|
|
||||||
SystemStatusOsObserver.cpp \
|
SystemStatusOsObserver.cpp \
|
||||||
SystemStatus.cpp
|
SystemStatus.cpp
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,6 @@ libloc_core_la_c_sources = \
|
||||||
LocDualContext.cpp \
|
LocDualContext.cpp \
|
||||||
loc_core_log.cpp \
|
loc_core_log.cpp \
|
||||||
data-items/DataItemsFactoryProxy.cpp \
|
data-items/DataItemsFactoryProxy.cpp \
|
||||||
data-items/common/ClientIndex.cpp \
|
|
||||||
data-items/common/DataItemIndex.cpp \
|
|
||||||
data-items/common/IndexFactory.cpp \
|
|
||||||
SystemStatusOsObserver.cpp \
|
SystemStatusOsObserver.cpp \
|
||||||
SystemStatus.cpp
|
SystemStatus.cpp
|
||||||
|
|
||||||
|
|
|
@ -1694,9 +1694,7 @@ bool SystemStatus::eventConnectionStatus(bool connected, int8_t type)
|
||||||
|
|
||||||
// send networkinof dataitem to systemstatus observer clients
|
// send networkinof dataitem to systemstatus observer clients
|
||||||
SystemStatusNetworkInfo s(type, "", "", false, connected, false);
|
SystemStatusNetworkInfo s(type, "", "", false, connected, false);
|
||||||
list<IDataItemCore*> dl(0);
|
mSysStatusObsvr.notify({&s});
|
||||||
dl.push_back(&s);
|
|
||||||
mSysStatusObsvr.notify(dl);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,28 +32,20 @@
|
||||||
#include <SystemStatus.h>
|
#include <SystemStatus.h>
|
||||||
#include <SystemStatusOsObserver.h>
|
#include <SystemStatusOsObserver.h>
|
||||||
#include <IDataItemCore.h>
|
#include <IDataItemCore.h>
|
||||||
#include <IClientIndex.h>
|
|
||||||
#include <IDataItemIndex.h>
|
|
||||||
#include <IndexFactory.h>
|
|
||||||
#include <DataItemsFactoryProxy.h>
|
#include <DataItemsFactoryProxy.h>
|
||||||
|
|
||||||
namespace loc_core
|
namespace loc_core
|
||||||
{
|
{
|
||||||
SystemStatusOsObserver::SystemStatusOsObserver(
|
template <typename CINT, typename COUT>
|
||||||
SystemStatus* systemstatus, const MsgTask* msgTask) :
|
COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
|
||||||
mSystemStatus(systemstatus),
|
COUT outContainer(0);
|
||||||
mAddress("SystemStatusOsObserver"),
|
for (auto item : inContainer) {
|
||||||
#ifdef USE_GLIB
|
outContainer.insert(outContainer.begin(), item);
|
||||||
mBackHaulConnectReqCount(0),
|
}
|
||||||
#endif
|
return outContainer;
|
||||||
mClientIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createClientIndex()),
|
|
||||||
mDataItemIndex(IndexFactory<IDataItemObserver*, DataItemId> :: createDataItemIndex())
|
|
||||||
{
|
|
||||||
mContext.mMsgTask = msgTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemStatusOsObserver::~SystemStatusOsObserver()
|
SystemStatusOsObserver::~SystemStatusOsObserver() {
|
||||||
{
|
|
||||||
// Close data-item library handle
|
// Close data-item library handle
|
||||||
DataItemsFactoryProxy::closeDataItemLibraryHandle();
|
DataItemsFactoryProxy::closeDataItemLibraryHandle();
|
||||||
|
|
||||||
|
@ -65,290 +57,238 @@ SystemStatusOsObserver::~SystemStatusOsObserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataItemCache.clear();
|
mDataItemCache.clear();
|
||||||
delete mClientIndex;
|
|
||||||
delete mDataItemIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
|
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",
|
if (!mContext.mSSObserver->mDataItemToClients.empty()) {
|
||||||
mSubscribeReqCache.size(), mReqDataCache.size());
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// we have received the subscription object. process cached requests
|
if (nullptr == subscriptionObj) {
|
||||||
// process - subscribe request cache
|
LOC_LOGw("subscriptionObj is NULL");
|
||||||
for (auto each : mSubscribeReqCache) {
|
} else {
|
||||||
subscribe(each.second, each.first);
|
mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
|
||||||
}
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// not found
|
|
||||||
reqCache[client] = l;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
IDataItemSubscription Overrides
|
IDataItemSubscription Overrides
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void SystemStatusOsObserver::subscribe(
|
void SystemStatusOsObserver::subscribe(const list<DataItemId>& l, IDataItemObserver* client,
|
||||||
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 {
|
struct HandleSubscribeReq : public LocMsg {
|
||||||
HandleSubscribeReq(SystemStatusOsObserver* parent,
|
inline HandleSubscribeReq(SystemStatusOsObserver* parent,
|
||||||
const list<DataItemId>& l, IDataItemObserver* client) :
|
list<DataItemId>& l, IDataItemObserver* client, bool requestData) :
|
||||||
mParent(parent), mClient(client), mDataItemList(l) {}
|
mParent(parent), mClient(client),
|
||||||
virtual ~HandleSubscribeReq() {}
|
mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)),
|
||||||
|
mToRequestData(requestData) {}
|
||||||
|
|
||||||
void proc() const {
|
void proc() const {
|
||||||
|
unordered_set<DataItemId> dataItemsToSubscribe(0);
|
||||||
|
mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
|
||||||
|
mParent->mClientToDataItems.add(mClient, mDataItemSet);
|
||||||
|
|
||||||
if (mDataItemList.empty()) {
|
mParent->sendCachedDataItems(mDataItemSet, mClient);
|
||||||
LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle First Response
|
// Send subscription set to framework
|
||||||
list<DataItemId> pendingFirstResponseList(0);
|
if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToSubscribe.empty()) {
|
||||||
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);
|
|
||||||
LOC_LOGD("Subscribe Request sent to framework for the following");
|
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;
|
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(
|
void SystemStatusOsObserver::updateSubscription(
|
||||||
const list<DataItemId>& l, IDataItemObserver* client)
|
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 {
|
struct HandleUpdateSubscriptionReq : public LocMsg {
|
||||||
HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
|
HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
|
||||||
const list<DataItemId>& l, IDataItemObserver* client) :
|
list<DataItemId>& l, IDataItemObserver* client) :
|
||||||
mParent(parent), mClient(client), mDataItemList(l) {}
|
mParent(parent), mClient(client),
|
||||||
virtual ~HandleUpdateSubscriptionReq() {}
|
mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
|
||||||
|
|
||||||
void proc() const {
|
void proc() const {
|
||||||
if (mDataItemList.empty()) {
|
unordered_set<DataItemId> dataItemsToSubscribe(0);
|
||||||
LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
|
unordered_set<DataItemId> dataItemsToUnsubscribe(0);
|
||||||
return;
|
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
|
||||||
list<DataItemId> currentlySubscribedList(0);
|
// result, the entire entry will be removed. dataItemsToUnsubscribe will be
|
||||||
mParent->mClientIndex->getSubscribedList(mClient, currentlySubscribedList);
|
// populated to keep the keys of the removed entries.
|
||||||
|
mParent->mDataItemToClients.trimOrRemove(
|
||||||
list<DataItemId> removeDataItemList(0);
|
// this call updates <IDataItemObserver*, DataItemId> map; removes
|
||||||
set_difference(currentlySubscribedList.begin(), currentlySubscribedList.end(),
|
// the DataItemId's that are not new to the clietn from mDataItemSet;
|
||||||
mDataItemList.begin(), mDataItemList.end(),
|
// and returns a set of mDataItemSet's that are no longer used by client.
|
||||||
inserter(removeDataItemList,removeDataItemList.begin()));
|
// This unused set of mDataItemSet's is passed to trimOrRemove method of
|
||||||
|
// <DataItemId, IDataItemObserver*> map to remove the client from the
|
||||||
// Handle First Response
|
// corresponding entries, and gets a set of the entries that are
|
||||||
list<DataItemId> pendingFirstResponseList(0);
|
// removed from the <DataItemId, IDataItemObserver*> map as a result.
|
||||||
mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList);
|
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
|
// Send First Response
|
||||||
mParent->sendFirstResponse(pendingFirstResponseList, mClient);
|
mParent->sendCachedDataItems(mDataItemSet, mClient);
|
||||||
|
|
||||||
list<DataItemId> yetToSubscribeDataItemsList(0);
|
if (nullptr != mParent->mContext.mSubscriptionObj) {
|
||||||
mParent->mDataItemIndex->add(
|
// Send subscription set to framework
|
||||||
mClient, mDataItemList, yetToSubscribeDataItemsList);
|
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(
|
mParent->mContext.mSubscriptionObj->subscribe(
|
||||||
yetToSubscribeDataItemsList, mParent);
|
containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
|
||||||
LOC_LOGD("Subscribe Request sent to framework for the following");
|
std::move(dataItemsToSubscribe)),
|
||||||
mParent->logMe(yetToSubscribeDataItemsList);
|
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
|
// Send unsubscribe to framework
|
||||||
mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
|
if (!dataItemsToUnsubscribe.empty()) {
|
||||||
LOC_LOGD("Unsubscribe Request sent to framework for the following");
|
LOC_LOGD("Unsubscribe Request sent to framework for the following");
|
||||||
mParent->logMe(unsubscribeList);
|
mParent->logMe(dataItemsToUnsubscribe);
|
||||||
|
|
||||||
|
mParent->mContext.mSubscriptionObj->unsubscribe(
|
||||||
|
containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
|
||||||
|
std::move(dataItemsToUnsubscribe)),
|
||||||
|
mParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SystemStatusOsObserver* mParent;
|
SystemStatusOsObserver* mParent;
|
||||||
IDataItemObserver* mClient;
|
IDataItemObserver* mClient;
|
||||||
const list<DataItemId> mDataItemList;
|
unordered_set<DataItemId> mDataItemSet;
|
||||||
};
|
};
|
||||||
mContext.mMsgTask->sendMsg(new (nothrow) HandleUpdateSubscriptionReq(this, l, client));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemStatusOsObserver::requestData(
|
if (l.empty() || nullptr == client) {
|
||||||
const list<DataItemId>& l, IDataItemObserver* client)
|
LOC_LOGw("Data item set is empty or client is nullptr");
|
||||||
{
|
} else {
|
||||||
if (nullptr == mContext.mSubscriptionObj) {
|
mContext.mMsgTask->sendMsg(
|
||||||
LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__);
|
new HandleUpdateSubscriptionReq(this, (list<DataItemId>&)l, client));
|
||||||
cacheObserverRequest(mReqDataCache, l, client);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
void SystemStatusOsObserver::unsubscribe(
|
||||||
const list<DataItemId>& l, IDataItemObserver* client)
|
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 {
|
struct HandleUnsubscribeReq : public LocMsg {
|
||||||
HandleUnsubscribeReq(SystemStatusOsObserver* parent,
|
HandleUnsubscribeReq(SystemStatusOsObserver* parent,
|
||||||
const list<DataItemId>& l, IDataItemObserver* client) :
|
list<DataItemId>& l, IDataItemObserver* client) :
|
||||||
mParent(parent), mClient(client), mDataItemList(l) {}
|
mParent(parent), mClient(client),
|
||||||
virtual ~HandleUnsubscribeReq() {}
|
mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
|
||||||
|
|
||||||
void proc() const {
|
void proc() const {
|
||||||
if (mDataItemList.empty()) {
|
unordered_set<DataItemId> dataItemsUnusedByClient(0);
|
||||||
LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting");
|
unordered_set<IDataItemObserver*> clientToRemove(0);
|
||||||
return;
|
mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet, &clientToRemove,
|
||||||
}
|
&dataItemsUnusedByClient);
|
||||||
|
unordered_set<DataItemId> dataItemsToUnsubscribe(0);
|
||||||
|
mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
|
||||||
|
&dataItemsToUnsubscribe, nullptr);
|
||||||
|
|
||||||
list<DataItemId> unsubscribeList(0);
|
if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
|
||||||
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);
|
|
||||||
LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
|
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;
|
SystemStatusOsObserver* mParent;
|
||||||
IDataItemObserver* mClient;
|
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)
|
void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
|
||||||
{
|
{
|
||||||
if (nullptr == mContext.mSubscriptionObj) {
|
|
||||||
LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HandleUnsubscribeAllReq : public LocMsg {
|
struct HandleUnsubscribeAllReq : public LocMsg {
|
||||||
HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
|
HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
|
||||||
IDataItemObserver* client) :
|
IDataItemObserver* client) :
|
||||||
mParent(parent), mClient(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()) {
|
void proc() const {
|
||||||
// Send unsubscribe to framework
|
unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
|
||||||
mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent);
|
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");
|
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;
|
SystemStatusOsObserver* mParent;
|
||||||
IDataItemObserver* mClient;
|
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)
|
void SystemStatusOsObserver::notify(const list<IDataItemCore*>& dlist)
|
||||||
{
|
{
|
||||||
list<IDataItemCore*> dataItemList(0);
|
struct HandleNotify : public LocMsg {
|
||||||
|
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.
|
||||||
|
unordered_set<DataItemId> dataItemIdsToBeSent(0);
|
||||||
|
for (auto item : mDiVec) {
|
||||||
|
if (mParent->updateCache(item)) {
|
||||||
|
dataItemIdsToBeSent.insert(item->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send data item to all subscribed clients
|
||||||
|
unordered_set<IDataItemObserver*> clientSet(0);
|
||||||
|
for (auto each : dataItemIdsToBeSent) {
|
||||||
|
auto clients = mParent->mDataItemToClients.getValSetPtr(each);
|
||||||
|
if (nullptr != clients) {
|
||||||
|
clientSet.insert(clients->begin(), clients->end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 vector<IDataItemCore*> mDiVec;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!dlist.empty()) {
|
||||||
|
vector<IDataItemCore*> dataItemVec(dlist.size());
|
||||||
|
|
||||||
for (auto each : dlist) {
|
for (auto each : dlist) {
|
||||||
|
IF_LOC_LOGD {
|
||||||
string dv;
|
string dv;
|
||||||
each->stringify(dv);
|
each->stringify(dv);
|
||||||
LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
|
LOC_LOGD("notify: DataItem In Value:%s", dv.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
|
IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
|
||||||
if (nullptr == di) {
|
if (nullptr == di) {
|
||||||
LOC_LOGE("Unable to create dataitem:%d", each->getId());
|
LOC_LOGw("Unable to create dataitem:%d", each->getId());
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy contents into the newly created data item
|
// Copy contents into the newly created data item
|
||||||
di->copy(each);
|
di->copy(each);
|
||||||
|
|
||||||
// Request systemstatus to record this dataitem in its cache
|
|
||||||
if (mSystemStatus->eventDataItemNotify(di)) {
|
|
||||||
// add this dataitem if updated from last one
|
// add this dataitem if updated from last one
|
||||||
dataItemList.push_back(di);
|
dataItemVec.push_back(di);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HandleNotify : public LocMsg {
|
if (!dataItemVec.empty()) {
|
||||||
HandleNotify(SystemStatusOsObserver* parent, const list<IDataItemCore*>& l) :
|
mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
|
||||||
mParent(parent), mDList(l) {}
|
|
||||||
virtual ~HandleNotify() {
|
|
||||||
for (auto each : mDList) {
|
|
||||||
delete each;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send data item to all subscribed clients
|
|
||||||
list<IDataItemObserver*> clientList(0);
|
|
||||||
for (auto each : dataItemIdsToBeSent) {
|
|
||||||
list<IDataItemObserver*> clients(0);
|
|
||||||
mParent->mDataItemIndex->getListOfSubscribedClients(each, clients);
|
|
||||||
for (auto each_cient: clients) {
|
|
||||||
clientList.push_back(each_cient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SystemStatusOsObserver* mParent;
|
|
||||||
const list<IDataItemCore*> mDList;
|
|
||||||
};
|
|
||||||
mContext.mMsgTask->sendMsg(new (nothrow) HandleNotify(this, dataItemList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -447,7 +381,7 @@ void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if data item exists in mActiveRequestCount
|
// 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()) {
|
if (citer == mActiveRequestCount.end()) {
|
||||||
// Data item not found in map
|
// Data item not found in map
|
||||||
// Add reference count as 1 and add dataitem to 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
|
// 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()) {
|
if (citer != mActiveRequestCount.end()) {
|
||||||
// found
|
// found
|
||||||
citer->second--;
|
citer->second--;
|
||||||
|
@ -573,84 +507,65 @@ bool SystemStatusOsObserver::disconnectBackhaul()
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Helpers
|
Helpers
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void SystemStatusOsObserver::sendFirstResponse(
|
void SystemStatusOsObserver::sendCachedDataItems(
|
||||||
const list<DataItemId>& l, IDataItemObserver* to)
|
const unordered_set<DataItemId>& s, IDataItemObserver* to)
|
||||||
{
|
{
|
||||||
if (l.empty()) {
|
if (nullptr == to) {
|
||||||
LOC_LOGV("list is empty. Nothing to do. Exiting");
|
LOC_LOGv("client pointer is NULL.");
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
string clientName;
|
string clientName;
|
||||||
to->getName(clientName);
|
to->getName(clientName);
|
||||||
list<IDataItemCore*> dataItems(0);
|
list<IDataItemCore*> dataItems(0);
|
||||||
|
|
||||||
for (auto each : l) {
|
for (auto each : s) {
|
||||||
map<DataItemId, IDataItemCore*>::const_iterator citer = mDataItemCache.find(each);
|
auto citer = mDataItemCache.find(each);
|
||||||
if (citer != mDataItemCache.end()) {
|
if (citer != mDataItemCache.end()) {
|
||||||
string dv;
|
string dv;
|
||||||
citer->second->stringify(dv);
|
citer->second->stringify(dv);
|
||||||
LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
|
LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
|
||||||
dataItems.push_back(citer->second);
|
dataItems.push_front(citer->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataItems.empty()) {
|
if (dataItems.empty()) {
|
||||||
LOC_LOGV("No items to notify. Nothing to do. Exiting");
|
LOC_LOGv("No items to notify.");
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
to->notify(dataItems);
|
to->notify(dataItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStatusOsObserver::sendCachedDataItems(
|
bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
|
||||||
const list<DataItemId>& l, IDataItemObserver* to)
|
|
||||||
{
|
{
|
||||||
string clientName;
|
bool dataItemUpdated = false;
|
||||||
to->getName(clientName);
|
|
||||||
list<IDataItemCore*> dataItems(0);
|
|
||||||
|
|
||||||
for (auto each : l) {
|
// Request systemstatus to record this dataitem in its cache
|
||||||
string dv;
|
// if the return is false, it means that SystemStatus is not
|
||||||
IDataItemCore* di = mDataItemCache[each];
|
// handling it, so SystemStatusOsObserver also doesn't.
|
||||||
di->stringify(dv);
|
// So it has to be true to proceed.
|
||||||
LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
|
if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
|
||||||
dataItems.push_back(di);
|
auto citer = mDataItemCache.find(d->getId());
|
||||||
}
|
|
||||||
to->notify(dataItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemStatusOsObserver::updateCache(IDataItemCore* d, bool& dataItemUpdated)
|
|
||||||
{
|
|
||||||
if (nullptr == d) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if data item exists in cache
|
|
||||||
map<DataItemId, IDataItemCore*>::iterator citer =
|
|
||||||
mDataItemCache.find(d->getId());
|
|
||||||
if (citer == mDataItemCache.end()) {
|
if (citer == mDataItemCache.end()) {
|
||||||
// New data item; not found in cache
|
// New data item; not found in cache
|
||||||
IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
|
IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
|
||||||
if (nullptr == dataitem) {
|
if (nullptr != dataitem) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the contents of the data item
|
// Copy the contents of the data item
|
||||||
dataitem->copy(d);
|
dataitem->copy(d);
|
||||||
pair<DataItemId, IDataItemCore*> cpair(d->getId(), dataitem);
|
|
||||||
// Insert in mDataItemCache
|
// Insert in mDataItemCache
|
||||||
mDataItemCache.insert(cpair);
|
mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
|
||||||
dataItemUpdated = true;
|
dataItemUpdated = true;
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
// Found in cache; Update cache if necessary
|
// Found in cache; Update cache if necessary
|
||||||
if(0 == citer->second->copy(d, &dataItemUpdated)) {
|
citer->second->copy(d, &dataItemUpdated);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataItemUpdated) {
|
if (dataItemUpdated) {
|
||||||
LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
|
LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataItemUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace loc_core
|
} // namespace loc_core
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <IOsObserver.h>
|
#include <IOsObserver.h>
|
||||||
#include <loc_pla.h>
|
#include <loc_pla.h>
|
||||||
#include <log_util.h>
|
#include <log_util.h>
|
||||||
|
#include <LocUnorderedSetMap.h>
|
||||||
|
|
||||||
namespace loc_core
|
namespace loc_core
|
||||||
{
|
{
|
||||||
|
@ -48,39 +49,57 @@ namespace loc_core
|
||||||
SystemStatusOsObserver
|
SystemStatusOsObserver
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace loc_util;
|
||||||
|
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
class IDataItemCore;
|
class IDataItemCore;
|
||||||
template<typename CT, typename DIT> class IClientIndex;
|
class SystemStatus;
|
||||||
template<typename CT, typename DIT> class IDataItemIndex;
|
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;
|
IDataItemSubscription* mSubscriptionObj;
|
||||||
IFrameworkActionReq* mFrameworkActionReqObj;
|
IFrameworkActionReq* mFrameworkActionReqObj;
|
||||||
const MsgTask* mMsgTask;
|
const MsgTask* mMsgTask;
|
||||||
|
SystemStatusOsObserver* mSSObserver;
|
||||||
|
|
||||||
inline SystemContext() :
|
inline ObserverContext(const MsgTask* msgTask, SystemStatusOsObserver* observer) :
|
||||||
mSubscriptionObj(NULL),
|
mSubscriptionObj(NULL), mFrameworkActionReqObj(NULL),
|
||||||
mFrameworkActionReqObj(NULL),
|
mMsgTask(msgTask), mSSObserver(observer) {}
|
||||||
mMsgTask(NULL) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef map<IDataItemObserver*, list<DataItemId>> ObserverReqCache;
|
|
||||||
|
|
||||||
// Clients wanting to get data from OS/Framework would need to
|
// Clients wanting to get data from OS/Framework would need to
|
||||||
// subscribe with OSObserver using IDataItemSubscription interface.
|
// subscribe with OSObserver using IDataItemSubscription interface.
|
||||||
// Such clients would need to implement IDataItemObserver interface
|
// Such clients would need to implement IDataItemObserver interface
|
||||||
// to receive data when it becomes available.
|
// to receive data when it becomes available.
|
||||||
class SystemStatus;
|
|
||||||
class SystemStatusOsObserver : public IOsObserver {
|
class SystemStatusOsObserver : public IOsObserver {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ctor
|
// ctor
|
||||||
SystemStatusOsObserver(
|
inline SystemStatusOsObserver(SystemStatus* systemstatus, const MsgTask* msgTask) :
|
||||||
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
|
// dtor
|
||||||
~SystemStatusOsObserver();
|
~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
|
// To set the subscription object
|
||||||
virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj);
|
virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj);
|
||||||
|
|
||||||
|
@ -96,38 +115,40 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDataItemSubscription Overrides
|
// IDataItemSubscription Overrides
|
||||||
virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client);
|
inline virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client) override {
|
||||||
virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client);
|
subscribe(l, client, false);
|
||||||
virtual void requestData(const list<DataItemId>& l, IDataItemObserver* client);
|
}
|
||||||
virtual void unsubscribe(const list<DataItemId>& l, IDataItemObserver* client);
|
virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client) override;
|
||||||
virtual void unsubscribeAll(IDataItemObserver* client);
|
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
|
// IDataItemObserver Overrides
|
||||||
virtual void notify(const list<IDataItemCore*>& dlist);
|
virtual void notify(const list<IDataItemCore*>& dlist) override;
|
||||||
inline virtual void getName(string& name) {
|
inline virtual void getName(string& name) override {
|
||||||
name = mAddress;
|
name = mAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFrameworkActionReq Overrides
|
// IFrameworkActionReq Overrides
|
||||||
virtual void turnOn(DataItemId dit, int timeOut = 0);
|
virtual void turnOn(DataItemId dit, int timeOut = 0) override;
|
||||||
virtual void turnOff(DataItemId dit);
|
virtual void turnOff(DataItemId dit) override;
|
||||||
#ifdef USE_GLIB
|
#ifdef USE_GLIB
|
||||||
virtual bool connectBackhaul();
|
virtual bool connectBackhaul() override;
|
||||||
virtual bool disconnectBackhaul();
|
virtual bool disconnectBackhaul();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SystemStatus* mSystemStatus;
|
SystemStatus* mSystemStatus;
|
||||||
SystemContext mContext;
|
ObserverContext mContext;
|
||||||
const string mAddress;
|
const string mAddress;
|
||||||
IClientIndex<IDataItemObserver*, DataItemId>* mClientIndex;
|
ClientToDataItems mClientToDataItems;
|
||||||
IDataItemIndex<IDataItemObserver*, DataItemId>* mDataItemIndex;
|
DataItemToClients mDataItemToClients;
|
||||||
map<DataItemId, IDataItemCore*> mDataItemCache;
|
DataItemIdToCore mDataItemCache;
|
||||||
map<DataItemId, int> mActiveRequestCount;
|
DataItemIdToInt mActiveRequestCount;
|
||||||
|
|
||||||
// Cache the subscribe and requestData till subscription obj is obtained
|
// Cache the subscribe and requestData till subscription obj is obtained
|
||||||
ObserverReqCache mSubscribeReqCache;
|
|
||||||
ObserverReqCache mReqDataCache;
|
|
||||||
void cacheObserverRequest(ObserverReqCache& reqCache,
|
void cacheObserverRequest(ObserverReqCache& reqCache,
|
||||||
const list<DataItemId>& l, IDataItemObserver* client);
|
const list<DataItemId>& l, IDataItemObserver* client);
|
||||||
#ifdef USE_GLIB
|
#ifdef USE_GLIB
|
||||||
|
@ -135,15 +156,18 @@ private:
|
||||||
int mBackHaulConnectReqCount;
|
int mBackHaulConnectReqCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void subscribe(const list<DataItemId>& l, IDataItemObserver* client, bool toRequestData);
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
void sendFirstResponse(const list<DataItemId>& l, IDataItemObserver* to);
|
void sendCachedDataItems(const unordered_set<DataItemId>& s, IDataItemObserver* to);
|
||||||
void sendCachedDataItems(const list<DataItemId>& l, IDataItemObserver* to);
|
bool updateCache(IDataItemCore* d);
|
||||||
void updateCache(IDataItemCore* d, bool& dataItemUpdated);
|
inline void logMe(const unordered_set<DataItemId>& l) {
|
||||||
inline void logMe(const list<DataItemId>& l) {
|
IF_LOC_LOGD {
|
||||||
for (auto id : l) {
|
for (auto id : l) {
|
||||||
LOC_LOGD("DataItem %d", id);
|
LOC_LOGD("DataItem %d", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace loc_core
|
} // namespace loc_core
|
||||||
|
|
|
@ -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>;
|
|
||||||
}
|
|
|
@ -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>;
|
|
||||||
}
|
|
|
@ -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__
|
|
|
@ -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__
|
|
||||||
|
|
|
@ -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>;
|
|
||||||
}
|
|
|
@ -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__
|
|
|
@ -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__
|
|
|
@ -26,45 +26,167 @@
|
||||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#ifndef __LOC_UNORDERDED_SETMAP_H__
|
||||||
|
#define __LOC_UNORDERDED_SETMAP_H__
|
||||||
|
|
||||||
#ifndef __DATAITEMINDEX_H__
|
#include <algorithm>
|
||||||
#define __DATAITEMINDEX_H__
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <list>
|
using std::unordered_set;
|
||||||
#include <map>
|
using std::unordered_map;
|
||||||
#include <IDataItemIndex.h>
|
|
||||||
|
|
||||||
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:
|
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:
|
// This puts *newVals* into the map keyed by *key*, and returns the VALs that are
|
||||||
std :: map < DIT, std :: list <CT> > mClientsPerDataItemMap;
|
// 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__
|
||||||
|
|
Loading…
Reference in a new issue