Inject InteractionModelEngine into ReadHandler and reporting/Engine (#31494)
* Inject InteractionModelEngine into ReadHandler and reporting/Engine
Pass in a poinger of InteractionModelEngine in constructor or init
function instead of using InteractionMOdelEngine as a singleton.
* Modify tests for the change
* Fix Engine cpp mpImEngine pointer nullptr
* Changes to avoid public interface modifications
* Address comments and fix tests
* Restyled by clang-format
* Move setting ImEngine is Reporting::Engine from Init to constructor
---------
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp
index 300e934..98cb6ff 100644
--- a/src/app/InteractionModelEngine.cpp
+++ b/src/app/InteractionModelEngine.cpp
@@ -57,7 +57,7 @@
Global<InteractionModelEngine> sInteractionModelEngine;
-InteractionModelEngine::InteractionModelEngine() {}
+InteractionModelEngine::InteractionModelEngine() : mReportingEngine(this) {}
InteractionModelEngine * InteractionModelEngine::GetInstance()
{
diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h
index 4b89cab..8ed201a 100644
--- a/src/app/InteractionModelEngine.h
+++ b/src/app/InteractionModelEngine.h
@@ -407,6 +407,8 @@
ReadHandler::ApplicationCallback * GetAppCallback() override { return mpReadHandlerApplicationCallback; }
+ InteractionModelEngine * GetInteractionModelEngine() override { return this; }
+
CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override;
/**
diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp
index df8516d..bd63503 100644
--- a/src/app/ReadHandler.cpp
+++ b/src/app/ReadHandler.cpp
@@ -68,7 +68,7 @@
mInteractionType = aInteractionType;
mLastWrittenEventsBytes = 0;
- mTransactionStartGeneration = InteractionModelEngine::GetInstance()->GetReportingEngine().GetDirtySetGeneration();
+ mTransactionStartGeneration = mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().GetDirtySetGeneration();
mFlags.ClearAll();
SetStateFlag(ReadHandlerFlags::PrimingReports);
@@ -102,7 +102,7 @@
for (size_t i = 0; i < resumptionSessionEstablisher.mSubscriptionInfo.mAttributePaths.AllocatedSize(); i++)
{
AttributePathParams params = resumptionSessionEstablisher.mSubscriptionInfo.mAttributePaths[i].GetParams();
- CHIP_ERROR err = InteractionModelEngine::GetInstance()->PushFrontAttributePathList(mpAttributePathList, params);
+ CHIP_ERROR err = mManagementCallback.GetInteractionModelEngine()->PushFrontAttributePathList(mpAttributePathList, params);
if (err != CHIP_NO_ERROR)
{
Close();
@@ -112,7 +112,7 @@
for (size_t i = 0; i < resumptionSessionEstablisher.mSubscriptionInfo.mEventPaths.AllocatedSize(); i++)
{
EventPathParams params = resumptionSessionEstablisher.mSubscriptionInfo.mEventPaths[i].GetParams();
- CHIP_ERROR err = InteractionModelEngine::GetInstance()->PushFrontEventPathParamsList(mpEventPathList, params);
+ CHIP_ERROR err = mManagementCallback.GetInteractionModelEngine()->PushFrontEventPathParamsList(mpEventPathList, params);
if (err != CHIP_NO_ERROR)
{
Close();
@@ -137,7 +137,7 @@
ObjectList<AttributePathParams> * attributePath = mpAttributePathList;
while (attributePath)
{
- InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(attributePath->mValue);
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().SetDirty(attributePath->mValue);
attributePath = attributePath->mpNext;
}
}
@@ -156,11 +156,11 @@
if (IsAwaitingReportResponse())
{
- InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().OnReportConfirm();
}
- InteractionModelEngine::GetInstance()->ReleaseAttributePathList(mpAttributePathList);
- InteractionModelEngine::GetInstance()->ReleaseEventPathList(mpEventPathList);
- InteractionModelEngine::GetInstance()->ReleaseDataVersionFilterList(mpDataVersionFilterList);
+ mManagementCallback.GetInteractionModelEngine()->ReleaseAttributePathList(mpAttributePathList);
+ mManagementCallback.GetInteractionModelEngine()->ReleaseEventPathList(mpEventPathList);
+ mManagementCallback.GetInteractionModelEngine()->ReleaseDataVersionFilterList(mpDataVersionFilterList);
}
void ReadHandler::Close(CloseOptions options)
@@ -168,7 +168,7 @@
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
if (IsType(InteractionType::Subscribe) && options == CloseOptions::kDropPersistedSubscription)
{
- auto * subscriptionResumptionStorage = InteractionModelEngine::GetInstance()->GetSubscriptionResumptionStorage();
+ auto * subscriptionResumptionStorage = mManagementCallback.GetInteractionModelEngine()->GetSubscriptionResumptionStorage();
if (subscriptionResumptionStorage)
{
subscriptionResumptionStorage->Delete(GetInitiatorNodeId(), GetAccessingFabricIndex(), mSubscriptionId);
@@ -285,7 +285,8 @@
#if CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
auto exchange = mExchangeMgr->NewContext(mSessionHandle.Get().Value(), this);
#else // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
- auto exchange = InteractionModelEngine::GetInstance()->GetExchangeManager()->NewContext(mSessionHandle.Get().Value(), this);
+ auto exchange =
+ mManagementCallback.GetInteractionModelEngine()->GetExchangeManager()->NewContext(mSessionHandle.Get().Value(), this);
#endif // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
VerifyOrReturnLogError(exchange != nullptr, CHIP_ERROR_INCORRECT_STATE);
mExchangeCtx.Grab(exchange);
@@ -310,7 +311,8 @@
#if CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
auto exchange = mExchangeMgr->NewContext(mSessionHandle.Get().Value(), this);
#else // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
- auto exchange = InteractionModelEngine::GetInstance()->GetExchangeManager()->NewContext(mSessionHandle.Get().Value(), this);
+ auto exchange =
+ mManagementCallback.GetInteractionModelEngine()->GetExchangeManager()->NewContext(mSessionHandle.Get().Value(), this);
#endif // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
VerifyOrReturnLogError(exchange != nullptr, CHIP_ERROR_INCORRECT_STATE);
mExchangeCtx.Grab(exchange);
@@ -320,7 +322,8 @@
if (!IsReporting())
{
- mCurrentReportsBeginGeneration = InteractionModelEngine::GetInstance()->GetReportingEngine().GetDirtySetGeneration();
+ mCurrentReportsBeginGeneration =
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().GetDirtySetGeneration();
}
SetStateFlag(ReadHandlerFlags::ChunkedReport, aMoreChunks);
bool responseExpected = IsType(InteractionType::Subscribe) || aMoreChunks;
@@ -339,7 +342,7 @@
{
// Make sure we're not treated as an in-flight report waiting for a
// response by the reporting engine.
- InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().OnReportConfirm();
}
// If we just finished a non-priming subscription report, notify our observers.
@@ -353,7 +356,7 @@
{
mPreviousReportsBeginGeneration = mCurrentReportsBeginGeneration;
ClearForceDirtyFlag();
- InteractionModelEngine::GetInstance()->ReleaseDataVersionFilterList(mpDataVersionFilterList);
+ mManagementCallback.GetInteractionModelEngine()->ReleaseDataVersionFilterList(mpDataVersionFilterList);
}
return err;
@@ -489,12 +492,13 @@
AttributePathIB::Parser path;
ReturnErrorOnFailure(path.Init(reader));
ReturnErrorOnFailure(path.ParsePath(attribute));
- ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->PushFrontAttributePathList(mpAttributePathList, attribute));
+ ReturnErrorOnFailure(
+ mManagementCallback.GetInteractionModelEngine()->PushFrontAttributePathList(mpAttributePathList, attribute));
}
// if we have exhausted this container
if (CHIP_END_OF_TLV == err)
{
- InteractionModelEngine::GetInstance()->RemoveDuplicateConcreteAttributePath(mpAttributePathList);
+ mManagementCallback.GetInteractionModelEngine()->RemoveDuplicateConcreteAttributePath(mpAttributePathList);
mAttributePathExpandIterator = AttributePathExpandIterator(mpAttributePathList);
err = CHIP_NO_ERROR;
}
@@ -521,8 +525,8 @@
ReturnErrorOnFailure(path.GetEndpoint(&(versionFilter.mEndpointId)));
ReturnErrorOnFailure(path.GetCluster(&(versionFilter.mClusterId)));
VerifyOrReturnError(versionFilter.IsValidDataVersionFilter(), CHIP_ERROR_IM_MALFORMED_DATA_VERSION_FILTER_IB);
- ReturnErrorOnFailure(
- InteractionModelEngine::GetInstance()->PushFrontDataVersionFilterList(mpDataVersionFilterList, versionFilter));
+ ReturnErrorOnFailure(mManagementCallback.GetInteractionModelEngine()->PushFrontDataVersionFilterList(
+ mpDataVersionFilterList, versionFilter));
}
if (CHIP_END_OF_TLV == err)
@@ -544,7 +548,7 @@
EventPathIB::Parser path;
ReturnErrorOnFailure(path.Init(reader));
ReturnErrorOnFailure(path.ParsePath(event));
- ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->PushFrontEventPathParamsList(mpEventPathList, event));
+ ReturnErrorOnFailure(mManagementCallback.GetInteractionModelEngine()->PushFrontEventPathParamsList(mpEventPathList, event));
}
// if we have exhausted this container
@@ -604,7 +608,7 @@
if (IsAwaitingReportResponse() && aTargetState != HandlerState::AwaitingReportResponse)
{
- InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().OnReportConfirm();
}
mState = aTargetState;
@@ -618,7 +622,7 @@
{
if (ShouldReportUnscheduled())
{
- InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
+ mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().ScheduleRun();
}
else
{
@@ -814,7 +818,7 @@
void ReadHandler::PersistSubscription()
{
- auto * subscriptionResumptionStorage = InteractionModelEngine::GetInstance()->GetSubscriptionResumptionStorage();
+ auto * subscriptionResumptionStorage = mManagementCallback.GetInteractionModelEngine()->GetSubscriptionResumptionStorage();
VerifyOrReturn(subscriptionResumptionStorage != nullptr);
SubscriptionResumptionStorage::SubscriptionInfo subscriptionInfo = { .mNodeId = GetInitiatorNodeId(),
@@ -843,7 +847,7 @@
{
ConcreteAttributePath path;
- mDirtyGeneration = InteractionModelEngine::GetInstance()->GetReportingEngine().GetDirtySetGeneration();
+ mDirtyGeneration = mManagementCallback.GetInteractionModelEngine()->GetReportingEngine().GetDirtySetGeneration();
// We won't reset the path iterator for every AttributePathIsDirty call to reduce the number of full data reports.
// The iterator will be reset after finishing each report session.
diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h
index 2809786..d602273 100644
--- a/src/app/ReadHandler.h
+++ b/src/app/ReadHandler.h
@@ -153,6 +153,11 @@
* issues w.r.t the ReadHandler itself.
*/
virtual ApplicationCallback * GetAppCallback() = 0;
+
+ /*
+ * Retrieve the InteractionalModelEngine that holds this ReadHandler.
+ */
+ virtual InteractionModelEngine * GetInteractionModelEngine() = 0;
};
// TODO (#27675) : Merge existing callback and observer into one class and have an observer pool in the Readhandler to notify
diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp
index 2530ec7..80dec7e 100644
--- a/src/app/reporting/Engine.cpp
+++ b/src/app/reporting/Engine.cpp
@@ -38,6 +38,9 @@
namespace chip {
namespace app {
namespace reporting {
+
+Engine::Engine(InteractionModelEngine * apImEngine) : mpImEngine(apImEngine) {}
+
CHIP_ERROR Engine::Init()
{
mNumReportsInFlight = 0;
@@ -616,7 +619,7 @@
return CHIP_NO_ERROR;
}
- Messaging::ExchangeManager * exchangeManager = InteractionModelEngine::GetInstance()->GetExchangeManager();
+ Messaging::ExchangeManager * exchangeManager = mpImEngine->GetExchangeManager();
if (exchangeManager == nullptr)
{
return CHIP_ERROR_INCORRECT_STATE;
@@ -640,17 +643,16 @@
{
uint32_t numReadHandled = 0;
- InteractionModelEngine * imEngine = InteractionModelEngine::GetInstance();
-
// We may be deallocating read handlers as we go. Track how many we had
// initially, so we make sure to go through all of them.
- size_t initialAllocated = imEngine->mReadHandlers.Allocated();
+ size_t initialAllocated = mpImEngine->mReadHandlers.Allocated();
while ((mNumReportsInFlight < CHIP_IM_MAX_REPORTS_IN_FLIGHT) && (numReadHandled < initialAllocated))
{
- ReadHandler * readHandler = imEngine->ActiveHandlerAt(mCurReadHandlerIdx % (uint32_t) imEngine->mReadHandlers.Allocated());
+ ReadHandler * readHandler =
+ mpImEngine->ActiveHandlerAt(mCurReadHandlerIdx % (uint32_t) mpImEngine->mReadHandlers.Allocated());
VerifyOrDie(readHandler != nullptr);
- if (readHandler->ShouldReportUnscheduled() || imEngine->GetReportScheduler()->IsReportableNow(readHandler))
+ if (readHandler->ShouldReportUnscheduled() || mpImEngine->GetReportScheduler()->IsReportableNow(readHandler))
{
mRunningReadHandler = readHandler;
@@ -674,14 +676,14 @@
// This isn't strictly necessary, but does make it easier to debug issues in this code if they
// do arise.
//
- if (mCurReadHandlerIdx >= imEngine->mReadHandlers.Allocated())
+ if (mCurReadHandlerIdx >= mpImEngine->mReadHandlers.Allocated())
{
mCurReadHandlerIdx = 0;
}
bool allReadClean = true;
- imEngine->mReadHandlers.ForEachActiveObject([&allReadClean](ReadHandler * handler) {
+ mpImEngine->mReadHandlers.ForEachActiveObject([&allReadClean](ReadHandler * handler) {
if (handler->IsDirty())
{
allReadClean = false;
@@ -839,26 +841,25 @@
BumpDirtySetGeneration();
bool intersectsInterestPath = false;
- InteractionModelEngine::GetInstance()->mReadHandlers.ForEachActiveObject(
- [&aAttributePath, &intersectsInterestPath](ReadHandler * handler) {
- // We call AttributePathIsDirty for both read interactions and subscribe interactions, since we may send inconsistent
- // attribute data between two chunks. AttributePathIsDirty will not schedule a new run for read handlers which are
- // waiting for a response to the last message chunk for read interactions.
- if (handler->CanStartReporting() || handler->IsAwaitingReportResponse())
+ mpImEngine->mReadHandlers.ForEachActiveObject([&aAttributePath, &intersectsInterestPath](ReadHandler * handler) {
+ // We call AttributePathIsDirty for both read interactions and subscribe interactions, since we may send inconsistent
+ // attribute data between two chunks. AttributePathIsDirty will not schedule a new run for read handlers which are
+ // waiting for a response to the last message chunk for read interactions.
+ if (handler->CanStartReporting() || handler->IsAwaitingReportResponse())
+ {
+ for (auto object = handler->GetAttributePathList(); object != nullptr; object = object->mpNext)
{
- for (auto object = handler->GetAttributePathList(); object != nullptr; object = object->mpNext)
+ if (object->mValue.Intersects(aAttributePath))
{
- if (object->mValue.Intersects(aAttributePath))
- {
- handler->AttributePathIsDirty(aAttributePath);
- intersectsInterestPath = true;
- break;
- }
+ handler->AttributePathIsDirty(aAttributePath);
+ intersectsInterestPath = true;
+ break;
}
}
+ }
- return Loop::Continue;
- });
+ return Loop::Continue;
+ });
if (!intersectsInterestPath)
{
@@ -899,7 +900,7 @@
void Engine::GetMinEventLogPosition(uint32_t & aMinLogPosition)
{
- InteractionModelEngine::GetInstance()->mReadHandlers.ForEachActiveObject([&aMinLogPosition](ReadHandler * handler) {
+ mpImEngine->mReadHandlers.ForEachActiveObject([&aMinLogPosition](ReadHandler * handler) {
if (handler->IsType(ReadHandler::InteractionType::Read))
{
return Loop::Continue;
@@ -934,13 +935,13 @@
// we don't need to call schedule run for event.
// If schedule run is called, actually we would not delivery events as well.
// Just wanna save one schedule run here
- if (InteractionModelEngine::GetInstance()->mEventPathPool.Allocated() == 0)
+ if (mpImEngine->mEventPathPool.Allocated() == 0)
{
return CHIP_NO_ERROR;
}
bool isUrgentEvent = false;
- InteractionModelEngine::GetInstance()->mReadHandlers.ForEachActiveObject([&aPath, &isUrgentEvent](ReadHandler * handler) {
+ mpImEngine->mReadHandlers.ForEachActiveObject([&aPath, &isUrgentEvent](ReadHandler * handler) {
if (handler->IsType(ReadHandler::InteractionType::Read))
{
return Loop::Continue;
@@ -971,7 +972,7 @@
void Engine::ScheduleUrgentEventDeliverySync(Optional<FabricIndex> fabricIndex)
{
- InteractionModelEngine::GetInstance()->mReadHandlers.ForEachActiveObject([fabricIndex](ReadHandler * handler) {
+ mpImEngine->mReadHandlers.ForEachActiveObject([fabricIndex](ReadHandler * handler) {
if (handler->IsType(ReadHandler::InteractionType::Read))
{
return Loop::Continue;
diff --git a/src/app/reporting/Engine.h b/src/app/reporting/Engine.h
index 5a86381..01115b9 100644
--- a/src/app/reporting/Engine.h
+++ b/src/app/reporting/Engine.h
@@ -25,6 +25,7 @@
#pragma once
#include <access/AccessControl.h>
+#include <app/InteractionModelEngine.h>
#include <app/MessageDef/ReportDataMessage.h>
#include <app/ReadHandler.h>
#include <app/util/basic-types.h>
@@ -57,6 +58,11 @@
{
public:
/**
+ * Constructor Engine with a valid InteractionModelEngine pointer.
+ */
+ Engine(InteractionModelEngine * apImEngine);
+
+ /**
* Initializes the reporting engine. Should only be called once.
*
* @retval #CHIP_NO_ERROR On success.
@@ -279,6 +285,8 @@
uint32_t mReservedSize = 0;
uint32_t mMaxAttributesPerChunk = UINT32_MAX;
#endif
+
+ InteractionModelEngine * mpImEngine = nullptr;
};
}; // namespace reporting
diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp
index 4f26604..9e8bc58 100644
--- a/src/app/tests/TestReadInteraction.cpp
+++ b/src/app/tests/TestReadInteraction.cpp
@@ -285,6 +285,10 @@
public:
void OnDone(chip::app::ReadHandler & apReadHandlerObj) override {}
chip::app::ReadHandler::ApplicationCallback * GetAppCallback() override { return nullptr; }
+ chip::app::InteractionModelEngine * GetInteractionModelEngine() override
+ {
+ return chip::app::InteractionModelEngine::GetInstance();
+ }
};
} // namespace
diff --git a/src/app/tests/TestReportScheduler.cpp b/src/app/tests/TestReportScheduler.cpp
index af6f367..5219943 100644
--- a/src/app/tests/TestReportScheduler.cpp
+++ b/src/app/tests/TestReportScheduler.cpp
@@ -34,6 +34,10 @@
public:
void OnDone(chip::app::ReadHandler & apReadHandlerObj) override {}
chip::app::ReadHandler::ApplicationCallback * GetAppCallback() override { return nullptr; }
+ chip::app::InteractionModelEngine * GetInteractionModelEngine() override
+ {
+ return chip::app::InteractionModelEngine::GetInstance();
+ }
};
} // namespace
diff --git a/src/app/tests/TestReportingEngine.cpp b/src/app/tests/TestReportingEngine.cpp
index 5a19845..618a2e8 100644
--- a/src/app/tests/TestReportingEngine.cpp
+++ b/src/app/tests/TestReportingEngine.cpp
@@ -120,6 +120,10 @@
public:
void OnDone(ReadHandler & apHandler) override {}
chip::app::ReadHandler::ApplicationCallback * GetAppCallback() override { return nullptr; }
+ chip::app::InteractionModelEngine * GetInteractionModelEngine() override
+ {
+ return chip::app::InteractionModelEngine::GetInstance();
+ }
};
void TestReportingEngine::TestBuildAndSendSingleReportData(nlTestSuite * apSuite, void * apContext)