Skip to content

Commit

Permalink
Remove no-longer-used MTRDevice logic for truncating data version lis…
Browse files Browse the repository at this point in the history
…ts (#34183)

* Remove no-longer-used MTRDevice logic for truncating data version lists

After #34111, ReadClient
handles this logic itself, so the attempted truncation in MTRDevice was now dead
code.

* Address review comment.

* Fix compile issues.

* Address another review comment.

* Address review comment.
  • Loading branch information
bzbarsky-apple authored Jul 25, 2024
1 parent b74057e commit ba949bf
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 80 deletions.
22 changes: 21 additions & 1 deletion src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder
const Span<DataVersionFilter> & aDataVersionFilters,
bool & aEncodedDataVersionList)
{
#if CHIP_PROGRESS_LOGGING
size_t encodedFilterCount = 0;
size_t irrelevantFilterCount = 0;
size_t skippedFilterCount = 0;
#endif
for (auto & filter : aDataVersionFilters)
{
VerifyOrReturnError(filter.IsValidDataVersionFilter(), CHIP_ERROR_INVALID_ARGUMENT);
Expand All @@ -420,6 +425,9 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder

if (!intersected)
{
#if CHIP_PROGRESS_LOGGING
++irrelevantFilterCount;
#endif
continue;
}

Expand All @@ -428,19 +436,31 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder
CHIP_ERROR err = EncodeDataVersionFilter(aDataVersionFilterIBsBuilder, filter);
if (err == CHIP_NO_ERROR)
{
#if CHIP_PROGRESS_LOGGING
++encodedFilterCount;
#endif
aEncodedDataVersionList = true;
}
else if (err == CHIP_ERROR_NO_MEMORY || err == CHIP_ERROR_BUFFER_TOO_SMALL)
{
// Packet is full, ignore the rest of the list
aDataVersionFilterIBsBuilder.Rollback(backup);
return CHIP_NO_ERROR;
#if CHIP_PROGRESS_LOGGING
ssize_t nonSkippedFilterCount = &filter - aDataVersionFilters.data();
skippedFilterCount = aDataVersionFilters.size() - static_cast<size_t>(nonSkippedFilterCount);
#endif // CHIP_PROGRESS_LOGGING
break;
}
else
{
return err;
}
}

ChipLogProgress(DataManagement,
"%lu data version filters provided, %lu not relevant, %lu encoded, %lu skipped due to lack of space",
static_cast<unsigned long>(aDataVersionFilters.size()), static_cast<unsigned long>(irrelevantFilterCount),
static_cast<unsigned long>(encodedFilterCount), static_cast<unsigned long>(skippedFilterCount));
return CHIP_NO_ERROR;
}

Expand Down
132 changes: 53 additions & 79 deletions src/darwin/Framework/CHIP/MTRDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2277,32 +2277,26 @@ - (void)_removeCachedAttribute:(NSNumber *)attributeID fromCluster:(MTRClusterPa
[clusterData removeValueForAttribute:attributeID];
}

