@@ -220,7 +220,7 @@ - (void)storeValue:(MTRDeviceDataValueDictionary _Nullable)value forAttribute:(N
220
220
_attributes[attribute] = value;
221
221
}
222
222
223
- - (void)_removeValueForAttribute :(NSNumber *)attribute
223
+ - (void)removeValueForAttribute :(NSNumber *)attribute
224
224
{
225
225
[_attributes removeObjectForKey:attribute];
226
226
}
@@ -1614,15 +1614,15 @@ - (void)_setCachedAttributeValue:(MTRDeviceDataValueDictionary _Nullable)value f
1614
1614
_clusterDataToPersist[clusterPath] = clusterData;
1615
1615
}
1616
1616
1617
- - (void)_removeCachedAttributeValue:(MTRClusterPath *)clusterPath forPath:(MTRAttributePath *)attributePath
1617
+ - (void)_removeCachedAttribute:(NSNumber *)attributeID fromCluster:(MTRClusterPath *)clusterPath
1618
1618
{
1619
1619
os_unfair_lock_assert_owner(&self->_lock);
1620
1620
1621
1621
if (_clusterDataToPersist == nil) {
1622
1622
return;
1623
1623
}
1624
1624
auto * clusterData = [_clusterDataToPersist objectForKey:clusterPath];
1625
- [clusterData _removeValueForAttribute:attributePath.attribute ];
1625
+ [clusterData removeValueForAttribute:attributeID ];
1626
1626
[_clusterDataToPersist setObject:clusterData forKey:clusterPath];
1627
1627
}
1628
1628
@@ -2745,42 +2745,55 @@ - (BOOL)_attributeAffectsDeviceConfiguration:(MTRAttributePath *)attributePath
2745
2745
return NO;
2746
2746
}
2747
2747
2748
- - (BOOL)_needsPruningOfEndpointsAndClusters:(MTRAttributePath *)attributePath
2748
+ - (void)_removeClusters:(NSSet *)clusterPathsToRemove
2749
2749
{
2750
- // Check for attributes in the descriptor cluster that could cause removal of endpoints and clusters.
2751
- if (attributePath.cluster.unsignedLongValue == MTRClusterIDTypeDescriptorID) {
2752
- switch (attributePath.attribute.unsignedLongValue) {
2753
- case MTRAttributeIDTypeClusterDescriptorAttributePartsListID:
2754
- case MTRAttributeIDTypeClusterDescriptorAttributeServerListID:
2755
- return YES;
2756
- }
2750
+ os_unfair_lock_assert_owner(&self->_lock);
2751
+
2752
+ [_persistedClusters minusSet:clusterPathsToRemove];
2753
+
2754
+ for (MTRClusterPath * path in clusterPathsToRemove)
2755
+ {
2756
+ [_persistedClusterData removeObjectForKey:path];
2757
+ [_persistedClusters removeObject:path];
2758
+ [_clusterDataToPersist removeObjectForKey:path];
2759
+ [self.deviceController.controllerDataStore clearStoredClusterDataForNodeID:self.nodeID endpointID:path.endpoint clusterID:path.cluster];
2757
2760
}
2761
+ }
2758
2762
2759
- // Check for global attribute - attribute list that could cause removal of attributes.
2760
- switch (attributePath.attribute.unsignedLongValue) {
2761
- case MTRAttributeIDTypeGlobalAttributeAttributeListID:
2762
- return YES;
2763
+ - (void)_removeAttributes:(NSSet *)toBeRemovedAttributes fromCluster:(MTRClusterPath *)clusterPathToRemoveAttributesFrom
2764
+ {
2765
+ if (toBeRemovedAttributes == nil || clusterPathToRemoveAttributesFrom == nil)
2766
+ {
2767
+ return;
2763
2768
}
2764
- return NO;
2769
+ os_unfair_lock_assert_owner(&self->_lock);
2770
+
2771
+ for (NSNumber * attribute in toBeRemovedAttributes)
2772
+ {
2773
+ [self _removeCachedAttribute:attribute fromCluster:clusterPathToRemoveAttributesFrom];
2774
+ }
2775
+ [_persistedClusterData removeObjectForKey:clusterPathToRemoveAttributesFrom];
2776
+ [self.deviceController.controllerDataStore clearStoredClusterDataForNodeID:self.nodeID endpointID:clusterPathToRemoveAttributesFrom.endpoint clusterID:clusterPathToRemoveAttributesFrom.cluster];
2765
2777
}
2766
2778
2767
2779
- (void)_pruneOrphanedEndpointsAndClusters:(MTRAttributePath *)attributePath
2768
2780
previousValue:(NSDictionary *)previousValue
2769
2781
attributeDataValue:(NSDictionary *)attributeDataValue
2770
2782
{
2771
2783
os_unfair_lock_assert_owner(&self->_lock);
2784
+
2785
+ NSNumber * rootEndpoint = @0;
2772
2786
2773
2787
if (_persistedClusters == nil || _persistedClusterData == nil || !previousValue.count) {
2774
2788
return;
2775
2789
}
2776
2790
// Check if parts list changed or server list changed for the descriptor cluster or the attribute list changed for a cluster.
2777
2791
// If yes, we might need to prune any deleted endpoints, clusters or attributes from the storage and persisted cluster data.
2778
2792
if (attributePath.cluster.unsignedLongValue == MTRClusterIDTypeDescriptorID) {
2779
- switch (attributePath.attribute.unsignedLongValue) {
2780
-
2781
- // If the parts list changed and one or more endpoints were removed, remove all the clusters in _persistedClusters and _persistedClusterData for all those endpoints.
2782
- // Also remove it from the data store.
2783
- case MTRAttributeIDTypeClusterDescriptorAttributePartsListID: {
2793
+ if (attributePath.attribute.unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributePartsListID && [attributePath.endpoint isEqualToNumber:rootEndpoint]) {
2794
+
2795
+ // If the parts list changed and one or more endpoints were removed, remove all the clusters in _persistedClusters, _persistedClusterData and _clusterDataToPersist for all those endpoints.
2796
+ // Also remove it from the data store.
2784
2797
NSMutableSet * toBeRemovedEndpoints = [NSMutableSet setWithArray:[self arrayOfNumbersFromAttributeValue:previousValue]];
2785
2798
NSSet * endpointsOnDevice = [NSSet setWithArray:[self arrayOfNumbersFromAttributeValue:attributeDataValue]];
2786
2799
[toBeRemovedEndpoints minusSet:endpointsOnDevice];
@@ -2790,72 +2803,50 @@ - (void)_pruneOrphanedEndpointsAndClusters:(MTRAttributePath *)attributePath
2790
2803
for (MTRClusterPath * path in _persistedClusters) {
2791
2804
if ([path.endpoint isEqualToNumber:endpoint]) {
2792
2805
[clusterPathsToRemove addObject:path];
2793
- [_persistedClusterData removeObjectForKey:path];
2794
- [self.deviceController.controllerDataStore clearStoredClusterDataForNodeIDWithEndpointID:self.nodeID endpointID:endpoint];
2795
2806
}
2796
2807
}
2797
- [_persistedClusters minusSet:clusterPathsToRemove];
2808
+ [self _removeClusters:[clusterPathsToRemove copy]];
2809
+ [self.deviceController.controllerDataStore removeEndpointFromEndpointIndex:endpoint forNodeID:self.nodeID];
2798
2810
}
2799
- break;
2800
2811
}
2801
-
2802
- // If the server list changed and clusters were removed, remove the clusters from the _persistedClusters and _persistedClusterData for that endpoint
2803
- // Also remove it from the data store.
2804
- case MTRAttributeIDTypeClusterDescriptorAttributeServerListID: {
2805
- NSMutableSet<NSNumber *> * toBeRemovedClusters = [NSMutableSet setWithArray:[self arrayOfNumbersFromAttributeValue:previousValue]];
2812
+ else if (attributePath.attribute.unsignedLongValue == MTRAttributeIDTypeClusterDescriptorAttributeServerListID)
2813
+ {
2814
+
2815
+ // If the server list changed and clusters were removed, remove the clusters from the _persistedClusters, _persistedClusterData and _clusterDataToPersist for all those clusters.
2816
+ // Also remove it from the data store.
2817
+ NSMutableSet<NSNumber *> * toBeRemovedClusters = [NSMutableSet setWithArray:[self arrayOfNumbersFromAttributeValue:[self _dataValueWithoutDataVersion:previousValue]]];
2806
2818
NSSet<NSNumber *> * clustersStillOnEndpoint = [NSSet setWithArray:[self arrayOfNumbersFromAttributeValue:attributeDataValue]];
2807
- [toBeRemovedClusters minusSet:clustersOnDevice ];
2819
+ [toBeRemovedClusters minusSet:clustersStillOnEndpoint ];
2808
2820
2809
2821
NSMutableSet<MTRClusterPath *> * clusterPathsToRemove = [[NSMutableSet alloc] init];
2810
2822
for (NSNumber * cluster in toBeRemovedClusters) {
2811
2823
for (MTRClusterPath * path in _persistedClusters) {
2812
2824
if ([path.endpoint isEqualToNumber:attributePath.endpoint] && [path.cluster isEqualToNumber:cluster]) {
2813
2825
[clusterPathsToRemove addObject:path];
2814
- [_persistedClusterData removeObjectForKey:path];
2815
-
2816
- [self.deviceController.controllerDataStore clearStoredClusterDataForNodeIDWithClusterID:self.nodeID endpointID:path.endpoint clusterID:path.cluster];
2817
2826
}
2818
2827
}
2819
2828
}
2820
- [_persistedClusters minusSet:clusterPathsToRemove];
2821
- break;
2822
- }
2829
+ [self _removeClusters:[clusterPathsToRemove copy]];
2823
2830
}
2824
2831
}
2825
2832
2826
- switch (attributePath.attribute.unsignedLongValue) {
2827
- // If the attribute list changed and attributes were removed, remove the attributes from the _persistedClusterData for that cluster and endpoint.
2828
- // Also remove it from the data store cluster data .
2829
- case MTRAttributeIDTypeGlobalAttributeAttributeListID: {
2833
+ if (attributePath.attribute.unsignedLongValue == MTRAttributeIDTypeGlobalAttributeAttributeListID ) {
2834
+
2835
+ // If the attribute list changed and attributes were removed, remove the attributes from the _clusterDataToPersist for that cluster and endpoint .
2836
+ // Clear out the _peristedClusterData and data store cluster data. Update the data storage with updated cluster data.
2830
2837
NSMutableSet<NSNumber *> * toBeRemovedAttributes = [NSMutableSet setWithArray:[self arrayOfNumbersFromAttributeValue:[self _cachedAttributeValueForPath:attributePath]]];
2831
- NSSet<NSNumber *> * attributesStillIncluster = [NSSet setWithArray:[self arrayOfNumbersFromAttributeValue:attributeDataValue]];
2832
-
2833
- [toBeRemovedAttributes minusSet:attributesOnDevice];
2834
- for (NSNumber * attribute in toBeRemovedAttributes) {
2835
- for (MTRClusterPath * path in _persistedClusters) {
2836
- if ([path.endpoint isEqualToNumber:attributePath.endpoint] && [path.cluster isEqualToNumber:attributePath.cluster]) {
2837
- MTRDeviceClusterData * clusterData = [self _clusterDataForPath:path];
2838
- if (clusterData == nil) {
2839
- return;
2840
- }
2841
- [clusterData _removeValueForAttribute:attribute];
2842
- [self->_persistedClusterData setObject:clusterData forKey:path];
2843
-
2844
- NSDictionary<MTRClusterPath *, MTRDeviceClusterData *> * dataStoreClusterData = [self.deviceController.controllerDataStore getStoredClusterDataForNodeID:self.nodeID];
2845
- NSMutableDictionary<MTRClusterPath *, MTRDeviceClusterData *> * dataStoreClusterDataCopy = [dataStoreClusterData mutableCopy];
2846
- for (MTRClusterPath * dataStorePath in dataStoreClusterData) {
2847
- if ([dataStorePath.endpoint isEqualToNumber:path.endpoint] && [dataStorePath.cluster isEqualToNumber:path.cluster]) {
2848
- [dataStoreClusterDataCopy removeObjectForKey:path];
2849
- [dataStoreClusterDataCopy setObject:clusterData forKey:path];
2850
- [self.deviceController.controllerDataStore storeClusterData:dataStoreClusterDataCopy forNodeID:self.nodeID];
2851
- }
2852
- }
2853
- [self _removeCachedAttributeValue:path forPath:attributePath];
2854
- }
2838
+ NSSet<NSNumber *> * attributesStillInCluster = [NSSet setWithArray:[self arrayOfNumbersFromAttributeValue:attributeDataValue]];
2839
+
2840
+ [toBeRemovedAttributes minusSet:attributesStillInCluster];
2841
+ MTRClusterPath * clusterPathToRemoveAttributesFrom;
2842
+ for (MTRClusterPath * path in _persistedClusters) {
2843
+ if ([path.endpoint isEqualToNumber:attributePath.endpoint] && [path.cluster isEqualToNumber:attributePath.cluster]) {
2844
+ clusterPathToRemoveAttributesFrom = path;
2845
+ break;
2855
2846
}
2856
2847
}
2857
- break ;
2858
- }
2848
+ [self _removeAttributes:[toBeRemovedAttributes copy] fromCluster:clusterPathToRemoveAttributesFrom] ;
2849
+ [self.deviceController.controllerDataStore removeAttributes:[toBeRemovedAttributes copy] fromCluster:clusterPathToRemoveAttributesFrom forNodeID:self.nodeID];
2859
2850
}
2860
2851
}
2861
2852
@@ -2912,10 +2903,7 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray<NSDictionary<NSSt
2912
2903
[self _noteDataVersion:dataVersion forClusterPath:clusterPath];
2913
2904
}
2914
2905
2915
- if ([self _needsPruningOfEndpointsAndClusters:attributePath]) {
2916
- previousValue = [self _dataValueWithoutDataVersion:previousValue];
2917
- [self _pruneOrphanedEndpointsAndClusters:attributePath previousValue:previousValue attributeDataValue:attributeDataValue];
2918
- }
2906
+ [self _pruneOrphanedEndpointsAndClusters:attributePath previousValue:previousValue attributeDataValue:attributeDataValue];
2919
2907
2920
2908
if (!_deviceConfigurationChanged) {
2921
2909
_deviceConfigurationChanged = [self _attributeAffectsDeviceConfiguration:attributePath];
@@ -3078,35 +3066,15 @@ - (void)_storePersistedDeviceData
3078
3066
[datastore storeDeviceData:[data copy] forNodeID:self.nodeID];
3079
3067
}
3080
3068
3081
- - (void)_removePersistedClusterDataForPath:(MTRClusterPath *)path
3082
- {
3083
- os_unfair_lock_assert_owner(&self->_lock);
3084
- if (_persistedClusters == nil || _persistedClusterData == nil) {
3085
- return;
3086
- }
3087
-
3088
- [_persistedClusterData removeObjectForKey:path];
3089
- [_persistedClusters removeObject:path];
3090
- }
3091
-
3092
- - (NSMutableSet<MTRClusterPath *> *)_getPersistedClusters
3093
- {
3094
- std::lock_guard lock(_lock);
3095
-
3096
- return _persistedClusters;
3097
- }
3098
-
3099
- - (MTRDeviceClusterData *)_getPersistedClusterDataForPath:(MTRClusterPath *)path
3069
+ #ifdef DEBUG
3070
+ - (MTRDeviceClusterData *)_getClusterDataForPath:(MTRClusterPath *)path
3100
3071
{
3101
3072
std::lock_guard lock(_lock);
3102
3073
3103
- if ([_persistedClusters containsObject:path]) {
3104
- return [_persistedClusterData objectForKey:path];
3105
- }
3106
- return nil;
3074
+ return [[self _clusterDataForPath:path] copy];
3107
3075
}
3108
3076
3109
- - (BOOL)_persistedClusterContains :(MTRClusterPath *)path
3077
+ - (BOOL)_clusterHasBeenPersisted :(MTRClusterPath *)path
3110
3078
{
3111
3079
std::lock_guard lock(_lock);
3112
3080
@@ -3115,6 +3083,7 @@ - (BOOL)_persistedClusterContains:(MTRClusterPath *)path
3115
3083
}
3116
3084
return NO;
3117
3085
}
3086
+ #endif
3118
3087
3119
3088
- (BOOL)deviceCachePrimed
3120
3089
{
0 commit comments