Skip to content

Fix handling of out-of-range scan option#13995

Closed
cbi42 wants to merge 5 commits intofacebook:mainfrom
cbi42:handle-oob-scan-opts
Closed

Fix handling of out-of-range scan option#13995
cbi42 wants to merge 5 commits intofacebook:mainfrom
cbi42:handle-oob-scan-opts

Conversation

@cbi42
Copy link
Contributor

@cbi42 cbi42 commented Sep 24, 2025

Summary: currently BlockBasedTableIterator::Prepare() fails the iterator with non-ok status if an out-of-range scan option is detected. This is due to the interaction between LevelIterator and BlockBasedTableIterator, see added comment above BlockBasedTableIterator::Prepare(). This can fail stress test for L0 files since it doesn't use LevelIterator and scan options are not pruned. This PR fixes this by adding an internal option to MultiScanArgs that enables this check.

Test plan:

  • new unit test
  • stress test that fails before this pr: python3 -u ./tools/db_crashtest.py whitebox --iterpercent=60 --prefix_size=-1 --prefixpercent=0 --readpercent=0 --test_batches_snapshots=0 --use_multiscan=1 --read_fault_one_in=0 --kill_random_test=88888 --interval=60 --multiscan_use_async_io=0 --mmap_read=0 --level0_file_num_compaction_trigger=20

@meta-cla meta-cla bot added the CLA Signed label Sep 24, 2025
@facebook-github-bot
Copy link
Contributor

@cbi42 has imported this pull request. If you are a Meta employee, you can view this in D83166088.

Comment on lines +1193 to +1196
file_to_arg.second.io_coalesce_threshold = so->io_coalesce_threshold;
file_to_arg.second.max_prefetch_size = so->max_prefetch_size;
file_to_arg.second.use_async_io = so->use_async_io;
file_to_arg.second.require_file_overlap = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to group the properties that needs to propagate down to each file together? In addition, since all of them are const, maybe we could just use a const pointer to it? Is there any lifetime concern?

struct MultiScanOptions {
  io_coalesce_threshold;
  max_prefetch_size;
};

struct MultiScanArgs {
  MultiScanOptions options;
};

for (auto& file_to_arg : *file_to_scan_opts_) {
  file_to_arg.options = so->options;
}


Comment on lines +1879 to +1882
// Internal use only.
// Fail the Prepare() on a file if a scan range does not overlap
// with the file.
bool require_file_overlap = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we expect this value is always set to false when caller pass it to RocksDB external API? Meantime, since this is exposed to caller, caller could set it by mistake. Probably, we should set it to false, when RocksDB received it. However, there might be many places we need to update, which is hard to maintain and enforce. Maybe it is better to move it to private and declare a the classes that need to access it as friends.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to private field.

;
// If require_file_overlap is set, then the scan ranges for this file
// must intersect with the file. Otherwise, allow empty intersection.
if (multiscan_opts->require_file_overlap) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the only usage of multiscan_opts is to get require_file_overlap, why not just pass require_file_overlap itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other fields of multiscan_opts are also used. To pass require_file_overlap by itself, I'll have to change Prepare() signature for the iterator interface which is a bigger change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think his comment is just about CollectBlockHandles

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated CollectBlockHandles()

Copy link
Contributor

@anand1976 anand1976 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Would be good to add a test with L0/non-L0 files to verify the end to end works as expected.

@cbi42
Copy link
Contributor Author

cbi42 commented Sep 25, 2025

LGTM. Would be good to add a test with L0/non-L0 files to verify the end to end works as expected.

Thanks for the review, I've added a test with both L0 and non-L0 files which fails before this PR.

@facebook-github-bot
Copy link
Contributor

@cbi42 has imported this pull request. If you are a Meta employee, you can view this in D83166088.

@facebook-github-bot
Copy link
Contributor

@cbi42 merged this pull request in 862438a.

xingbowang pushed a commit to xingbowang/rocksdb that referenced this pull request Oct 6, 2025
Summary:
currently BlockBasedTableIterator::Prepare() fails the iterator with non-ok status if an out-of-range scan option is detected. This is due to the interaction between LevelIterator and BlockBasedTableIterator, see added comment above BlockBasedTableIterator::Prepare(). This can fail stress test for L0 files since it doesn't use LevelIterator and scan options are not pruned. This PR fixes this by adding an internal option to MultiScanArgs that enables this check.

Pull Request resolved: facebook#13995

Test Plan:
- new unit test
- stress test that fails before this pr: `python3 -u ./tools/db_crashtest.py whitebox --iterpercent=60 --prefix_size=-1 --prefixpercent=0 --readpercent=0 --test_batches_snapshots=0 --use_multiscan=1 --read_fault_one_in=0 --kill_random_test=88888 --interval=60 --multiscan_use_async_io=0 --mmap_read=0 --level0_file_num_compaction_trigger=20`

Reviewed By: anand1976

Differential Revision: D83166088

Pulled By: cbi42

fbshipit-source-id: 241a7d43c8c00d9a98eea0cabb03d2174d51aae5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants