From 23edbec90379c46933219acf350aec2e3eef0061 Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:00:07 -0700 Subject: [PATCH] [Darwin] MTRDeviceController should clear attribute cache on pairing start --- .../Framework/CHIP/MTRDeviceController.mm | 45 +++- .../CHIP/MTRDeviceControllerDataStore.mm | 195 +++++++++++++----- 2 files changed, 173 insertions(+), 67 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index fa90eb2f542831..b72fc89b734e74 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -44,6 +44,7 @@ #import "MTRPersistentStorageDelegateBridge.h" #import "MTRServerEndpoint_Internal.h" #import "MTRSetupPayload.h" +#import "MTRUnfairLock.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" #import @@ -623,6 +624,12 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; }; + // Reset previous information about this new nodeID + os_unfair_lock_lock(&_deviceMapLock); + [self _removeDeviceWithNodeID:newNodeID device:nil]; + os_unfair_lock_unlock(&_deviceMapLock); + [_controllerDataStore clearStoredAttributesForNodeID:newNodeID]; + return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; } @@ -670,6 +677,12 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error]; }; + // Reset previous information about this new nodeID + os_unfair_lock_lock(&_deviceMapLock); + [self _removeDeviceWithNodeID:newNodeID device:nil]; + os_unfair_lock_unlock(&_deviceMapLock); + [_controllerDataStore clearStoredAttributesForNodeID:newNodeID]; + return [self syncRunOnWorkQueueWithBoolReturnValue:block error:error]; } @@ -897,18 +910,30 @@ - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID return deviceToReturn; } -- (void)removeDevice:(MTRDevice *)device +// Remove a device from the device map, optionally with a specific object +- (void)_removeDeviceWithNodeID:(NSNumber *)nodeID device:(MTRDevice * _Nullable)deviceToRemove { - os_unfair_lock_lock(&_deviceMapLock); - auto * nodeID = device.nodeID; - MTRDevice * deviceToRemove = _nodeIDToDeviceMap[nodeID]; - if (deviceToRemove == device) { - [deviceToRemove invalidate]; - _nodeIDToDeviceMap[nodeID] = nil; - } else { - MTR_LOG_ERROR("Error: Cannot remove device %p with nodeID %llu", device, nodeID.unsignedLongLongValue); + os_unfair_lock_assert_owner(&_deviceMapLock); + + MTRDevice * device = _nodeIDToDeviceMap[nodeID]; + if (!device) { + MTR_LOG_INFO("No device to remove with nodeID %llu", nodeID.unsignedLongLongValue); + return; } - os_unfair_lock_unlock(&_deviceMapLock); + + if (deviceToRemove && (device != deviceToRemove)) { + MTR_LOG_ERROR("Error: Cannot remove device %p with nodeID %llu", deviceToRemove, nodeID.unsignedLongLongValue); + return; + } + + [deviceToRemove invalidate]; + _nodeIDToDeviceMap[nodeID] = nil; +} + +- (void)removeDevice:(MTRDevice *)device +{ + std::lock_guard lock(_deviceMapLock); + [self _removeDeviceWithNodeID:device.nodeID device:device]; } - (void)setDeviceControllerDelegate:(id)delegate queue:(dispatch_queue_t)queue diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm index 0495211b76b449..9202da6cc9b095 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerDataStore.mm @@ -329,12 +329,12 @@ - (BOOL)_storeAttributeCacheValue:(id)value forKey:(NSString *)key sharingType:MTRStorageSharingTypeNotShared]; } -- (void)_removeAttributeCacheValueForKey:(NSString *)key +- (BOOL)_removeAttributeCacheValueForKey:(NSString *)key { - [_storageDelegate controller:_controller - removeValueForKey:key - securityLevel:MTRStorageSecurityLevelSecure - sharingType:MTRStorageSharingTypeNotShared]; + return [_storageDelegate controller:_controller + removeValueForKey:key + securityLevel:MTRStorageSecurityLevelSecure + sharingType:MTRStorageSharingTypeNotShared]; } static NSString * sAttributeCacheNodeIndexKey = @"attrCacheNodeIndex"; @@ -349,9 +349,9 @@ - (BOOL)_storeNodeIndex:(NSArray *)nodeIndex return [self _storeAttributeCacheValue:nodeIndex forKey:sAttributeCacheNodeIndexKey]; } -- (void)_deleteNodeIndex +- (BOOL)_deleteNodeIndex { - [self _removeAttributeCacheValueForKey:sAttributeCacheNodeIndexKey]; + return [self _removeAttributeCacheValueForKey:sAttributeCacheNodeIndexKey]; } static NSString * sAttributeCacheEndpointIndexKeyPrefix = @"attrCacheEndpointIndex"; @@ -371,9 +371,9 @@ - (BOOL)_storeEndpointIndex:(NSArray *)endpointIndex forNodeID:(NSNu return [self _storeAttributeCacheValue:endpointIndex forKey:[self _endpointIndexKeyForNodeID:nodeID]]; } -- (void)_deleteEndpointIndexForNodeID:(NSNumber *)nodeID +- (BOOL)_deleteEndpointIndexForNodeID:(NSNumber *)nodeID { - [self _removeAttributeCacheValueForKey:[self _endpointIndexKeyForNodeID:nodeID]]; + return [self _removeAttributeCacheValueForKey:[self _endpointIndexKeyForNodeID:nodeID]]; } static NSString * sAttributeCacheClusterIndexKeyPrefix = @"attrCacheClusterIndex"; @@ -393,9 +393,9 @@ - (BOOL)_storeClusterIndex:(NSArray *)clusterIndex forNodeID:(NSNumb return [self _storeAttributeCacheValue:clusterIndex forKey:[self _clusterIndexKeyForNodeID:nodeID endpointID:endpointID]]; } -- (void)_deleteClusterIndexForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID +- (BOOL)_deleteClusterIndexForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID { - [self _removeAttributeCacheValueForKey:[self _clusterIndexKeyForNodeID:nodeID endpointID:endpointID]]; + return [self _removeAttributeCacheValueForKey:[self _clusterIndexKeyForNodeID:nodeID endpointID:endpointID]]; } static NSString * sAttributeCacheAttributeIndexKeyPrefix = @"attrCacheAttributeIndex"; @@ -415,9 +415,9 @@ - (BOOL)_storeAttributeIndex:(NSArray *)attributeIndex forNodeID:(NS return [self _storeAttributeCacheValue:attributeIndex forKey:[self _attributeIndexKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID]]; } -- (void)_deleteAttributeIndexForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID +- (BOOL)_deleteAttributeIndexForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID { - [self _removeAttributeCacheValueForKey:[self _attributeIndexKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID]]; + return [self _removeAttributeCacheValueForKey:[self _attributeIndexKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID]]; } static NSString * sAttributeCacheAttributeValueKeyPrefix = @"attrCacheAttributeValue"; @@ -437,13 +437,19 @@ - (BOOL)_storeAttributeValue:(NSDictionary *)value forNodeID:(NSNumber *)nodeID return [self _storeAttributeCacheValue:value forKey:[self _attributeValueKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]]; } -- (void)_deleteAttributeValueForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID attributeID:(NSNumber *)attributeID +- (BOOL)_deleteAttributeValueForNodeID:(NSNumber *)nodeID endpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID attributeID:(NSNumber *)attributeID { - [self _removeAttributeCacheValueForKey:[self _attributeValueKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]]; + return [self _removeAttributeCacheValueForKey:[self _attributeValueKeyForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]]; } #pragma - Attribute Cache management +#define ATTRIBUTE_CACHE_VERBOSE_LOGGING 1 + +#ifndef ATTRIBUTE_CACHE_VERBOSE_LOGGING +#define ATTRIBUTE_CACHE_VERBOSE_LOGGING 0 +#endif + - (nullable NSArray *)getStoredAttributesForNodeID:(NSNumber *)nodeID { __block NSMutableArray * attributesToReturn = nil; @@ -451,6 +457,10 @@ - (void)_deleteAttributeValueForNodeID:(NSNumber *)nodeID endpointID:(NSNumber * // Fetch node index NSArray * nodeIndex = [self _fetchNodeIndex]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Fetch got %lu values for nodeIndex", static_cast(nodeIndex.count)); +#endif + if (![nodeIndex containsObject:nodeID]) { // Sanity check and delete if nodeID exists in index NSArray * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID]; @@ -458,6 +468,8 @@ - (void)_deleteAttributeValueForNodeID:(NSNumber *)nodeID endpointID:(NSNumber * MTR_LOG_ERROR("Persistent attribute cache contains orphaned entry for nodeID %@ - deleting", nodeID); [self clearStoredAttributesForNodeID:nodeID]; } + + MTR_LOG_INFO("Fetch got no value for endpointIndex @ 0x%016llX", nodeID.unsignedLongLongValue); attributesToReturn = nil; return; } @@ -465,17 +477,33 @@ - (void)_deleteAttributeValueForNodeID:(NSNumber *)nodeID endpointID:(NSNumber * // Fetch endpoint index NSArray * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Fetch got %lu values for endpointIndex @ 0x%016llX", static_cast(endpointIndex.count), nodeID.unsignedLongLongValue); +#endif + for (NSNumber * endpointID in endpointIndex) { // Fetch endpoint index NSArray * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:endpointID]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Fetch got %lu values for clusterIndex @ 0x%016llX:0x%04X", static_cast(clusterIndex.count), nodeID.unsignedLongLongValue, endpointID.unsignedShortValue); +#endif + for (NSNumber * clusterID in clusterIndex) { // Fetch endpoint index NSArray * attributeIndex = [self _fetchAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Fetch got %lu values for attributeIndex @ 0x%016llX:0x%04X:0x%08lX", static_cast(attributeIndex.count), nodeID.unsignedLongLongValue, endpointID.unsignedShortValue, clusterID.unsignedLongValue); +#endif + for (NSNumber * attributeID in attributeIndex) { NSDictionary * value = [self _fetchAttributeValueForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Fetch got %u values for attribute value @ 0x%016llX:0x%04X:0x%08lX:0x%08lX", value ? 1 : 0, nodeID.unsignedLongLongValue, endpointID.unsignedShortValue, clusterID.unsignedLongValue, attributeID.unsignedLongValue); +#endif + if (value) { if (!attributesToReturn) { attributesToReturn = [NSMutableArray array]; @@ -499,79 +527,95 @@ - (void)_pruneEmptyStoredAttributesBranches { dispatch_assert_queue(_storageDelegateQueue); + NSUInteger storeFailures = 0; + // Fetch node index - NSMutableArray * nodeIndex = [self _fetchNodeIndex].mutableCopy; - NSUInteger nodeIndexCount = nodeIndex.count; + NSArray * nodeIndex = [self _fetchNodeIndex].mutableCopy; + NSMutableArray * nodeIndexCopy = nodeIndex.mutableCopy; - NSUInteger storeFailures = 0; for (NSNumber * nodeID in nodeIndex) { // Fetch endpoint index - NSMutableArray * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID].mutableCopy; - NSUInteger endpointIndexCount = endpointIndex.count; + NSArray * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID]; + NSMutableArray * endpointIndexCopy = endpointIndex.mutableCopy; for (NSNumber * endpointID in endpointIndex) { // Fetch endpoint index - NSMutableArray * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:endpointID].mutableCopy; - NSUInteger clusterIndexCount = clusterIndex.count; + NSArray * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:endpointID].mutableCopy; + NSMutableArray * clusterIndexCopy = clusterIndex.mutableCopy; for (NSNumber * clusterID in clusterIndex) { // Fetch endpoint index - NSMutableArray * attributeIndex = [self _fetchAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID].mutableCopy; - NSUInteger attributeIndexCount = attributeIndex.count; + NSArray * attributeIndex = [self _fetchAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID].mutableCopy; + NSMutableArray * attributeIndexCopy = attributeIndex.mutableCopy; for (NSNumber * attributeID in attributeIndex) { NSDictionary * value = [self _fetchAttributeValueForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]; if (!value) { - [attributeIndex removeObject:attributeID]; + [attributeIndexCopy removeObject:attributeID]; } } - if (!attributeIndex.count) { - [clusterIndex removeObject:clusterID]; - } else if (attributeIndex.count != attributeIndexCount) { - BOOL success = [self _storeAttributeIndex:attributeIndex forNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + if (attributeIndex.count != attributeIndexCopy.count) { + BOOL success; if (!success) { + if (attributeIndexCopy.count) { + success = [self _storeAttributeIndex:attributeIndexCopy forNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + } else { + [clusterIndexCopy removeObject:clusterID]; + success = [self _deleteAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + } storeFailures++; - MTR_LOG_INFO("Store failed for attributeIndex"); + MTR_LOG_INFO("Store failed in _pruneEmptyStoredAttributesBranches for attributeIndex @ 0x%016llX:0x%04X:0x%08lX", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue, clusterID.unsignedLongValue); } } } - if (!clusterIndex.count) { - [endpointIndex removeObject:endpointID]; - } else if (clusterIndex.count != clusterIndexCount) { - BOOL success = [self _storeClusterIndex:clusterIndex forNodeID:nodeID endpointID:endpointID]; + if (clusterIndex.count != clusterIndexCopy.count) { + BOOL success; + if (clusterIndex.count) { + success = [self _storeClusterIndex:clusterIndexCopy forNodeID:nodeID endpointID:endpointID]; + } else { + [endpointIndexCopy removeObject:endpointID]; + success = [self _deleteClusterIndexForNodeID:nodeID endpointID:endpointID]; + } if (!success) { storeFailures++; - MTR_LOG_INFO("Store failed for clusterIndex"); + MTR_LOG_INFO("Store failed in _pruneEmptyStoredAttributesBranches for clusterIndex @ 0x%016llX:0x%04X", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue); } } } - if (!endpointIndex.count) { - [nodeIndex removeObject:nodeID]; - } else if (endpointIndex.count != endpointIndexCount) { - BOOL success = [self _storeEndpointIndex:endpointIndex forNodeID:nodeID]; + if (endpointIndex.count != endpointIndexCopy.count) { + BOOL success; + if (endpointIndexCopy.count) { + success = [self _storeEndpointIndex:endpointIndexCopy forNodeID:nodeID]; + } else { + [nodeIndexCopy removeObject:nodeID]; + success = [self _deleteEndpointIndexForNodeID:nodeID]; + } if (!success) { storeFailures++; - MTR_LOG_INFO("Store failed for endpointIndex"); + MTR_LOG_INFO("Store failed in _pruneEmptyStoredAttributesBranches for endpointIndex @ 0x%016llX", nodeID.unsignedLongLongValue); } } } - if (!nodeIndex.count) { - [self _deleteNodeIndex]; - } else if (nodeIndex.count != nodeIndexCount) { - BOOL success = [self _storeNodeIndex:nodeIndex]; + if (nodeIndex.count != nodeIndexCopy.count) { + BOOL success; + if (!nodeIndex.count) { + success = [self _storeNodeIndex:nodeIndexCopy]; + } else { + success = [self _deleteNodeIndex]; + } if (!success) { storeFailures++; - MTR_LOG_INFO("Store failed for nodeIndex"); + MTR_LOG_INFO("Store failed in _pruneEmptyStoredAttributesBranches for nodeIndex"); } } if (storeFailures) { - MTR_LOG_ERROR("Store failed in _pruneEmptyStoredAttributesBranches: %lu", (unsigned long) storeFailures); + MTR_LOG_ERROR("Store failed in _pruneEmptyStoredAttributesBranches: total %lu", static_cast(storeFailures)); } } @@ -584,6 +628,10 @@ - (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NS MTRAttributePath * path = dataValue[MTRAttributePathKey]; NSDictionary * value = dataValue[MTRDataKey]; +#if ATTRIBUTE_CACHE_VERBOSE_LOGGING + MTR_LOG_INFO("Attempt to store attribute value @ 0x%016llX:0x%04X:0x%08lX:0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue, path.attribute.unsignedLongValue); +#endif + BOOL storeFailed = NO; // Ensure node index exists NSArray * nodeIndex = [self _fetchNodeIndex]; @@ -609,7 +657,7 @@ - (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NS } if (storeFailed) { storeFailures++; - MTR_LOG_INFO("Store failed for endpointIndex"); + MTR_LOG_INFO("Store failed for endpointIndex @ 0x%016llX", nodeID.unsignedLongLongValue); continue; } @@ -623,7 +671,7 @@ - (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NS } if (storeFailed) { storeFailures++; - MTR_LOG_INFO("Store failed for clusterIndex"); + MTR_LOG_INFO("Store failed for clusterIndex @ 0x%016llX:0x%04X", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue); continue; } @@ -640,50 +688,80 @@ - (void)storeAttributeValues:(NSArray *)dataValues forNodeID:(NS } if (storeFailed) { storeFailures++; - MTR_LOG_INFO("Store failed for attributeIndex"); + MTR_LOG_INFO("Store failed for attributeIndex @ 0x%016llX:0x%04X:0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue); continue; } // Store value - storeFailed = [self _storeAttributeValue:value forNodeID:nodeID endpointID:path.endpoint clusterID:path.cluster attributeID:path.attribute]; + storeFailed = ![self _storeAttributeValue:value forNodeID:nodeID endpointID:path.endpoint clusterID:path.cluster attributeID:path.attribute]; if (storeFailed) { storeFailures++; - MTR_LOG_INFO("Store failed for attribute value"); + MTR_LOG_INFO("Store failed for attribute value @ 0x%016llX:0x%04X:0x%08lX:0x%08lX", nodeID.unsignedLongLongValue, path.endpoint.unsignedShortValue, path.cluster.unsignedLongValue, path.attribute.unsignedLongValue); } } // 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]; - MTR_LOG_ERROR("Store failed in -storeAttributeValues:forNodeID: %lu", (unsigned long) storeFailures); + MTR_LOG_ERROR("Store failed in -storeAttributeValues:forNodeID: total %lu", static_cast(storeFailures)); } }); } - (void)_clearStoredAttributesForNodeID:(NSNumber *)nodeID { + NSUInteger endpointsClearAttempts = 0; + NSUInteger clustersClearAttempts = 0; + NSUInteger attributesClearAttempts = 0; + NSUInteger endpointsCleared = 0; + NSUInteger clustersCleared = 0; + NSUInteger attributesCleared = 0; + // Fetch endpoint index NSArray * endpointIndex = [self _fetchEndpointIndexForNodeID:nodeID]; + endpointsClearAttempts += endpointIndex.count; for (NSNumber * endpointID in endpointIndex) { // Fetch cluster index NSArray * clusterIndex = [self _fetchClusterIndexForNodeID:nodeID endpointID:endpointID]; + clustersClearAttempts += clusterIndex.count; for (NSNumber * clusterID in clusterIndex) { // Fetch attribute index NSArray * attributeIndex = [self _fetchAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + attributesClearAttempts += attributeIndex.count; for (NSNumber * attributeID in attributeIndex) { - [self _deleteAttributeValueForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]; + BOOL success = [self _deleteAttributeValueForNodeID:nodeID endpointID:endpointID clusterID:clusterID attributeID:attributeID]; + if (!success) { + MTR_LOG_INFO("Delete failed for attribute value @ 0x%016llX:0x%04X:0x%08lX:0x%08lX", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue, clusterID.unsignedLongValue, attributeID.unsignedLongValue); + } else { + attributesCleared++; + } } - [self _deleteAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + BOOL success = [self _deleteAttributeIndexForNodeID:nodeID endpointID:endpointID clusterID:clusterID]; + if (!success) { + MTR_LOG_INFO("Delete failed for attributeIndex @ 0x%016llX:0x%04X:0x%08lX", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue, clusterID.unsignedLongValue); + } else { + clustersCleared++; + } } - [self _deleteClusterIndexForNodeID:nodeID endpointID:endpointID]; + BOOL success = [self _deleteClusterIndexForNodeID:nodeID endpointID:endpointID]; + if (!success) { + MTR_LOG_INFO("Delete failed for clusterIndex @ 0x%016llX:0x%04X", nodeID.unsignedLongLongValue, endpointID.unsignedShortValue); + } else { + endpointsCleared++; + } } - [self _deleteEndpointIndexForNodeID:nodeID]; + BOOL success = [self _deleteEndpointIndexForNodeID:nodeID]; + if (!success) { + MTR_LOG_INFO("Delete failed for endpointrIndex @ 0x%016llX", nodeID.unsignedLongLongValue); + } + + MTR_LOG_INFO("clearStoredAttributesForNodeID: deleted endpoints %lu/%lu clusters %lu/%lu attributes %lu/%lu", static_cast(endpointsCleared), static_cast(endpointsClearAttempts), static_cast(clustersCleared), static_cast(clustersClearAttempts), static_cast(attributesCleared), static_cast(attributesClearAttempts)); } - (void)clearStoredAttributesForNodeID:(NSNumber *)nodeID @@ -703,7 +781,10 @@ - (void)clearAllStoredAttributes [self _clearStoredAttributesForNodeID:nodeID]; } - [self _deleteNodeIndex]; + BOOL success = [self _deleteNodeIndex]; + if (!success) { + MTR_LOG_INFO("Delete failed for nodeIndex"); + } }); }