Skip to content

Commit

Permalink
Inject event management into report engine (project-chip#36831)
Browse files Browse the repository at this point in the history
* Inject event management into report engine

* Restyled by whitespace

* Restyled by clang-format

* add event scheduler file

* add missing includes

* Rename it to EventReporter

* Restyled by clang-format

* Restyled by gn

* Modify comments and fix typo

* Fix some comments

* Restyled by clang-format

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
yyzhong-g and restyled-commits authored Dec 18, 2024
1 parent 27ca6ec commit 48e8a0e
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 27 deletions.
6 changes: 6 additions & 0 deletions src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,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 @@ -211,6 +215,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 @@ -456,6 +461,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
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

0 comments on commit 48e8a0e

Please sign in to comment.