Skip to content

Commit 2619da7

Browse files
[Scenes] MaxCapacity fix (project-chip#31981)
* Added refresh on read to the FabricSceneInfo capacity and patched Resource Exhausted for Copy Scene and Store Scene along with tests * Applied suggested fix on ReturnOnFailure and /* = name*/
1 parent 2696bc9 commit 2619da7

File tree

3 files changed

+920
-20
lines changed

3 files changed

+920
-20
lines changed

src/app/clusters/scenes-server/scenes-server.cpp

+29-20
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ CHIP_ERROR AddResponseOnError(CommandHandlerInterface::HandlerContext & ctx, Res
6666
{
6767
resp.status = to_underlying(Protocols::InteractionModel::Status::NotFound);
6868
}
69+
else if (CHIP_ERROR_NO_MEMORY == err)
70+
{
71+
resp.status = to_underlying(Protocols::InteractionModel::Status::ResourceExhausted);
72+
}
6973
else
7074
{
7175
resp.status = to_underlying(StatusIB(err).mStatus);
@@ -168,7 +172,6 @@ CHIP_ERROR UpdateFabricSceneInfo(EndpointId endpoint, FabricIndex fabric, Option
168172

169173
/// @brief Gets the SceneInfoStruct array associated to an endpoint
170174
/// @param endpoint target endpoint
171-
/// @param fabric target fabric
172175
/// @return Optional with no value not found, Span of SceneInfoStruct
173176
Span<Structs::SceneInfoStruct::Type> ScenesServer::FabricSceneInfo::GetFabricSceneInfo(EndpointId endpoint)
174177
{
@@ -675,13 +678,21 @@ void ScenesServer::InvokeCommand(HandlerContext & ctxt)
675678
// AttributeAccessInterface
676679
CHIP_ERROR ScenesServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
677680
{
681+
uint16_t endpointTableSize = 0;
682+
ReturnErrorOnFailure(StatusIB(Attributes::SceneTableSize::Get(aPath.mEndpointId, &endpointTableSize)).ToChipError());
683+
684+
// Get Scene Table Instance
685+
SceneTable * sceneTable = scenes::GetSceneTableImpl(aPath.mEndpointId, endpointTableSize);
686+
678687
switch (aPath.mAttributeId)
679688
{
680689
case Attributes::FabricSceneInfo::Id: {
681-
return aEncoder.EncodeList([&](const auto & encoder) -> CHIP_ERROR {
690+
return aEncoder.EncodeList([&, sceneTable](const auto & encoder) -> CHIP_ERROR {
682691
Span<Structs::SceneInfoStruct::Type> fabricSceneInfoSpan = mFabricSceneInfo.GetFabricSceneInfo(aPath.mEndpointId);
683692
for (auto & info : fabricSceneInfoSpan)
684693
{
694+
// Update the SceneInfoStruct's Capacity in case it's capacity was limited by other fabrics
695+
sceneTable->GetRemainingCapacity(info.fabricIndex, info.remainingCapacity);
685696
ReturnErrorOnFailure(encoder.Encode(info));
686697
}
687698
return CHIP_NO_ERROR;
@@ -918,12 +929,10 @@ void ScenesServer::HandleStoreScene(HandlerContext & ctx, const Commands::StoreS
918929
CHIP_ERROR err = StoreSceneParse(ctx.mCommandHandler.GetAccessingFabricIndex(), ctx.mRequestPath.mEndpointId, req.groupID,
919930
req.sceneID, mGroupProvider);
920931

921-
if (CHIP_NO_ERROR == err)
922-
{
923-
ReturnOnFailure(UpdateLastConfiguredBy(ctx, response));
924-
}
932+
ReturnOnFailure(AddResponseOnError(ctx, response, err));
925933

926-
response.status = to_underlying(StatusIB(err).mStatus);
934+
ReturnOnFailure(UpdateLastConfiguredBy(ctx, response));
935+
response.status = to_underlying(Protocols::InteractionModel::Status::Success);
927936
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
928937
}
929938

@@ -1031,6 +1040,13 @@ void ScenesServer::HandleCopyScene(HandlerContext & ctx, const Commands::CopySce
10311040
ReturnOnFailure(AddResponseOnError(ctx, response,
10321041
sceneTable->GetRemainingCapacity(ctx.mCommandHandler.GetAccessingFabricIndex(), capacity)));
10331042

1043+
if (0 == capacity)
1044+
{
1045+
response.status = to_underlying(Protocols::InteractionModel::Status::ResourceExhausted);
1046+
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
1047+
return;
1048+
}
1049+
10341050
// Checks if we copy a single scene or all of them
10351051
if (req.mode.GetField(app::Clusters::ScenesManagement::CopyModeBitmap::kCopyAllScenes))
10361052
{
@@ -1043,13 +1059,6 @@ void ScenesServer::HandleCopyScene(HandlerContext & ctx, const Commands::CopySce
10431059
ctx, response,
10441060
sceneTable->GetAllSceneIdsInGroup(ctx.mCommandHandler.GetAccessingFabricIndex(), req.groupIdentifierFrom, sceneList)));
10451061

1046-
if (0 == capacity)
1047-
{
1048-
response.status = to_underlying(Protocols::InteractionModel::Status::ResourceExhausted);
1049-
ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response);
1050-
return;
1051-
}
1052-
10531062
for (auto & sceneId : sceneList)
10541063
{
10551064
SceneTableEntry scene(SceneStorageId(sceneId, req.groupIdentifierFrom));
@@ -1062,13 +1071,13 @@ void ScenesServer::HandleCopyScene(HandlerContext & ctx, const Commands::CopySce
10621071

10631072
ReturnOnFailure(AddResponseOnError(
10641073
ctx, response, sceneTable->SetSceneTableEntry(ctx.mCommandHandler.GetAccessingFabricIndex(), scene)));
1065-
}
10661074

1067-
// Update SceneInfoStruct Attributes
1068-
ReturnOnFailure(
1069-
AddResponseOnError(ctx, response,
1070-
UpdateFabricSceneInfo(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(),
1071-
Optional<GroupId>(), Optional<SceneId>(), Optional<bool>())));
1075+
// Update SceneInfoStruct Attributes after each insert in case we hit max capacity in the middle of the loop
1076+
ReturnOnFailure(AddResponseOnError(
1077+
ctx, response,
1078+
UpdateFabricSceneInfo(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(),
1079+
Optional<GroupId>(), Optional<SceneId>(), Optional<bool>() /* = sceneValid*/)));
1080+
}
10721081

10731082
ReturnOnFailure(UpdateLastConfiguredBy(ctx, response));
10741083

0 commit comments

Comments
 (0)