Matter SDK Coverage Report
Current view: top level - app/reporting - ReportSchedulerImpl.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 96.8 % 63 61
Test Date: 2025-01-17 19:00:11 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2023 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #include <app/AppConfig.h>
      19              : #include <app/InteractionModelEngine.h>
      20              : #include <app/reporting/ReportSchedulerImpl.h>
      21              : 
      22              : namespace chip {
      23              : namespace app {
      24              : namespace reporting {
      25              : 
      26              : using namespace System::Clock;
      27              : using ReadHandlerNode = ReportScheduler::ReadHandlerNode;
      28              : 
      29              : /// @brief Callback called when the report timer expires to schedule an engine run regardless of the state of the ReadHandlers, as
      30              : /// the engine already verifies that read handlers are reportable before sending a report
      31          129 : void ReportSchedulerImpl::ReportTimerCallback()
      32              : {
      33          129 :     InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
      34          129 : }
      35              : 
      36           54 : ReportSchedulerImpl::ReportSchedulerImpl(TimerDelegate * aTimerDelegate) : ReportScheduler(aTimerDelegate)
      37              : {
      38           54 :     VerifyOrDie(nullptr != mTimerDelegate);
      39           54 : }
      40              : 
      41              : /// @brief Method that triggers a report emission on each ReadHandler that is not blocked on its min interval.
      42              : ///        Each read handler that is not blocked is immediately marked dirty so that it will report as soon as possible.
      43            0 : void ReportSchedulerImpl::OnEnterActiveMode()
      44              : {
      45              : #if ICD_REPORT_ON_ENTER_ACTIVE_MODE
      46              :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      47              :     mNodesPool.ForEachActiveObject([this, now](ReadHandlerNode * node) {
      48              :         if (now >= node->GetMinTimestamp())
      49              :         {
      50              :             this->HandlerForceDirtyState(node->GetReadHandler());
      51              :         }
      52              : 
      53              :         return Loop::Continue;
      54              :     });
      55              : #endif
      56            0 : }
      57              : 
      58          237 : void ReportSchedulerImpl::OnSubscriptionEstablished(ReadHandler * aReadHandler)
      59              : {
      60          237 :     ReadHandlerNode * newNode = FindReadHandlerNode(aReadHandler);
      61              :     // Handler must not be registered yet; it's just being constructed.
      62          237 :     VerifyOrDie(nullptr == newNode);
      63              : 
      64          237 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      65              : 
      66              :     // The NodePool is the same size as the ReadHandler pool from the IM Engine, so we don't need a check for size here since if a
      67              :     // ReadHandler was created, space should be available.
      68          237 :     newNode = mNodesPool.CreateObject(aReadHandler, this, now);
      69              : 
      70          237 :     ChipLogProgress(DataManagement,
      71              :                     "Registered a ReadHandler that will schedule a report between system Timestamp: 0x" ChipLogFormatX64
      72              :                     " and system Timestamp 0x" ChipLogFormatX64 ".",
      73              :                     ChipLogValueX64(newNode->GetMinTimestamp().count()), ChipLogValueX64(newNode->GetMaxTimestamp().count()));
      74          237 : }
      75              : 
      76          692 : void ReportSchedulerImpl::OnBecameReportable(ReadHandler * aReadHandler)
      77              : {
      78          692 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
      79          692 :     VerifyOrReturn(nullptr != node);
      80              : 
      81          432 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      82              : 
      83              :     Milliseconds32 newTimeout;
      84          432 :     CalculateNextReportTimeout(newTimeout, node, now);
      85          432 :     ScheduleReport(newTimeout, node, now);
      86              : }
      87              : 
      88          113 : void ReportSchedulerImpl::OnSubscriptionReportSent(ReadHandler * aReadHandler)
      89              : {
      90          113 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
      91          113 :     VerifyOrReturn(nullptr != node);
      92              : 
      93          113 :     Timestamp now = mTimerDelegate->GetCurrentMonotonicTimestamp();
      94              : 
      95              :     // This method is called after the report is sent, so the ReadHandler is no longer reportable, and thus CanBeSynced and
      96              :     // EngineRunScheduled of the node associated with the ReadHandler are set to false here.
      97          113 :     node->SetCanBeSynced(false);
      98          113 :     node->SetIntervalTimeStamps(aReadHandler, now);
      99              :     Milliseconds32 newTimeout;
     100              :     // Reset the EngineRunScheduled flag so that the next report is scheduled correctly
     101          113 :     node->SetEngineRunScheduled(false);
     102          113 :     CalculateNextReportTimeout(newTimeout, node, now);
     103          113 :     ScheduleReport(newTimeout, node, now);
     104              : }
     105              : 
     106         1033 : void ReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aReadHandler)
     107              : {
     108         1033 :     CancelReport(aReadHandler);
     109              : 
     110         1033 :     ReadHandlerNode * removeNode = FindReadHandlerNode(aReadHandler);
     111              :     // Nothing to remove if the handler is not found in the list
     112         1033 :     VerifyOrReturn(nullptr != removeNode);
     113              : 
     114          211 :     mNodesPool.ReleaseObject(removeNode);
     115              : }
     116              : 
     117          392 : CHIP_ERROR ReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
     118              : {
     119              :     // Cancel Report if it is currently scheduled
     120          392 :     mTimerDelegate->CancelTimer(node);
     121          392 :     if (timeout == Milliseconds32(0))
     122              :     {
     123          102 :         node->TimerFired();
     124          102 :         return CHIP_NO_ERROR;
     125              :     }
     126          290 :     ReturnErrorOnFailure(mTimerDelegate->StartTimer(node, timeout));
     127              : 
     128          290 :     return CHIP_NO_ERROR;
     129              : }
     130              : 
     131         1034 : void ReportSchedulerImpl::CancelReport(ReadHandler * aReadHandler)
     132              : {
     133         1034 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     134         1034 :     VerifyOrReturn(nullptr != node);
     135          212 :     mTimerDelegate->CancelTimer(node);
     136              : }
     137              : 
     138           83 : void ReportSchedulerImpl::UnregisterAllHandlers()
     139              : {
     140           83 :     mNodesPool.ForEachActiveObject([this](ReadHandlerNode * node) {
     141           18 :         this->OnReadHandlerDestroyed(node->GetReadHandler());
     142           18 :         return Loop::Continue;
     143              :     });
     144           83 : }
     145              : 
     146           14 : bool ReportSchedulerImpl::IsReportScheduled(ReadHandler * aReadHandler)
     147              : {
     148           14 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     149           14 :     VerifyOrReturnValue(nullptr != node, false);
     150           11 :     return mTimerDelegate->IsTimerActive(node);
     151              : }
     152              : 
     153          392 : CHIP_ERROR ReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode, const Timestamp & now)
     154              : {
     155          392 :     VerifyOrReturnError(nullptr != FindReadHandlerNode(aNode->GetReadHandler()), CHIP_ERROR_INVALID_ARGUMENT);
     156              : 
     157              :     // If the handler is reportable now, just schedule a report immediately
     158          392 :     if (aNode->IsReportableNow(now))
     159              :     {
     160              :         // If the handler is reportable now, just schedule a report immediately
     161           93 :         timeout = Milliseconds32(0);
     162              :     }
     163          299 :     else if (IsReadHandlerReportable(aNode->GetReadHandler()) && (aNode->GetMinTimestamp() > now))
     164              :     {
     165              :         // If the handler is reportable now, but the min interval is not elapsed, schedule a report for the moment the min interval
     166              :         // has elapsed
     167            5 :         timeout = aNode->GetMinTimestamp() - now;
     168              :     }
     169              :     else
     170              :     {
     171              :         // If the handler is not reportable now, schedule a report for the max interval
     172          294 :         timeout = aNode->GetMaxTimestamp() - now;
     173              :     }
     174          392 :     return CHIP_NO_ERROR;
     175              : }
     176              : 
     177              : } // namespace reporting
     178              : } // namespace app
     179              : } // namespace chip
        

Generated by: LCOV version 2.0-1