Skip to content

Commit

Permalink
Fix behavior of MTRDevice readAttributePaths if it happens mid-primin…
Browse files Browse the repository at this point in the history
…g. (#35656)

* Fix behavior of MTRDevice readAttributePaths if it happens mid-priming.

We might not know the values of AttributeList/ServerList/PartsList yet at that
point.  Just go ahead and figure out which attribute values we have by walking
our own data structures, not the metadata list attribute values.

* Apply suggestion from code review.

Co-authored-by: Nivi Sarkar <55898241+nivi-apple@users.noreply.github.com>

---------

Co-authored-by: Nivi Sarkar <55898241+nivi-apple@users.noreply.github.com>
  • Loading branch information
bzbarsky-apple and nivi-apple authored Sep 20, 2024
1 parent dff8864 commit 58b43e0
Showing 1 changed file with 25 additions and 47 deletions.
72 changes: 25 additions & 47 deletions src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2983,11 +2983,31 @@ - (void)writeAttributeWithEndpointID:(NSNumber *)endpointID
// Determine the set of what the spec calls "existent paths" that correspond
// to the request paths. Building the whole set in-memory is OK, because
// we're going to need all those paths for our return value anyway.
//
// Note that we don't use the structural attributes (PartsList, ServerList,
// AttributeList) to determine this set, because we might be in the middle
// of priming right now and have not gotten those yet. Just use the set of
// attribute paths we actually have.
NSMutableSet<MTRAttributePath *> * existentPaths = [[NSMutableSet alloc] init];
{
std::lock_guard lock(_lock);
for (MTRAttributeRequestPath * path in attributePaths) {
[self _addExistentPathsFor:path to:existentPaths];
for (MTRAttributeRequestPath * requestPath in attributePaths) {
for (MTRClusterPath * clusterPath in [self _knownClusters]) {
if (requestPath.endpoint != nil && ![requestPath.endpoint isEqual:clusterPath.endpoint]) {
continue;
}
if (requestPath.cluster != nil && ![requestPath.cluster isEqual:clusterPath.cluster]) {
continue;
}
MTRDeviceClusterData * clusterData = [self _clusterDataForPath:clusterPath];
if (requestPath.attribute == nil) {
for (NSNumber * attributeID in clusterData.attributes) {
[existentPaths addObject:[MTRAttributePath attributePathWithEndpointID:clusterPath.endpoint clusterID:clusterPath.cluster attributeID:attributeID]];
}
} else if ([clusterData.attributes objectForKey:requestPath.attribute] != nil) {
[existentPaths addObject:[MTRAttributePath attributePathWithEndpointID:clusterPath.endpoint clusterID:clusterPath.cluster attributeID:requestPath.attribute]];
}
}
}
}

Expand All @@ -3006,51 +3026,6 @@ - (void)writeAttributeWithEndpointID:(NSNumber *)endpointID
return result;
}

- (void)_addExistentPathsFor:(MTRAttributeRequestPath *)path to:(NSMutableSet<MTRAttributePath *> *)set
{
os_unfair_lock_assert_owner(&_lock);

if (path.endpoint != nil) {
[self _addExistentPathsForEndpoint:path.endpoint path:path to:set];
return;
}

NSArray<NSNumber *> * endpointList = [self _endpointList];
for (NSNumber * endpoint in endpointList) {
[self _addExistentPathsForEndpoint:endpoint path:path to:set];
}
}

- (void)_addExistentPathsForEndpoint:(NSNumber *)endpoint path:(MTRAttributeRequestPath *)path to:(NSMutableSet<MTRAttributePath *> *)set
{
os_unfair_lock_assert_owner(&_lock);

if (path.cluster != nil) {
[self _addExistentPathsForEndpoint:endpoint cluster:path.cluster attribute:path.attribute to:set];
return;
}

auto * clusterList = [self _serverListForEndpointID:endpoint];
for (NSNumber * cluster in clusterList) {
[self _addExistentPathsForEndpoint:endpoint cluster:cluster attribute:path.attribute to:set];
}
}

- (void)_addExistentPathsForEndpoint:(NSNumber *)endpoint cluster:(NSNumber *)cluster attribute:(NSNumber * _Nullable)attribute to:(NSMutableSet<MTRAttributePath *> *)set
{
os_unfair_lock_assert_owner(&_lock);

if (attribute != nil) {
[set addObject:[MTRAttributePath attributePathWithEndpointID:endpoint clusterID:cluster attributeID:attribute]];
return;
}

auto * attributeList = [self _attributeListForEndpointID:endpoint clusterID:cluster];
for (NSNumber * existentAttribute in attributeList) {
[set addObject:[MTRAttributePath attributePathWithEndpointID:endpoint clusterID:cluster attributeID:existentAttribute]];
}
}

- (void)_invokeCommandWithEndpointID:(NSNumber *)endpointID
clusterID:(NSNumber *)clusterID
commandID:(NSNumber *)commandID
Expand Down Expand Up @@ -3652,6 +3627,9 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
return attributesToReport;
}

// TODO: Figure out whether we can get rid of this in favor of readAttributePaths. This differs from
// readAttributePaths in one respect: that function will do read-through for
// C-quality attributes, but this one does not.
- (NSArray<NSDictionary<NSString *, id> *> *)getAllAttributesReport
{
std::lock_guard lock(_lock);
Expand Down

0 comments on commit 58b43e0

Please sign in to comment.