- (void)_createDataVersionFilterListFromDictionary:(NSDictionary<MTRClusterPath *, NSNumber *> *)dataVersions dataVersionFilterList:(DataVersionFilter **)dataVersionFilterList count:(size_t *)count sizeReduction:(size_t)sizeReduction
- (void)_createDataVersionFilterListFromDictionary:(NSDictionary<MTRClusterPath *, NSNumber *> *)dataVersions dataVersionFilterList:(DataVersionFilter **)dataVersionFilterList count:(size_t *)count
{
size_t maxDataVersionFilterSize = dataVersions.count;
size_t dataVersionFilterSize = dataVersions.count;

// Check if any filter list should be generated
if (!dataVersions.count || (maxDataVersionFilterSize <= sizeReduction)) {
if (dataVersionFilterSize == 0) {
*count = 0;
*dataVersionFilterList = nullptr;
return;
}
maxDataVersionFilterSize -= sizeReduction;

DataVersionFilter * dataVersionFilterArray = new DataVersionFilter[maxDataVersionFilterSize];
DataVersionFilter * dataVersionFilterArray = new DataVersionFilter[dataVersionFilterSize];
size_t i = 0;
for (MTRClusterPath * path in dataVersions) {
NSNumber * dataVersionNumber = dataVersions[path];
if (dataVersionNumber) {
dataVersionFilterArray[i++] = DataVersionFilter(static_cast<chip::EndpointId>(path.endpoint.unsignedShortValue), static_cast<chip::ClusterId>(path.cluster.unsignedLongValue), static_cast<chip::DataVersion>(dataVersionNumber.unsignedLongValue));
}
if (i == maxDataVersionFilterSize) {
break;
}
dataVersionFilterArray[i++] = DataVersionFilter(static_cast<chip::EndpointId>(path.endpoint.unsignedShortValue), static_cast<chip::ClusterId>(path.cluster.unsignedLongValue), static_cast<chip::DataVersion>(dataVersionNumber.unsignedLongValue));
}

*dataVersionFilterList = dataVersionFilterArray;
*count = maxDataVersionFilterSize;
*count = dataVersionFilterSize;
}

- (void)_setupConnectivityMonitoring
Expand Down Expand Up @@ -2530,75 +2524,55 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
auto readClient = std::make_unique<ReadClient>(InteractionModelEngine::GetInstance(), exchangeManager,
clusterStateCache->GetBufferedCallback(), ReadClient::InteractionType::Subscribe);

// Subscribe with data version filter list and retry with smaller list if out of packet space
CHIP_ERROR err;
NSDictionary<MTRClusterPath *, NSNumber *> * dataVersions = [self _getCachedDataVersions];
size_t dataVersionFilterListSizeReduction = 0;
for (;;) {
// Wildcard endpoint, cluster, attribute, event.
auto attributePath = std::make_unique<AttributePathParams>();
auto eventPath = std::make_unique<EventPathParams>();
// We want to get event reports at the minInterval, not the maxInterval.
eventPath->mIsUrgentEvent = true;
ReadPrepareParams readParams(session.Value());

readParams.mMinIntervalFloorSeconds = 0;
// Select a max interval based on the device's claimed idle sleep interval.
auto idleSleepInterval = std::chrono::duration_cast<System::Clock::Seconds32>(
session.Value()->GetRemoteMRPConfig().mIdleRetransTimeout);

auto maxIntervalCeilingMin = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MIN);
if (idleSleepInterval < maxIntervalCeilingMin) {
idleSleepInterval = maxIntervalCeilingMin;
}

auto maxIntervalCeilingMax = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MAX);
if (idleSleepInterval > maxIntervalCeilingMax) {
idleSleepInterval = maxIntervalCeilingMax;
}
// Wildcard endpoint, cluster, attribute, event.
auto attributePath = std::make_unique<AttributePathParams>();
auto eventPath = std::make_unique<EventPathParams>();
// We want to get event reports at the minInterval, not the maxInterval.
eventPath->mIsUrgentEvent = true;
ReadPrepareParams readParams(session.Value());

readParams.mMinIntervalFloorSeconds = 0;
// Select a max interval based on the device's claimed idle sleep interval.
auto idleSleepInterval = std::chrono::duration_cast<System::Clock::Seconds32>(
session.Value()->GetRemoteMRPConfig().mIdleRetransTimeout);

auto maxIntervalCeilingMin = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MIN);
if (idleSleepInterval < maxIntervalCeilingMin) {
idleSleepInterval = maxIntervalCeilingMin;
}

auto maxIntervalCeilingMax = System::Clock::Seconds32(MTR_DEVICE_SUBSCRIPTION_MAX_INTERVAL_MAX);
if (idleSleepInterval > maxIntervalCeilingMax) {
idleSleepInterval = maxIntervalCeilingMax;
}
#ifdef DEBUG
if (maxIntervalOverride.HasValue()) {
idleSleepInterval = maxIntervalOverride.Value();
}
#endif
readParams.mMaxIntervalCeilingSeconds = static_cast<uint16_t>(idleSleepInterval.count());

