Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject event management into report engine #36831

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ source_set("test-event-trigger") {
sources = [ "TestEventTriggerDelegate.h" ]
}

source_set("event-reporter") {
sources = [ "EventReporter.h" ]
}

# interaction-model is a static-library because it currently requires global functions (app/util/...) that are stubbed in different test files that depend on the app static_library
# which in tern depens on the interaction-model.
# Using source_set prevents the unit test to build correctly.
Expand Down Expand Up @@ -210,6 +214,7 @@ static_library("interaction-model") {
":app_config",
":command-handler-impl",
":constants",
":event-reporter",
":paths",
":subscription-info-provider",
"${chip_root}/src/app/MessageDef",
Expand Down Expand Up @@ -455,6 +460,7 @@ static_library("app") {
":app_config",
":attribute-access",
":constants",
":event-reporter",
":global-attributes",
":interaction-model",
"${chip_root}/src/app/data-model",
Expand Down
17 changes: 15 additions & 2 deletions src/app/EventManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct CopyAndAdjustDeltaTimeContext
void EventManagement::Init(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers,
CircularEventBuffer * apCircularEventBuffer, const LogStorageResources * const apLogStorageResources,
MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
System::Clock::Milliseconds64 aMonotonicStartupTime)
System::Clock::Milliseconds64 aMonotonicStartupTime, EventReporter * apEventReporter)
{
CircularEventBuffer * current = nullptr;
CircularEventBuffer * prev = nullptr;
Expand Down Expand Up @@ -124,6 +124,16 @@ void EventManagement::Init(Messaging::ExchangeManager * apExchangeManager, uint3
mBytesWritten = 0;

mMonotonicStartupTime = aMonotonicStartupTime;

// Should remove using the global instance and rely only on passed in variable.
if (apEventReporter == nullptr)
{
mpEventReporter = &InteractionModelEngine::GetInstance()->GetReportingEngine();
}
else
{
mpEventReporter = apEventReporter;
}
}

CHIP_ERROR EventManagement::CopyToNextBuffer(CircularEventBuffer * apEventBuffer)
Expand Down Expand Up @@ -490,7 +500,10 @@ CHIP_ERROR EventManagement::LogEventPrivate(EventLoggingDelegate * apDelegate, c
opts.mTimestamp.mType == Timestamp::Type::kSystem ? "Sys" : "Epoch", ChipLogValueX64(opts.mTimestamp.mValue));
#endif // CHIP_CONFIG_EVENT_LOGGING_VERBOSE_DEBUG_LOGS

err = InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleEventDelivery(opts.mPath, mBytesWritten);
if (mpEventReporter)
{
err = mpEventReporter->NewEventGenerated(opts.mPath, mBytesWritten);
}
}

return err;
Expand Down
8 changes: 7 additions & 1 deletion src/app/EventManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "EventLoggingDelegate.h"
#include <access/SubjectDescriptor.h>
#include <app/EventLoggingTypes.h>
#include <app/EventReporter.h>
#include <app/MessageDef/EventDataIB.h>
#include <app/MessageDef/StatusIB.h>
#include <app/data-model-provider/EventsGenerator.h>
Expand Down Expand Up @@ -225,11 +226,14 @@ class EventManagement : public DataModel::EventsGenerator
* time 0" for cases when we use
* system-time event timestamps.
*
* @param[in] apEventReporter Event reporter to deliver the event, default is the reporting
* engine in InteractionModelEngine.
*
*/
void Init(Messaging::ExchangeManager * apExchangeManager, uint32_t aNumBuffers, CircularEventBuffer * apCircularEventBuffer,
const LogStorageResources * const apLogStorageResources,
MonotonicallyIncreasingCounter<EventNumber> * apEventNumberCounter,
System::Clock::Milliseconds64 aMonotonicStartupTime);
System::Clock::Milliseconds64 aMonotonicStartupTime, EventReporter * apEventReporter = nullptr);

static EventManagement & GetInstance();

Expand Down Expand Up @@ -563,6 +567,8 @@ class EventManagement : public DataModel::EventsGenerator
Timestamp mLastEventTimestamp; ///< The timestamp of the last event in this buffer

System::Clock::Milliseconds64 mMonotonicStartupTime;

EventReporter * mpEventReporter = nullptr;
};

} // namespace app
Expand Down
47 changes: 47 additions & 0 deletions src/app/EventReporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <app/ConcreteEventPath.h>
#include <lib/core/CHIPError.h>

namespace chip {
namespace app {

/**
* Define EventReporter interface. Event reporter is used by EventManagement to notify that events are ready to be reported.
* Usually this is implemented by the Reporting Engine to find the proper ReadHandlers and deliver the events.
*
*/
class EventReporter
{
public:
virtual ~EventReporter() = default;

/**
* Notify of a new event generated.
*
* @param[in] aPath The path to the event.
* @param[in] aBytesWritten Bytes that the event is written into the buffer in EventManagement.
*/
CHIP_ERROR virtual NewEventGenerated(ConcreteEventPath & aPath, uint32_t aBytesWritten) = 0;
};

} // namespace app
} // namespace chip
5 changes: 3 additions & 2 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ InteractionModelEngine * InteractionModelEngine::GetInstance()

CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeMgr, FabricTable * apFabricTable,
reporting::ReportScheduler * reportScheduler, CASESessionManager * apCASESessionMgr,
SubscriptionResumptionStorage * subscriptionResumptionStorage)
SubscriptionResumptionStorage * subscriptionResumptionStorage,
EventManagement * eventManagement)
{
VerifyOrReturnError(apFabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(apExchangeMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
Expand All @@ -165,7 +166,7 @@ CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeM
ReturnErrorOnFailure(mpFabricTable->AddFabricDelegate(this));
ReturnErrorOnFailure(mpExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id, this));

mReportingEngine.Init();
mReportingEngine.Init((eventManagement != nullptr) ? eventManagement : &EventManagement::GetInstance());

StatusIB::RegisterErrorFormatter();

Expand Down
4 changes: 3 additions & 1 deletion src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
* @param[in] apExchangeMgr A pointer to the ExchangeManager object.
* @param[in] apFabricTable A pointer to the FabricTable object.
* @param[in] apCASESessionMgr An optional pointer to a CASESessionManager (used for re-subscriptions).
* @parma[in] eventManagement An optional pointer to a EventManagement. Use the global instance if not presented.
*
*/
CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, FabricTable * apFabricTable,
reporting::ReportScheduler * reportScheduler, CASESessionManager * apCASESessionMgr = nullptr,
SubscriptionResumptionStorage * subscriptionResumptionStorage = nullptr);
SubscriptionResumptionStorage * subscriptionResumptionStorage = nullptr,
EventManagement * eventManagement = nullptr);

void Shutdown();

Expand Down
25 changes: 14 additions & 11 deletions src/app/reporting/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,13 @@ bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const Concrete

Engine::Engine(InteractionModelEngine * apImEngine) : mpImEngine(apImEngine) {}

