LCOV - code coverage report
Current view: top level - app/reporting - ReportSchedulerImpl.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 61 63 96.8 %
Date: 2024-02-15 08:20:41 Functions: 12 13 92.3 %

          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         125 : void ReportSchedulerImpl::ReportTimerCallback()
      32             : {
      33         125 :     InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun();
      34         125 : }
      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         113 :     node->SetCanBeSynced(false);
      96         113 :     node->SetIntervalTimeStamps(aReadHandler, now);
      97             :     Milliseconds32 newTimeout;
      98             :     // Reset the EngineRunScheduled flag so that the next report is scheduled correctly
      99         113 :     node->SetEngineRunScheduled(false);
     100         113 :     CalculateNextReportTimeout(newTimeout, node, now);
     101         113 :     ScheduleReport(newTimeout, node, now);
     102             : }
     103             : 
     104         949 : void ReportSchedulerImpl::OnReadHandlerDestroyed(ReadHandler * aReadHandler)
     105             : {
     106         949 :     CancelReport(aReadHandler);
     107             : 
     108         949 :     ReadHandlerNode * removeNode = FindReadHandlerNode(aReadHandler);
     109             :     // Nothing to remove if the handler is not found in the list
     110         949 :     VerifyOrReturn(nullptr != removeNode);
     111             : 
     112         211 :     mNodesPool.ReleaseObject(removeNode);
     113             : }
     114             : 
     115         392 : CHIP_ERROR ReportSchedulerImpl::ScheduleReport(Timeout timeout, ReadHandlerNode * node, const Timestamp & now)
     116             : {
     117             :     // Cancel Report if it is currently scheduled
     118         392 :     mTimerDelegate->CancelTimer(node);
     119         392 :     if (timeout == Milliseconds32(0))
     120             :     {
     121         102 :         node->TimerFired();
     122         102 :         return CHIP_NO_ERROR;
     123             :     }
     124         290 :     ReturnErrorOnFailure(mTimerDelegate->StartTimer(node, timeout));
     125             : 
     126         290 :     return CHIP_NO_ERROR;
     127             : }
     128             : 
     129         950 : void ReportSchedulerImpl::CancelReport(ReadHandler * aReadHandler)
     130             : {
     131         950 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     132         950 :     VerifyOrReturn(nullptr != node);
     133         212 :     mTimerDelegate->CancelTimer(node);
     134             : }
     135             : 
     136          83 : void ReportSchedulerImpl::UnregisterAllHandlers()
     137             : {
     138          83 :     mNodesPool.ForEachActiveObject([this](ReadHandlerNode * node) {
     139          18 :         this->OnReadHandlerDestroyed(node->GetReadHandler());
     140          18 :         return Loop::Continue;
     141             :     });
     142          83 : }
     143             : 
     144          14 : bool ReportSchedulerImpl::IsReportScheduled(ReadHandler * aReadHandler)
     145             : {
     146          14 :     ReadHandlerNode * node = FindReadHandlerNode(aReadHandler);
     147          14 :     VerifyOrReturnValue(nullptr != node, false);
     148          11 :     return mTimerDelegate->IsTimerActive(node);
     149             : }
     150             : 
     151         392 : CHIP_ERROR ReportSchedulerImpl::CalculateNextReportTimeout(Timeout & timeout, ReadHandlerNode * aNode, const Timestamp & now)
     152             : {
     153         392 :     VerifyOrReturnError(nullptr != FindReadHandlerNode(aNode->GetReadHandler()), CHIP_ERROR_INVALID_ARGUMENT);
     154             : 
     155             :     // If the handler is reportable now, just schedule a report immediately
     156         392 :     if (aNode->IsReportableNow(now))
     157             :     {
     158             :         // If the handler is reportable now, just schedule a report immediately
     159          93 :         timeout = Milliseconds32(0);
     160             :     }
     161         299 :     else if (IsReadHandlerReportable(aNode->GetReadHandler()) && (aNode->GetMinTimestamp() > now))
     162             :     {
     163             :         // If the handler is reportable now, but the min interval is not elapsed, schedule a report for the moment the min interval
     164             :         // has elapsed
     165           5 :         timeout = aNode->GetMinTimestamp() - now;
     166             :     }
     167             :     else
     168             :     {
     169             :         // If the handler is not reportable now, schedule a report for the max interval
     170         294 :         timeout = aNode->GetMaxTimestamp() - now;
     171             :     }
     172         392 :     return CHIP_NO_ERROR;
     173             : }
     174             : 
     175             : } // namespace reporting
     176             : } // namespace app
     177             : } // namespace chip

Generated by: LCOV version 1.14