readParams.mpAttributePathParamsList = attributePath.get();
readParams.mAttributePathParamsListSize = 1;
readParams.mpEventPathParamsList = eventPath.get();
readParams.mEventPathParamsListSize = 1;
readParams.mKeepSubscriptions = true;
readParams.mIsFabricFiltered = false;
size_t dataVersionFilterListSize = 0;
DataVersionFilter * dataVersionFilterList;
[self _createDataVersionFilterListFromDictionary:dataVersions dataVersionFilterList:&dataVersionFilterList count:&dataVersionFilterListSize sizeReduction:dataVersionFilterListSizeReduction];
readParams.mDataVersionFilterListSize = dataVersionFilterListSize;
readParams.mpDataVersionFilterList = dataVersionFilterList;
attributePath.release();
eventPath.release();

// TODO: Change from local filter list generation to rehydrating ClusterStateCache ot take advantage of existing filter list sorting algorithm

// SendAutoResubscribeRequest cleans up the params, even on failure.
err = readClient->SendAutoResubscribeRequest(std::move(readParams));
if (err == CHIP_NO_ERROR) {
break;
}

// If error is not a "no memory" issue, then break and go through regular resubscribe logic
if (err != CHIP_ERROR_NO_MEMORY) {
break;
}

// If "no memory" error is not caused by data version filter list, break as well
if (!dataVersionFilterListSize) {
break;
}

// Now "no memory" could mean subscribe request packet space ran out. Reduce size and try again immediately
dataVersionFilterListSizeReduction++;
if (maxIntervalOverride.HasValue()) {
idleSleepInterval = maxIntervalOverride.Value();
}
#endif
readParams.mMaxIntervalCeilingSeconds = static_cast<uint16_t>(idleSleepInterval.count());

readParams.mpAttributePathParamsList = attributePath.get();
readParams.mAttributePathParamsListSize = 1;
readParams.mpEventPathParamsList = eventPath.get();
readParams.mEventPathParamsListSize = 1;
readParams.mKeepSubscriptions = true;
readParams.mIsFabricFiltered = false;

// Subscribe with data version filter list from our cache.
size_t dataVersionFilterListSize = 0;
DataVersionFilter * dataVersionFilterList;
[self _createDataVersionFilterListFromDictionary:[self _getCachedDataVersions] dataVersionFilterList:&dataVersionFilterList count:&dataVersionFilterListSize];

readParams.mDataVersionFilterListSize = dataVersionFilterListSize;
readParams.mpDataVersionFilterList = dataVersionFilterList;
attributePath.release();
eventPath.release();

// TODO: Change from local filter list generation to rehydrating ClusterStateCache to take advantage of existing filter list sorting algorithm

// SendAutoResubscribeRequest cleans up the params, even on failure.
CHIP_ERROR err = readClient->SendAutoResubscribeRequest(std::move(readParams));
if (err != CHIP_NO_ERROR) {
NSError * error = [MTRError errorForCHIPErrorCode:err logContext:self];
MTR_LOG_ERROR("%@ SendAutoResubscribeRequest error %@", self, error);
Expand All @@ -2610,7 +2584,7 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason
return;
}

MTR_LOG("%@ Subscribe with data version list size %lu, reduced by %lu", self, static_cast<unsigned long>(dataVersions.count), static_cast<unsigned long>(dataVersionFilterListSizeReduction));
MTR_LOG("%@ Subscribe with data version list size %lu", self, static_cast<unsigned long>(dataVersionFilterListSize));

// Callback and ClusterStateCache and ReadClient will be deleted
// when OnDone is called.
Expand Down

0 comments on commit ba949bf

Please sign in to comment.