CHIP_ERROR Engine::Init()
CHIP_ERROR Engine::Init(EventManagement * apEventManagement)
{
VerifyOrReturnError(apEventManagement != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
mNumReportsInFlight = 0;
mCurReadHandlerIdx = 0;
mpEventManagement = apEventManagement;

return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -560,20 +563,20 @@ CHIP_ERROR Engine::BuildSingleReportDataEventReports(ReportDataMessage::Builder
size_t eventCount = 0;
bool hasEncodedStatus = false;
TLV::TLVWriter backup;
bool eventClean = true;
auto & eventMin = apReadHandler->GetEventMin();
EventManagement & eventManager = EventManagement::GetInstance();
bool hasMoreChunks = false;
bool eventClean = true;
auto & eventMin = apReadHandler->GetEventMin();
bool hasMoreChunks = false;

aReportDataBuilder.Checkpoint(backup);

VerifyOrExit(apReadHandler->GetEventPathList() != nullptr, );

// If the eventManager is not valid or has not been initialized,
// If the mpEventManagement is not valid or has not been initialized,
// skip the rest of processing
VerifyOrExit(eventManager.IsValid(), ChipLogError(DataManagement, "EventManagement has not yet initialized"));
VerifyOrExit(mpEventManagement != nullptr && mpEventManagement->IsValid(),
ChipLogError(DataManagement, "EventManagement has not yet initialized"));

eventClean = apReadHandler->CheckEventClean(eventManager);
eventClean = apReadHandler->CheckEventClean(*mpEventManagement);

// proceed only if there are new events.
if (eventClean)
Expand All @@ -593,8 +596,8 @@ CHIP_ERROR Engine::BuildSingleReportDataEventReports(ReportDataMessage::Builder
err = CheckAccessDeniedEventPaths(*(eventReportIBs.GetWriter()), hasEncodedStatus, apReadHandler);
SuccessOrExit(err);

err = eventManager.FetchEventsSince(*(eventReportIBs.GetWriter()), apReadHandler->GetEventPathList(), eventMin, eventCount,
apReadHandler->GetSubjectDescriptor());
err = mpEventManagement->FetchEventsSince(*(eventReportIBs.GetWriter()), apReadHandler->GetEventPathList(), eventMin,
eventCount, apReadHandler->GetSubjectDescriptor());

if ((err == CHIP_END_OF_TLV) || (err == CHIP_ERROR_TLV_UNDERRUN) || (err == CHIP_NO_ERROR))
{
Expand Down Expand Up @@ -1128,7 +1131,7 @@ CHIP_ERROR Engine::ScheduleBufferPressureEventDelivery(uint32_t aBytesWritten)
return CHIP_NO_ERROR;
}

CHIP_ERROR Engine::ScheduleEventDelivery(ConcreteEventPath & aPath, uint32_t aBytesWritten)
CHIP_ERROR Engine::NewEventGenerated(ConcreteEventPath & aPath, uint32_t aBytesWritten)
{
// If we literally have no read handlers right now that care about any events,
// we don't need to call schedule run for event.
Expand Down
22 changes: 13 additions & 9 deletions src/app/reporting/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#pragma once

#include <access/AccessControl.h>
#include <app/EventReporter.h>
#include <app/MessageDef/ReportDataMessage.h>
#include <app/ReadHandler.h>
#include <app/data-model-provider/ProviderChangeListener.h>
Expand Down Expand Up @@ -55,7 +56,7 @@ namespace reporting {
* At its core, it tries to gather and pack as much relevant attributes changes and/or events as possible into a report
* message before sending that to the reader. It continues to do so until it has no more work to do.
*/
class Engine : public DataModel::ProviderChangeListener
class Engine : public DataModel::ProviderChangeListener, public EventReporter
{
public:
/**
Expand All @@ -66,10 +67,12 @@ class Engine : public DataModel::ProviderChangeListener
/**
* Initializes the reporting engine. Should only be called once.
*
* @param[in] A pointer to EventManagement, should not be a nullptr.
*
* @retval #CHIP_NO_ERROR On success.
* @retval other Was unable to retrieve data and write it into the writer.
*/
CHIP_ERROR Init();
CHIP_ERROR Init(EventManagement * apEventManagement);

void Shutdown();

Expand All @@ -96,13 +99,6 @@ class Engine : public DataModel::ProviderChangeListener
*/
CHIP_ERROR SetDirty(const AttributePathParams & aAttributePathParams);

/**
* @brief
* Schedule the event delivery
*
*/
CHIP_ERROR ScheduleEventDelivery(ConcreteEventPath & aPath, uint32_t aBytesWritten);

/*
* Resets the tracker that tracks the currently serviced read handler.
* apReadHandler can be non-null to indicate that the reset is due to a
Expand Down Expand Up @@ -182,6 +178,12 @@ class Engine : public DataModel::ProviderChangeListener
bool IsClusterDataVersionMatch(const SingleLinkedListNode<DataVersionFilter> * aDataVersionFilterList,
const ConcreteReadAttributePath & aPath);

/**
* EventReporter implementations.
*
*/
CHIP_ERROR NewEventGenerated(ConcreteEventPath & aPath, uint32_t aBytesWritten) override;

/**
* Send Report via ReadHandler
*
Expand Down Expand Up @@ -287,6 +289,8 @@ class Engine : public DataModel::ProviderChangeListener
#endif

InteractionModelEngine * mpImEngine = nullptr;

EventManagement * mpEventManagement = nullptr;
};

}; // namespace reporting
Expand Down
Loading