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

Merged
merged 11 commits into from
Dec 18, 2024
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
14 changes: 12 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;

// TODO(#36890): 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,7 @@ 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);
err = mpEventReporter->NewEventGenerated(opts.mPath, mBytesWritten);
}

return err;
Expand Down
7 changes: 6 additions & 1 deletion src/app/EventManagement.h
yyzhong-g marked this conversation as resolved.
Show resolved Hide resolved
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,13 @@ class EventManagement : public DataModel::EventsGenerator
* time 0" for cases when we use
* system-time event timestamps.
*
* @param[in] apEventReporter Event reporter to be notified when events are generated.
*
*/
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 +566,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
46 changes: 46 additions & 0 deletions src/app/EventReporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
*
* 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 {

/**
* Interface that EventManagement can use to notify when events are generated and may need reporting.
*
*/
class EventReporter
{
public:
virtual ~EventReporter() = default;

/**
* Notify that an event was generated.
*
* @param[in] aPath The path that identifies the kind of event that was generated.
* @param[in] aBytesConsumed The number of bytes needed to store the event in EventManagement.
*/
CHIP_ERROR virtual NewEventGenerated(ConcreteEventPath & aPath, uint32_t aBytesConsumed) = 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. If null, the global instance will be used.
*
*/
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
27 changes: 15 additions & 12 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 aBytesConsumed)
{
// 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 Expand Up @@ -1166,7 +1169,7 @@ CHIP_ERROR Engine::ScheduleEventDelivery(ConcreteEventPath & aPath, uint32_t aBy
return CHIP_NO_ERROR;
}

return ScheduleBufferPressureEventDelivery(aBytesWritten);
return ScheduleBufferPressureEventDelivery(aBytesConsumed);
}

void Engine::ScheduleUrgentEventDeliverySync(Optional<FabricIndex> fabricIndex)
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 implementation.
*
*/
CHIP_ERROR NewEventGenerated(ConcreteEventPath & aPath, uint32_t aBytesConsumed) 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