Skip to content

Commit 020ef75

Browse files
bzbarsky-appleaustina-csa
authored andcommitted
Add methods to clear data from the cluster state cache. (project-chip#34186)
This allows consumers to clear stale data when they detects PartsList/ServerList/AttributeList changes.
1 parent 32f36b3 commit 020ef75

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

src/app/ClusterStateCache.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,47 @@ CHIP_ERROR ClusterStateCacheT<CanEnableDataCaching>::OnUpdateDataVersionFilterLi
648648
return err;
649649
}
650650

651+
template <bool CanEnableDataCaching>
652+
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttributes(EndpointId endpointId)
653+
{
654+
mCache.erase(endpointId);
655+
}
656+
657+
template <bool CanEnableDataCaching>
658+
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttributes(const ConcreteClusterPath & cluster)
659+
{
660+
// Can't use GetEndpointState here, since that only handles const things.
661+
auto endpointIter = mCache.find(cluster.mEndpointId);
662+
if (endpointIter == mCache.end())
663+
{
664+
return;
665+
}
666+
667+
auto & endpointState = endpointIter->second;
668+
endpointState.erase(cluster.mClusterId);
669+
}
670+
671+
template <bool CanEnableDataCaching>
672+
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttribute(const ConcreteAttributePath & attribute)
673+
{
674+
// Can't use GetClusterState here, since that only handles const things.
675+
auto endpointIter = mCache.find(attribute.mEndpointId);
676+
if (endpointIter == mCache.end())
677+
{
678+
return;
679+
}
680+
681+
auto & endpointState = endpointIter->second;
682+
auto clusterIter = endpointState.find(attribute.mClusterId);
683+
if (clusterIter == endpointState.end())
684+
{
685+
return;
686+
}
687+
688+
auto & clusterState = clusterIter->second;
689+
clusterState.mAttributes.erase(attribute.mAttributeId);
690+
}
691+
651692
template <bool CanEnableDataCaching>
652693
CHIP_ERROR ClusterStateCacheT<CanEnableDataCaching>::GetLastReportDataPath(ConcreteClusterPath & aPath)
653694
{

src/app/ClusterStateCache.h

+16
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,22 @@ class ClusterStateCacheT : protected ReadClient::Callback
504504
}
505505
}
506506

507+
/*
508+
* Clear out all the attribute data and DataVersions stored for a given endpoint.
509+
*/
510+
void ClearAttributes(EndpointId endpoint);
511+
512+
/*
513+
* Clear out all the attribute data and the DataVersion stored for a given cluster.
514+
*/
515+
void ClearAttributes(const ConcreteClusterPath & cluster);
516+
517+
/*
518+
* Clear out the data (or size, if not storing data) stored for an
519+
* attribute.
520+
*/
521+
void ClearAttribute(const ConcreteAttributePath & attribute);
522+
507523
/*
508524
* Clear out the event data and status caches.
509525
*

src/app/tests/TestClusterStateCache.cpp

+93
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ struct AttributeInstruction
101101
}
102102
}
103103

104+
ConcreteAttributePath GetAttributePath() const
105+
{
106+
return ConcreteAttributePath(mEndpointId, Clusters::UnitTesting::Id, GetAttributeId());
107+
}
108+
104109
static uint8_t sInstructionId;
105110
};
106111

@@ -626,6 +631,94 @@ void RunAndValidateSequence(AttributeInstructionListType list)
626631

627632
++bufferSize;
628633
} while (true);
634+
635+
// Now check clearing behavior. First for attributes.
636+
ConcreteAttributePath firstAttr = list[0].GetAttributePath();
637+
638+
TLV::TLVReader reader;
639+
CHIP_ERROR err = cache.Get(firstAttr, reader);
640+
// Should have gotten a value or status for now.
641+
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
642+
643+
cache.ClearAttribute(firstAttr);
644+
645+
err = cache.Get(firstAttr, reader);
646+
// Should have gotten no value.
647+
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);
648+
649+
// Now clearing for clusters. First check that things that should be there are.
650+
for (auto & listItem : list)
651+
{
652+
ConcreteAttributePath path = listItem.GetAttributePath();
653+
if (path == firstAttr)
654+
{
655+
// We removed this one already.
656+
continue;
657+
}
658+
659+
err = cache.Get(path, reader);
660+
661+
// Should have gotten a value or status for now.
662+
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
663+
}
664+
665+
auto firstCluster = ConcreteClusterPath(firstAttr);
666+
cache.ClearAttributes(firstCluster);
667+
668+
for (auto & listItem : list)
669+
{
670+
ConcreteAttributePath path = listItem.GetAttributePath();
671+
672+
err = cache.Get(path, reader);
673+
674+
if (ConcreteClusterPath(path) == firstCluster)
675+
{
676+
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);
677+
}
678+
else
679+
{
680+
// Should still have a value or status
681+
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
682+
}
683+
}
684+
685+
// Now clearing for endpoints. First check that things that should be there are.
686+
// TODO: Since all our attributes have the same cluster, this is not
687+
// actually testing anything useful right now.
688+
for (auto & listItem : list)
689+
{
690+
ConcreteAttributePath path = listItem.GetAttributePath();
691+
if (ConcreteClusterPath(path) == firstCluster)
692+
{
693+
// We removed this one already.
694+
continue;
695+
}
696+
697+
err = cache.Get(path, reader);
698+
699+
// Should have gotten a value or status for now.
700+
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
701+
}
702+
703+
auto firstEndpoint = firstAttr.mEndpointId;
704+
cache.ClearAttributes(firstEndpoint);
705+
706+
for (auto & listItem : list)
707+
{
708+
ConcreteAttributePath path = listItem.GetAttributePath();
709+
710+
err = cache.Get(path, reader);
711+
712+
if (path.mEndpointId == firstEndpoint)
713+
{
714+
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);
715+
}
716+
else
717+
{
718+
// Should still have a value or status
719+
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
720+
}
721+
}
629722
}
630723

631724
/*

0 commit comments

Comments
 (0)