Skip to content

Commit

Permalink
Add methods to clear data from the cluster state cache. (#34186)
Browse files Browse the repository at this point in the history
This allows consumers to clear stale data when they detects
PartsList/ServerList/AttributeList changes.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Aug 20, 2024
1 parent 4626930 commit 3319279
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/app/ClusterStateCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,47 @@ CHIP_ERROR ClusterStateCacheT<CanEnableDataCaching>::OnUpdateDataVersionFilterLi
return err;
}

template <bool CanEnableDataCaching>
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttributes(EndpointId endpointId)
{
mCache.erase(endpointId);
}

template <bool CanEnableDataCaching>
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttributes(const ConcreteClusterPath & cluster)
{
// Can't use GetEndpointState here, since that only handles const things.
auto endpointIter = mCache.find(cluster.mEndpointId);
if (endpointIter == mCache.end())
{
return;
}

auto & endpointState = endpointIter->second;
endpointState.erase(cluster.mClusterId);
}

template <bool CanEnableDataCaching>
void ClusterStateCacheT<CanEnableDataCaching>::ClearAttribute(const ConcreteAttributePath & attribute)
{
// Can't use GetClusterState here, since that only handles const things.
auto endpointIter = mCache.find(attribute.mEndpointId);
if (endpointIter == mCache.end())
{
return;
}

auto & endpointState = endpointIter->second;
auto clusterIter = endpointState.find(attribute.mClusterId);
if (clusterIter == endpointState.end())
{
return;
}

auto & clusterState = clusterIter->second;
clusterState.mAttributes.erase(attribute.mAttributeId);
}

template <bool CanEnableDataCaching>
CHIP_ERROR ClusterStateCacheT<CanEnableDataCaching>::GetLastReportDataPath(ConcreteClusterPath & aPath)
{
Expand Down
16 changes: 16 additions & 0 deletions src/app/ClusterStateCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,22 @@ class ClusterStateCacheT : protected ReadClient::Callback
}
}

/*
* Clear out all the attribute data and DataVersions stored for a given endpoint.
*/
void ClearAttributes(EndpointId endpoint);

/*
* Clear out all the attribute data and the DataVersion stored for a given cluster.
*/
void ClearAttributes(const ConcreteClusterPath & cluster);

/*
* Clear out the data (or size, if not storing data) stored for an
* attribute.
*/
void ClearAttribute(const ConcreteAttributePath & attribute);

/*
* Clear out the event data and status caches.
*
Expand Down
93 changes: 93 additions & 0 deletions src/app/tests/TestClusterStateCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ struct AttributeInstruction
}
}

ConcreteAttributePath GetAttributePath() const
{
return ConcreteAttributePath(mEndpointId, Clusters::UnitTesting::Id, GetAttributeId());
}

static uint8_t sInstructionId;
};

Expand Down Expand Up @@ -626,6 +631,94 @@ void RunAndValidateSequence(AttributeInstructionListType list)

++bufferSize;
} while (true);

// Now check clearing behavior. First for attributes.
ConcreteAttributePath firstAttr = list[0].GetAttributePath();

TLV::TLVReader reader;
CHIP_ERROR err = cache.Get(firstAttr, reader);
// Should have gotten a value or status for now.
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);

cache.ClearAttribute(firstAttr);

err = cache.Get(firstAttr, reader);
// Should have gotten no value.
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);

// Now clearing for clusters. First check that things that should be there are.
for (auto & listItem : list)
{
ConcreteAttributePath path = listItem.GetAttributePath();
if (path == firstAttr)
{
// We removed this one already.
continue;
}

err = cache.Get(path, reader);

// Should have gotten a value or status for now.
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
}

auto firstCluster = ConcreteClusterPath(firstAttr);
cache.ClearAttributes(firstCluster);

for (auto & listItem : list)
{
ConcreteAttributePath path = listItem.GetAttributePath();

err = cache.Get(path, reader);

if (ConcreteClusterPath(path) == firstCluster)
{
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);
}
else
{
// Should still have a value or status
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
}
}

// Now clearing for endpoints. First check that things that should be there are.
// TODO: Since all our attributes have the same cluster, this is not
// actually testing anything useful right now.
for (auto & listItem : list)
{
ConcreteAttributePath path = listItem.GetAttributePath();
if (ConcreteClusterPath(path) == firstCluster)
{
// We removed this one already.
continue;
}

err = cache.Get(path, reader);

// Should have gotten a value or status for now.
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
}

auto firstEndpoint = firstAttr.mEndpointId;
cache.ClearAttributes(firstEndpoint);

for (auto & listItem : list)
{
ConcreteAttributePath path = listItem.GetAttributePath();

err = cache.Get(path, reader);

if (path.mEndpointId == firstEndpoint)
{
EXPECT_EQ(err, CHIP_ERROR_KEY_NOT_FOUND);
}
else
{
// Should still have a value or status
EXPECT_NE(err, CHIP_ERROR_KEY_NOT_FOUND);
}
}
}

/*
Expand Down

0 comments on commit 3319279

Please sign in to comment.