@@ -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