Skip to content

Commit

Permalink
[IM] Fix EnsureResourceForSubscription (project-chip#18533)
Browse files Browse the repository at this point in the history
* [IM] Fix EnsureResourceForSubscription

* Address comments

* Fix

* Remove TestReadHandlerResourceExhaustion_MultipleSubscriptions since it is covered by resource minimas of subscription tests

* Add comments

* address comments

* Fix merge
  • Loading branch information
erjiaqing authored May 25, 2022
1 parent 5167991 commit ebc8c17
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 136 deletions.
57 changes: 37 additions & 20 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,25 +372,13 @@ CHIP_ERROR InteractionModelEngine::OnReadInitialRequest(Messaging::ExchangeConte
}
}

size_t handlerPoolCapacity = mReadHandlers.Capacity();

#if CONFIG_IM_BUILD_FOR_UNIT_TEST
size_t handlerPoolCapacity = mReadHandlers.Capacity();
if (mReadHandlerCapacityOverride != -1)
{
handlerPoolCapacity = (size_t) mReadHandlerCapacityOverride;
}
#endif

// Reserve the last ReadHandler for ReadInteraction
if (aInteractionType == ReadHandler::InteractionType::Subscribe && ((handlerPoolCapacity - GetNumActiveReadHandlers()) == 1) &&
!HasActiveRead())
{
ChipLogDetail(InteractionModel, "Reserve the last ReadHandler for IM read Interaction");
aStatus = Protocols::InteractionModel::Status::ResourceExhausted;
return CHIP_NO_ERROR;
}

#if CONFIG_IM_BUILD_FOR_UNIT_TEST
if ((handlerPoolCapacity - GetNumActiveReadHandlers()) == 0)
{
aStatus = Protocols::InteractionModel::Status::ResourceExhausted;
Expand Down Expand Up @@ -668,9 +656,27 @@ bool InteractionModelEngine::EnsureResourceForSubscription(FabricIndex aFabricIn
const size_t readHandlerCap =
allowUnlimited ? SIZE_MAX : static_cast<size_t>(readHandlerPoolCapacity - kReservedHandlersForReads);

size_t usedAttributePaths = mAttributePathPool.Allocated();
size_t usedEventPaths = mEventPathPool.Allocated();
size_t usedReadHandlers = mReadHandlers.Allocated();
size_t usedAttributePaths = 0;
size_t usedEventPaths = 0;
size_t usedReadHandlers = 0;

auto countResourceUsage = [&]() {
usedAttributePaths = 0;
usedEventPaths = 0;
usedReadHandlers = 0;
mReadHandlers.ForEachActiveObject([&](auto * handler) {
if (!handler->IsType(ReadHandler::InteractionType::Subscribe))
{
return Loop::Continue;
}
usedAttributePaths += handler->GetAttributePathCount();
usedEventPaths += handler->GetEventPathCount();
usedReadHandlers++;
return Loop::Continue;
});
};

countResourceUsage();

if (usedAttributePaths + aRequestedAttributePathCount <= attributePathCap &&
usedEventPaths + aRequestedEventPathCount <= eventPathCap && usedReadHandlers < readHandlerCap)
Expand All @@ -688,10 +694,8 @@ bool InteractionModelEngine::EnsureResourceForSubscription(FabricIndex aFabricIn
}

const auto evictAndUpdateResourceUsage = [&](FabricIndex fabricIndex, bool forceEvict) {
bool ret = TrimFabric(fabricIndex, forceEvict);
usedAttributePaths = mAttributePathPool.Allocated();
usedEventPaths = mEventPathPool.Allocated();
usedReadHandlers = mReadHandlers.Allocated();
bool ret = TrimFabric(fabricIndex, forceEvict);
countResourceUsage();
return ret;
};

Expand Down Expand Up @@ -1181,5 +1185,18 @@ uint16_t InteractionModelEngine::GetMinSubscriptionsPerFabric() const
return static_cast<uint16_t>(perFabricSubscriptionCapacity);
}

size_t InteractionModelEngine::GetNumDirtySubscriptions() const
{
size_t numDirtySubscriptions = 0;
mReadHandlers.ForEachActiveObject([&](const auto readHandler) {
if (readHandler->IsType(ReadHandler::InteractionType::Subscribe) && readHandler->IsDirty())
{
numDirtySubscriptions++;
}
return Loop::Continue;
});
return numDirtySubscriptions;
}

} // namespace app
} // namespace chip
5 changes: 5 additions & 0 deletions src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
*/
size_t GetNumActiveReadClients();

/**
* Returns the number of dirty subscriptions. Including the subscriptions that are generating reports.
*/
size_t GetNumDirtySubscriptions() const;

/**
* Returns whether the write operation to the given path is conflict with another write operations. (i.e. another write
* transaction is in the middle of processing the chunked value of the given path.)
Expand Down
Loading

0 comments on commit ebc8c17

Please sign in to comment.