Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading