Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder
const Span<DataVersionFilter> & aDataVersionFilters,
bool & aEncodedDataVersionList)
{
ChipLogProgress(DataManagement, "Attempting to encode %lu data version filters", static_cast<unsigned long>(aDataVersionFilters.size()));
woody-apple marked this conversation as resolved.
Show resolved Hide resolved
for (auto & filter : aDataVersionFilters)
{
VerifyOrReturnError(filter.IsValidDataVersionFilter(), CHIP_ERROR_INVALID_ARGUMENT);
Expand Down Expand Up @@ -434,6 +435,12 @@ CHIP_ERROR ReadClient::BuildDataVersionFilterList(DataVersionFilterIBs::Builder
{
// Packet is full, ignore the rest of the list
aDataVersionFilterIBsBuilder.Rollback(backup);
#if CHIP_PROGRESS_LOGGING
ssize_t nonSkippedFilters = &filter - aDataVersionFilters.data();
size_t skippedFilters = aDataVersionFilters.size() - static_cast<size_t>(nonSkippedFilters);
ChipLogProgress(DataManagement, "Skipped encoding %lu out of %lu data version filters due to lack of space",
static_cast<unsigned long>(skippedFilters), static_cast<unsigned long>(aDataVersionFilters.size()));
#endif // CHIP_PROGRESS_LOGGING
return CHIP_NO_ERROR;
}
else
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 @@ -2223,32 +2223,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 @@ -2443,75 +2437,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 @@ -2523,7 +2497,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));
bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
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
Loading