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

[Darwin] MTRDevice attribute storage should write indexes only once each time #32791

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
111 changes: 74 additions & 37 deletions src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm
Original file line number Diff line number Diff line change
Expand Up @@ -983,64 +983,101 @@ - (void)storeClusterData:(NSDictionary<MTRClusterPath *, MTRDeviceClusterData *>
dispatch_async(_storageDelegateQueue, ^{
NSUInteger storeFailures = 0;

// A map of endpoint => list of clusters modified for that endpoint so cluster indexes can be updated later
NSMutableDictionary<NSNumber *, NSMutableSet<NSNumber *> *> * clustersModified = [NSMutableDictionary dictionary];

// Write cluster specific data first
for (MTRClusterPath * path in clusterData) {
MTRDeviceClusterData * data = clusterData[path];

#if ATTRIBUTE_CACHE_VERBOSE_LOGGING
MTR_LOG_INFO("Attempt to store clusterData @ node 0x%016llX endpoint %u cluster 0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue);
#endif

BOOL storeFailed = NO;
// Ensure node index exists
NSArray<NSNumber *> * nodeIndex = [self _fetchNodeIndex];
if (!nodeIndex) {
nodeIndex = [NSArray arrayWithObject:nodeID];
storeFailed = ![self _storeNodeIndex:nodeIndex];
} else if (![nodeIndex containsObject:nodeID]) {
storeFailed = ![self _storeNodeIndex:[nodeIndex arrayByAddingObject:nodeID]];
}
// Store cluster data
BOOL storeFailed = ![self _storeClusterData:data forNodeID:nodeID endpointID:path.endpoint clusterID:path.cluster];
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for nodeIndex");
continue;
MTR_LOG_INFO("Store failed for clusterDAta @ node 0x%016llX endpoint %u cluster 0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue);
}

// Ensure endpoint index exists
NSArray<NSNumber *> * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID];
if (!endpointIndex) {
endpointIndex = [NSArray arrayWithObject:path.endpoint];
storeFailed = ![self _storeEndpointIndex:endpointIndex forNodeID:nodeID];
} else if (![endpointIndex containsObject:path.endpoint]) {
storeFailed = ![self _storeEndpointIndex:[endpointIndex arrayByAddingObject:path.endpoint] forNodeID:nodeID];
// Note the cluster as modified for the endpoint
NSMutableSet<NSNumber *> * clustersInEndpoint = clustersModified[path.endpoint];
if (!clustersInEndpoint) {
clustersInEndpoint = [NSMutableSet set];
clustersModified[path.endpoint] = clustersInEndpoint;
}
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for endpointIndex @ node 0x%016llX", nodeID.unsignedLongLongValue);
continue;
[clustersInEndpoint addObject:path.cluster];
}

// Prepare to tally all endpoints touched
NSArray<NSNumber *> * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID];
BOOL endpointIndexModified = NO;
NSMutableArray<NSNumber *> * endpointIndexToStore;
if (endpointIndex) {
endpointIndexToStore = [endpointIndex mutableCopy];
} else {
endpointIndexToStore = [NSMutableArray array];
endpointIndexModified = YES;
}

for (NSNumber * endpointID in clustersModified) {
if (![endpointIndexToStore containsObject:endpointID]) {
[endpointIndexToStore addObject:endpointID];
endpointIndexModified = YES;
}

// Ensure cluster index exists
NSArray<NSNumber *> * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:path.endpoint];
if (!clusterIndex) {
clusterIndex = [NSArray arrayWithObject:path.cluster];
storeFailed = ![self _storeClusterIndex:clusterIndex forNodeID:nodeID endpointID:path.endpoint];
} else if (![clusterIndex containsObject:path.cluster]) {
storeFailed = ![self _storeClusterIndex:[clusterIndex arrayByAddingObject:path.cluster] forNodeID:nodeID endpointID:path.endpoint];
// Get cluster index from storage and prepare to tally clusters touched
NSSet * newClusters = clustersModified[endpointID];
NSArray<NSNumber *> * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:endpointID];
BOOL clusterIndexModified = NO;
NSMutableArray<NSNumber *> * clusterIndexToStore;
if (clusterIndex) {
clusterIndexToStore = [clusterIndex mutableCopy];
} else {
clusterIndexToStore = [NSMutableArray array];
clusterIndexModified = YES;
}
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for clusterIndex @ node 0x%016llX endpoint %u", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue);
continue;

for (NSNumber * clusterID in newClusters) {
if (![clusterIndexToStore containsObject:clusterID]) {
[clusterIndexToStore addObject:clusterID];
clusterIndexModified = YES;
}
}

// Store cluster data
storeFailed = ![self _storeClusterData:data forNodeID:nodeID endpointID:path.endpoint clusterID:path.cluster];
if (clusterIndexModified) {
BOOL storeFailed = ![self _storeClusterIndex:clusterIndexToStore forNodeID:nodeID endpointID:endpointID];
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for clusterIndex @ node 0x%016llX endpoint %u", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue);
continue;
}
}
}

// Update endpoint index as needed
if (endpointIndexModified) {
BOOL storeFailed = ![self _storeEndpointIndex:endpointIndexToStore forNodeID:nodeID];
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for clusterDAta @ node 0x%016llX endpoint %u cluster 0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue);
MTR_LOG_INFO("Store failed for endpointIndex @ node 0x%016llX", nodeID.unsignedLongLongValue);
}
}

// Ensure node index exists
NSArray<NSNumber *> * nodeIndex = [self _fetchNodeIndex];
BOOL storeFailed = NO;
if (!nodeIndex) {
nodeIndex = [NSArray arrayWithObject:nodeID];
storeFailed = ![self _storeNodeIndex:nodeIndex];
} else if (![nodeIndex containsObject:nodeID]) {
storeFailed = ![self _storeNodeIndex:[nodeIndex arrayByAddingObject:nodeID]];
}
if (storeFailed) {
storeFailures++;
MTR_LOG_INFO("Store failed for nodeIndex");
}

// In the rare event that store fails, allow all attribute store attempts to go through and prune empty branches at the end altogether.
if (storeFailures) {
[self _pruneEmptyStoredAttributesBranches];
Expand Down
Loading