@@ -675,7 +675,7 @@ - (void)_setDSTOffsets:(NSArray<MTRTimeSynchronizationClusterDSTOffsetStruct *>
675
675
completion: setDSTOffsetResponseHandler];
676
676
}
677
677
678
- - (NSMutableArray <NSNumber *> *)arrayOfNumbersFromAttributeValue : (NSDictionary * )dataDictionary
678
+ - (NSMutableArray <NSNumber *> *)arrayOfNumbersFromAttributeValue : (MTRDeviceDataValueDictionary )dataDictionary
679
679
{
680
680
if (![MTRArrayValueType isEqual: dataDictionary[MTRTypeKey]]) {
681
681
return nil ;
@@ -3040,35 +3040,43 @@ - (void)_removeClusters:(NSSet<MTRClusterPath *> *)clusterPathsToRemove
3040
3040
3041
3041
for (MTRClusterPath * path in clusterPathsToRemove) {
3042
3042
[_persistedClusterData removeObjectForKey: path];
3043
- [_persistedClusters removeObject: path];
3044
3043
[_clusterDataToPersist removeObjectForKey: path];
3045
3044
[self .deviceController.controllerDataStore clearStoredClusterDataForNodeID: self .nodeID endpointID: path.endpoint clusterID: path.cluster];
3046
3045
}
3047
3046
}
3048
3047
3049
- - (void )_removeAttributes : (NSSet <NSNumber *> *)attributes fromCluster : (MTRClusterPath *) clusterPath
3048
+ - (void )_removeClustersFromCache : (NSSet <MTRClusterPath *> *)clusterPathsToRemove
3050
3049
{
3051
- if (toBeRemovedAttributes == nil || clusterPathToRemoveAttributesFrom == nil ) {
3052
- return ;
3050
+ os_unfair_lock_assert_owner (&self->_lock );
3051
+
3052
+ [_persistedClusters minusSet: clusterPathsToRemove];
3053
+
3054
+ for (MTRClusterPath * path in clusterPathsToRemove) {
3055
+ [_persistedClusterData removeObjectForKey: path];
3056
+ [_clusterDataToPersist removeObjectForKey: path];
3053
3057
}
3058
+ }
3059
+
3060
+ - (void )_removeAttributes : (NSSet <NSNumber *> *)attributes fromCluster : (MTRClusterPath *)clusterPath
3061
+ {
3054
3062
os_unfair_lock_assert_owner (&self->_lock );
3055
3063
3056
- for (NSNumber * attribute in toBeRemovedAttributes ) {
3057
- [self _removeCachedAttribute: attribute fromCluster: clusterPathToRemoveAttributesFrom ];
3064
+ for (NSNumber * attribute in attributes ) {
3065
+ [self _removeCachedAttribute: attribute fromCluster: clusterPath ];
3058
3066
}
3059
3067
// Just clear out the NSCache entry for this cluster, so we'll load it from storage as needed.
3060
- [_persistedClusterData removeObjectForKey: clusterPathToRemoveAttributesFrom ];
3061
- [self .deviceController.controllerDataStore clearStoredClusterDataForNodeID: self .nodeID endpointID: clusterPathToRemoveAttributesFrom.endpoint clusterID: clusterPathToRemoveAttributesFrom.cluster ];
3068
+ [_persistedClusterData removeObjectForKey: clusterPath ];
3069
+ [self .deviceController.controllerDataStore removeAttributes: attributes fromCluster: clusterPath forNodeID: self .nodeID ];
3062
3070
}
3063
3071
3064
- - (void )_pruneEndpointsIn : (NSDictionary * )previousPartsListValue
3065
- missingFrom : (NSDictionary * )newPartsListValue
3072
+ - (void )_pruneEndpointsIn : (MTRDeviceDataValueDictionary )previousPartsListValue
3073
+ missingFrom : (MTRDeviceDataValueDictionary )newPartsListValue
3066
3074
{
3067
3075
// If the parts list changed and one or more endpoints were removed, remove all the
3068
3076
// clusters for all those endpoints from our data structures.
3069
3077
// Also remove those endpoints from the data store.
3070
- NSMutableSet * toBeRemovedEndpoints = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: [ self _dataValueWithoutDataVersion: previousPartsListValue] ]];
3071
- NSSet * endpointsOnDevice = [NSSet setWithArray: [self arrayOfNumbersFromAttributeValue: newPartsListValue]];
3078
+ NSMutableSet < NSNumber *> * toBeRemovedEndpoints = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: previousPartsListValue]];
3079
+ NSSet < NSNumber *> * endpointsOnDevice = [NSSet setWithArray: [self arrayOfNumbersFromAttributeValue: newPartsListValue]];
3072
3080
[toBeRemovedEndpoints minusSet: endpointsOnDevice];
3073
3081
3074
3082
for (NSNumber * endpoint in toBeRemovedEndpoints) {
@@ -3078,75 +3086,71 @@ - (void)_pruneEndpointsIn:(NSDictionary *)previousPartsListValue
3078
3086
[clusterPathsToRemove addObject: path];
3079
3087
}
3080
3088
}
3081
- [self _removeClusters: [ clusterPathsToRemove copy ] ];
3082
- [self .deviceController.controllerDataStore removeEndpointFromEndpointIndex: endpoint forNodeID: self .nodeID];
3089
+ [self _removeClustersFromCache: clusterPathsToRemove];
3090
+ [self .deviceController.controllerDataStore clearStoredClusterDataForNodeID: self .nodeID endpointID: endpoint ];
3083
3091
}
3084
3092
}
3085
3093
3086
- - (void )_pruneOrphanedClusters : (MTRAttributePath *) attributePath
3087
- previousServerListValue : ( NSDictionary *) previousServerListValue
3088
- newServerListValue : ( NSDictionary *)newServerListValue
3094
+ - (void )_pruneClustersIn : (MTRDeviceDataValueDictionary) previousServerListValue
3095
+ missingFrom : (MTRDeviceDataValueDictionary) newServerListValue
3096
+ forEndpoint : ( NSNumber *)endpointID
3089
3097
{
3090
3098
// If the server list changed and clusters were removed, remove those clusters from our data structures.
3091
3099
// Also remove it from the data store.
3092
- NSMutableSet <NSNumber *> * toBeRemovedClusters = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: [ self _dataValueWithoutDataVersion: previousServerListValue] ]];
3100
+ NSMutableSet <NSNumber *> * toBeRemovedClusters = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: previousServerListValue]];
3093
3101
NSSet <NSNumber *> * clustersStillOnEndpoint = [NSSet setWithArray: [self arrayOfNumbersFromAttributeValue: newServerListValue]];
3094
3102
[toBeRemovedClusters minusSet: clustersStillOnEndpoint];
3095
3103
3096
3104
NSMutableSet <MTRClusterPath *> * clusterPathsToRemove = [[NSMutableSet alloc ] init ];
3097
3105
for (NSNumber * cluster in toBeRemovedClusters) {
3098
3106
for (MTRClusterPath * path in _persistedClusters) {
3099
- if ([path.endpoint isEqualToNumber: attributePath.endpoint ] && [path.cluster isEqualToNumber: cluster]) {
3107
+ if ([path.endpoint isEqualToNumber: endpointID ] && [path.cluster isEqualToNumber: cluster]) {
3100
3108
[clusterPathsToRemove addObject: path];
3101
3109
}
3102
3110
}
3103
3111
}
3104
- [self _removeClusters: [ clusterPathsToRemove copy ] ];
3112
+ [self _removeClusters: clusterPathsToRemove];
3105
3113
}
3106
3114
3107
- - (void )_pruneOrphanedAttributes : (MTRAttributePath *)attributePath
3108
- newAttributeListValue : (NSDictionary *)newAttributeListValue
3115
+ - (void )_pruneAttributesIn : (MTRDeviceDataValueDictionary)previousAttributeListValue
3116
+ missingFrom : (MTRDeviceDataValueDictionary)newAttributeListValue
3117
+ forCluster : (MTRClusterPath *)clusterPath
3109
3118
{
3110
3119
// If the attribute list changed and attributes were removed, remove the attributes from our
3111
3120
// data structures.
3112
- NSMutableSet <NSNumber *> * toBeRemovedAttributes = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: [ self _cachedAttributeValueForPath: attributePath] ]];
3121
+ NSMutableSet <NSNumber *> * toBeRemovedAttributes = [NSMutableSet setWithArray: [self arrayOfNumbersFromAttributeValue: previousAttributeListValue ]];
3113
3122
NSSet <NSNumber *> * attributesStillInCluster = [NSSet setWithArray: [self arrayOfNumbersFromAttributeValue: newAttributeListValue]];
3114
3123
3115
3124
[toBeRemovedAttributes minusSet: attributesStillInCluster];
3116
- MTRClusterPath * clusterPathToRemoveAttributesFrom;
3117
- for (MTRClusterPath * path in _persistedClusters) {
3118
- if ([path.endpoint isEqualToNumber: attributePath.endpoint] && [path.cluster isEqualToNumber: attributePath.cluster]) {
3119
- clusterPathToRemoveAttributesFrom = path;
3120
- break ;
3121
- }
3122
- }
3123
- [self _removeAttributes: [toBeRemovedAttributes copy ] fromCluster: clusterPathToRemoveAttributesFrom];
3124
- [self .deviceController.controllerDataStore removeAttributes: [toBeRemovedAttributes copy ] fromCluster: clusterPathToRemoveAttributesFrom forNodeID: self .nodeID];
3125
+ [self _removeAttributes: toBeRemovedAttributes fromCluster: clusterPath];
3125
3126
}
3126
3127
3127
- - (void )_pruneOrphanedEndpointsAndClusters : (MTRAttributePath *)attributePath
3128
- previousValue : (NSDictionary *)previousValue
3129
- attributeDataValue : (NSDictionary *)attributeDataValue
3128
+ - (void )_pruneStoredDataForPath : (MTRAttributePath *)attributePath
3129
+ missingFrom : (MTRDeviceDataValueDictionary)newAttributeDataValue
3130
3130
{
3131
3131
os_unfair_lock_assert_owner (&self->_lock );
3132
3132
3133
- NSNumber * rootEndpoint = @0 ;
3134
-
3135
- if (_persistedClusters == nil || _persistedClusterData == nil || !previousValue.count ) {
3133
+ if (![self _dataStoreExists ] && !_clusterDataToPersist.count ) {
3134
+ MTR_LOG_DEBUG (" %@ No data store to prune from" , self);
3136
3135
return ;
3137
3136
}
3137
+
3138
3138
// Check if parts list changed or server list changed for the descriptor cluster or the attribute list changed for a cluster.
3139
3139
// If yes, we might need to prune any deleted endpoints, clusters or attributes from the storage and persisted cluster data.
3140
3140
if (attributePath.cluster .unsignedLongValue == MTRClusterIDTypeDescriptorID) {
3141
- if (attributePath.attribute .unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributePartsListID && [attributePath.endpoint isEqualToNumber: rootEndpoint]) {
3142
- [self _pruneOrphanedEndpoints: previousValue newPartsListValue: attributeDataValue];
3143
- } else if (attributePath.attribute .unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributeServerListID) {
3144
- [self _pruneOrphanedClusters: attributePath previousServerListValue: previousValue newServerListValue: attributeDataValue];
3141
+ if (attributePath.attribute .unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributePartsListID && [attributePath.endpoint isEqualToNumber: @(kRootEndpointId )]) {
3142
+ [self _pruneEndpointsIn: [self _cachedAttributeValueForPath: attributePath] missingFrom: newAttributeDataValue];
3143
+ return ;
3144
+ }
3145
+
3146
+ if (attributePath.attribute .unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributeServerListID) {
3147
+ [self _pruneClustersIn: [self _cachedAttributeValueForPath: attributePath] missingFrom: newAttributeDataValue forEndpoint: attributePath.endpoint];
3148
+ return ;
3145
3149
}
3146
3150
}
3147
3151
3148
3152
if (attributePath.attribute .unsignedLongValue == MTRAttributeIDTypeGlobalAttributeAttributeListID) {
3149
- [self _pruneOrphanedAttributes: attributePath newAttributeListValue: attributeDataValue ];
3153
+ [self _pruneAttributesIn: [ self _cachedAttributeValueForPath: attributePath] missingFrom: newAttributeDataValue forCluster: [MTRClusterPath clusterPathWithEndpointID: attributePath.endpoint clusterID: attributePath.cluster] ];
3150
3154
}
3151
3155
}
3152
3156
@@ -3203,7 +3207,7 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
3203
3207
[self _noteDataVersion: dataVersion forClusterPath: clusterPath];
3204
3208
}
3205
3209
3206
- [self _pruneOrphanedEndpointsAndClusters : attributePath previousValue: previousValue attributeDataValue : attributeDataValue];
3210
+ [self _pruneStoredDataForPath : attributePath missingFrom : attributeDataValue];
3207
3211
3208
3212
if (!_deviceConfigurationChanged) {
3209
3213
_deviceConfigurationChanged = [self _attributeAffectsDeviceConfiguration: attributePath];
0 commit comments