Compare commits

...

9 Commits

Author SHA1 Message Date
Yanqin Jin 050027c35d Update version 2022-07-13 12:01:38 -07:00
Yanqin Jin 41be9ec937 Stop tracking syncing live WAL for performance (#10330)
Summary:
With https://github.com/facebook/rocksdb/issues/10087, applications calling `SyncWAL()` or writing with `WriteOptions::sync=true` can suffer
from performance regression. This PR reverts to original behavior of tracking the syncing of closed WALs.
After we revert back to old behavior, recovery, whether kPointInTime or kAbsoluteConsistency, may fail to
detect corruption in synced WALs if the corruption is in the live WAL.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10330

Test Plan:
make check

Before https://github.com/facebook/rocksdb/issues/10087
```bash
fillsync     :     750.269 micros/op 1332 ops/sec 75.027 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync     :     776.492 micros/op 1287 ops/sec 77.649 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 2 runs] : 1310 (± 44) ops/sec;    0.1 (± 0.0) MB/sec
fillsync     :     805.625 micros/op 1241 ops/sec 80.563 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 3 runs] : 1287 (± 51) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [AVG    3 runs] : 1287 (± 51) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [MEDIAN 3 runs] : 1287 ops/sec;    0.1 MB/sec
```

Before this PR and after https://github.com/facebook/rocksdb/issues/10087
```bash
fillsync     :    1479.601 micros/op 675 ops/sec 147.960 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync     :    1626.080 micros/op 614 ops/sec 162.608 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 2 runs] : 645 (± 59) ops/sec;    0.1 (± 0.0) MB/sec
fillsync     :    1588.402 micros/op 629 ops/sec 158.840 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 3 runs] : 640 (± 35) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [AVG    3 runs] : 640 (± 35) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [MEDIAN 3 runs] : 629 ops/sec;    0.1 MB/sec
```

After this PR
```bash
fillsync     :     749.621 micros/op 1334 ops/sec 74.962 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync     :     865.577 micros/op 1155 ops/sec 86.558 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 2 runs] : 1244 (± 175) ops/sec;    0.1 (± 0.0) MB/sec
fillsync     :     845.837 micros/op 1182 ops/sec 84.584 seconds 100000 operations;    0.1 MB/s (100 ops)
fillsync [AVG 3 runs] : 1223 (± 109) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [AVG    3 runs] : 1223 (± 109) ops/sec;    0.1 (± 0.0) MB/sec
fillsync [MEDIAN 3 runs] : 1182 ops/sec;    0.1 MB/sec
```

Reviewed By: ajkr

Differential Revision: D37725212

Pulled By: riversand963

fbshipit-source-id: 8fa7d13b3c7662be5d56351c42caf3266af937ae
2022-07-13 12:01:38 -07:00
akankshamahajan 4fd1285584 Update version to 7.4.2 and update HISTORY 2022-06-30 19:16:59 -07:00
Akanksha Mahajan d74333c500 Fix bug in Logger creation if dbname and db_log_dir are on different filesystem (#10292)
Summary:
If dbname and db_log_dir are at different filesystems (one
local and one remote), creation of dbname will fail because that path
doesn't exist wrt to db_log_dir.
This patch will ignore the error returned on creation of dbname. If they
are on same filesystem, db_log_dir creation will automatically return
the error in case there is any error in creation of dbname.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10292

Test Plan: Existing unit tests

Reviewed By: riversand963

Differential Revision: D37567773

Pulled By: akankshamahajan15

fbshipit-source-id: 005d28c536208d4c126c8cb8e196d1d85b881100
2022-06-30 19:12:53 -07:00
Peter Dillinger 57adbf0e91 Update version to 7.4.1 and update HISTORY 2022-06-28 09:36:10 -07:00
Bo Wang 0b8c8cf13a Pass rate_limiter_priority through filter block reader functions to FS (#10251)
Summary:
With https://github.com/facebook/rocksdb/pull/9996 , we can pass the rate_limiter_priority to FS for most cases. This PR is to update the code path for filter block reader.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10251

Test Plan: Current unit tests should pass.

Reviewed By: pdillinger

Differential Revision: D37427667

Pulled By: gitbw95

fbshipit-source-id: 1ce5b759b136efe4cfa48a6b97e2f837ff087433
2022-06-28 09:28:09 -07:00
Yanqin Jin 1bee5e0254 Expose the initial logger creation error (#10223)
Summary:
https://github.com/facebook/rocksdb/issues/9984 changes the behavior of RocksDB: if logger creation failed during `SanitizeOptions()`,
`DB::Open()` will fail. However, since `SanitizeOptions()` is called in `DBImpl::DBImpl()`, we cannot
directly expose the error to caller without some additional work.
This is a first version proposal which:
- Adds a new member `init_logger_creation_s` to `DBImpl` to store the result of init logger creation
- Checks the error during `DB::Open()` and return it to caller if non-ok

This is not very ideal. We can alternatively move the logger creation logic out of the `SanitizeOptions()`.
Since `SanitizeOptions()` is used in other places, we need to check whether this change breaks anything
in case other callers of `SanitizeOptions()` assumes that a logger should be created.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10223

Test Plan: make check

Reviewed By: pdillinger

Differential Revision: D37321717

Pulled By: riversand963

fbshipit-source-id: 58042358a86369d606549dd9938933dd47591c4b
2022-06-22 08:36:05 -07:00
Peter Dillinger c79e43d0dc Add data block hash index to crash test, fix MultiGet issue (#10220)
Summary:
There was a bug in the MultiGet enhancement in https://github.com/facebook/rocksdb/issues/9899 with data
block hash index, which was not caught because data block hash index was
never added to stress tests. This change fixes both issues.

Fixes https://github.com/facebook/rocksdb/issues/10186

I intend to pick this into the 7.4.0 release candidate

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10220

Test Plan:
Failure quickly reproduces in crash test with
kDataBlockBinaryAndHash, and does not seem to with the fix. Reproducing
the failure with a unit test I believe would be too tricky and fragile
to be worthwhile.

Reviewed By: anand1976

Differential Revision: D37315647

Pulled By: pdillinger

fbshipit-source-id: 9f648265bba867275edc752f7a56611a59401cba
2022-06-22 08:35:44 -07:00
Peter Dillinger c26abd4c25 Fix bad include (#10213)
Summary:
include "include/rocksdb/blah.h" is messing up some internal
builds vs. include "rocksdb/blah." This fixes the bad case and adds a
check for future instances.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/10213

Test Plan: back-port to 7.4 release candidate and watch internal build

Reviewed By: hx235

Differential Revision: D37296202

Pulled By: pdillinger

fbshipit-source-id: d7cc6b2c57d858dff0444f19320d83c8b4f9b185
2022-06-20 17:54:08 -07:00
29 changed files with 280 additions and 128 deletions
+14
View File
@@ -1,4 +1,16 @@
# Rocksdb Change Log
## 7.4.3 (07/13/2022)
### Behavior Changes
* For track_and_verify_wals_in_manifest, revert to the original behavior before #10087: syncing of live WAL file is not tracked, and we track only the synced sizes of **closed** WALs. (PR #10330).
## 7.4.2 (06/30/2022)
### Bug Fixes
* Fix a bug in Logger where if dbname and db_log_dir are on different filesystems, dbname creation would fail wrt to db_log_dir path returning an error and fails to open the DB.
## 7.4.1 (06/28/2022)
### Bug Fixes
* Pass `rate_limiter_priority` through filter block reader functions to `FileSystem`.
## 7.4.0 (06/19/2022)
### Bug Fixes
* Fixed a bug in calculating key-value integrity protection for users of in-place memtable updates. In particular, the affected users would be those who configure `protection_bytes_per_key > 0` on `WriteBatch` or `WriteOptions`, and configure `inplace_callback != nullptr`.
@@ -13,6 +25,8 @@
* Avoid a crash if the IDENTITY file is accidentally truncated to empty. A new DB ID will be written and generated on Open.
* Fixed a possible corruption for users of `manual_wal_flush` and/or `FlushWAL(true /* sync */)`, together with `track_and_verify_wals_in_manifest == true`. For those users, losing unsynced data (e.g., due to power loss) could make future DB opens fail with a `Status::Corruption` complaining about missing WAL data.
* Fixed a bug in `WriteBatchInternal::Append()` where WAL termination point in write batch was not considered and the function appends an incorrect number of checksums.
* Fixed a crash bug introduced in 7.3.0 affecting users of MultiGet with `kDataBlockBinaryAndHash`.
* Add some fixes in async_io which was doing extra prefetching in shorter scans.
### Public API changes
* Add new API GetUnixTime in Snapshot class which returns the unix time at which Snapshot is taken.
+7 -1
View File
@@ -17,12 +17,18 @@ if [ "$?" != "1" ]; then
BAD=1
fi
git grep -n '<rocksdb/' -- ':!build_tools/check-sources.sh'
git grep -n 'include <rocksdb/' -- ':!build_tools/check-sources.sh'
if [ "$?" != "1" ]; then
echo '^^^^^ Use double-quotes as in #include "rocksdb/something.h"'
BAD=1
fi
git grep -n 'include "include/rocksdb/' -- ':!build_tools/check-sources.sh'
if [ "$?" != "1" ]; then
echo '^^^^^ Use #include "rocksdb/something.h" instead of #include "include/rocksdb/something.h"'
BAD=1
fi
git grep -n 'using namespace' -- ':!build_tools' ':!docs' \
':!third-party/folly/folly/lang/Align.h' \
':!third-party/gtest-1.8.1/fused-src/gtest/gtest.h'
+1 -1
View File
@@ -10,7 +10,7 @@
#include "cache/cache_helpers.h"
#include "cache/cache_key.h"
#include "db/blob/blob_file_cache.h"
#include "include/rocksdb/cache.h"
#include "rocksdb/cache.h"
#include "rocksdb/rocksdb_namespace.h"
#include "table/block_based/cachable_entry.h"
+4 -2
View File
@@ -4143,7 +4143,7 @@ TEST_F(DBBasicTest, FailOpenIfLoggerCreationFail) {
Status s = TryReopen(options);
ASSERT_EQ(nullptr, options.info_log);
ASSERT_TRUE(s.IsAborted());
ASSERT_TRUE(s.IsIOError());
SyncPoint::GetInstance()->DisableProcessing();
SyncPoint::GetInstance()->ClearAllCallBacks();
@@ -4193,7 +4193,9 @@ TEST_F(DBBasicTest, VerifyFileChecksums) {
ASSERT_TRUE(db_->VerifyFileChecksums(ReadOptions()).IsInvalidArgument());
}
TEST_F(DBBasicTest, ManualWalSync) {
// TODO: re-enable after we provide finer-grained control for WAL tracking to
// meet the needs of different use cases, durability levels and recovery modes.
TEST_F(DBBasicTest, DISABLED_ManualWalSync) {
Options options = CurrentOptions();
options.track_and_verify_wals_in_manifest = true;
options.wal_recovery_mode = WALRecoveryMode::kAbsoluteConsistency;
+10 -5
View File
@@ -156,7 +156,9 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname,
bool read_only)
: dbname_(dbname),
own_info_log_(options.info_log == nullptr),
initial_db_options_(SanitizeOptions(dbname, options, read_only)),
init_logger_creation_s_(),
initial_db_options_(SanitizeOptions(dbname, options, read_only,
&init_logger_creation_s_)),
env_(initial_db_options_.env),
io_tracer_(std::make_shared<IOTracer>()),
immutable_db_options_(initial_db_options_),
@@ -747,6 +749,9 @@ Status DBImpl::CloseHelper() {
Status DBImpl::CloseImpl() { return CloseHelper(); }
DBImpl::~DBImpl() {
// TODO: remove this.
init_logger_creation_s_.PermitUncheckedError();
InstrumentedMutexLock closing_lock_guard(&closing_mutex_);
if (closed_) {
return;
@@ -1471,12 +1476,12 @@ Status DBImpl::MarkLogsSynced(uint64_t up_to, bool synced_dir) {
for (auto it = logs_.begin(); it != logs_.end() && it->number <= up_to;) {
auto& wal = *it;
assert(wal.IsSyncing());
if (immutable_db_options_.track_and_verify_wals_in_manifest &&
wal.GetPreSyncSize() > 0) {
synced_wals.AddWal(wal.number, WalMetadata(wal.GetPreSyncSize()));
}
if (logs_.size() > 1) {
if (immutable_db_options_.track_and_verify_wals_in_manifest &&
wal.GetPreSyncSize() > 0) {
synced_wals.AddWal(wal.number, WalMetadata(wal.GetPreSyncSize()));
}
logs_to_free_.push_back(wal.ReleaseWriter());
// To modify logs_ both mutex_ and log_write_mutex_ must be held
InstrumentedMutexLock l(&log_write_mutex_);
+5 -2
View File
@@ -1248,6 +1248,7 @@ class DBImpl : public DB {
std::unique_ptr<VersionSet> versions_;
// Flag to check whether we allocated and own the info log file
bool own_info_log_;
Status init_logger_creation_s_;
const DBOptions initial_db_options_;
Env* const env_;
std::shared_ptr<IOTracer> io_tracer_;
@@ -2590,10 +2591,12 @@ class GetWithTimestampReadCallback : public ReadCallback {
};
extern Options SanitizeOptions(const std::string& db, const Options& src,
bool read_only = false);
bool read_only = false,
Status* logger_creation_s = nullptr);
extern DBOptions SanitizeOptions(const std::string& db, const DBOptions& src,
bool read_only = false);
bool read_only = false,
Status* logger_creation_s = nullptr);
extern CompressionType GetCompressionFlush(
const ImmutableCFOptions& ioptions,
+10 -4
View File
@@ -27,8 +27,9 @@
namespace ROCKSDB_NAMESPACE {
Options SanitizeOptions(const std::string& dbname, const Options& src,
bool read_only) {
auto db_options = SanitizeOptions(dbname, DBOptions(src), read_only);
bool read_only, Status* logger_creation_s) {
auto db_options =
SanitizeOptions(dbname, DBOptions(src), read_only, logger_creation_s);
ImmutableDBOptions immutable_db_options(db_options);
auto cf_options =
SanitizeOptions(immutable_db_options, ColumnFamilyOptions(src));
@@ -36,7 +37,7 @@ Options SanitizeOptions(const std::string& dbname, const Options& src,
}
DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src,
bool read_only) {
bool read_only, Status* logger_creation_s) {
DBOptions result(src);
if (result.env == nullptr) {
@@ -59,6 +60,9 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src,
if (!s.ok()) {
// No place suitable for logging
result.info_log = nullptr;
if (logger_creation_s) {
*logger_creation_s = s;
}
}
}
@@ -1747,9 +1751,11 @@ Status DBImpl::Open(const DBOptions& db_options, const std::string& dbname,
DBImpl* impl = new DBImpl(db_options, dbname, seq_per_batch, batch_per_txn);
if (!impl->immutable_db_options_.info_log) {
s = Status::Aborted("Failed to create logger");
s = impl->init_logger_creation_s_;
delete impl;
return s;
} else {
assert(impl->init_logger_creation_s_.ok());
}
s = impl->env_->CreateDirIfMissing(impl->immutable_db_options_.GetWalDir());
if (s.ok()) {
+1
View File
@@ -157,6 +157,7 @@ DECLARE_bool(partition_filters);
DECLARE_bool(optimize_filters_for_memory);
DECLARE_bool(detect_filter_construct_corruption);
DECLARE_int32(index_type);
DECLARE_int32(data_block_index_type);
DECLARE_string(db);
DECLARE_string(secondaries_base);
DECLARE_bool(test_secondary);
+7 -1
View File
@@ -493,9 +493,15 @@ DEFINE_bool(
DEFINE_int32(
index_type,
static_cast<int32_t>(
ROCKSDB_NAMESPACE::BlockBasedTableOptions::kBinarySearch),
ROCKSDB_NAMESPACE::BlockBasedTableOptions().index_type),
"Type of block-based table index (see `enum IndexType` in table.h)");
DEFINE_int32(
data_block_index_type,
static_cast<int32_t>(
ROCKSDB_NAMESPACE::BlockBasedTableOptions().data_block_index_type),
"Index type for data blocks (see `enum DataBlockIndexType` in table.h)");
DEFINE_string(db, "", "Use the db with the following name.");
DEFINE_string(secondaries_base, "",
+3
View File
@@ -2775,6 +2775,9 @@ void InitializeOptionsFromFlags(
FLAGS_detect_filter_construct_corruption;
block_based_options.index_type =
static_cast<BlockBasedTableOptions::IndexType>(FLAGS_index_type);
block_based_options.data_block_index_type =
static_cast<BlockBasedTableOptions::DataBlockIndexType>(
FLAGS_data_block_index_type);
block_based_options.prepopulate_block_cache =
static_cast<BlockBasedTableOptions::PrepopulateBlockCache>(
FLAGS_prepopulate_block_cache);
+7 -1
View File
@@ -483,11 +483,17 @@ struct DBOptions {
bool flush_verify_memtable_count = true;
// If true, the log numbers and sizes of the synced WALs are tracked
// in MANIFEST, then during DB recovery, if a synced WAL is missing
// in MANIFEST. During DB recovery, if a synced WAL is missing
// from disk, or the WAL's size does not match the recorded size in
// MANIFEST, an error will be reported and the recovery will be aborted.
//
// This is one additional protection against WAL corruption besides the
// per-WAL-entry checksum.
//
// Note that this option does not work with secondary instance.
// Currently, only syncing closed WALs are tracked. Calling `DB::SyncWAL()`,
// etc. or writing with `WriteOptions::sync=true` to sync the live WAL is not
// tracked for performance/efficiency reasons.
//
// Default: false
bool track_and_verify_wals_in_manifest = false;
+1 -1
View File
@@ -13,7 +13,7 @@
// minor or major version number planned for release.
#define ROCKSDB_MAJOR 7
#define ROCKSDB_MINOR 4
#define ROCKSDB_PATCH 0
#define ROCKSDB_PATCH 3
// Do not use these. We made the mistake of declaring macros starting with
// double underscore. Now we have to live with our choice. We'll deprecate these
+12 -2
View File
@@ -278,11 +278,21 @@ Status CreateLoggerFromOptions(const std::string& dbname,
InfoLogFileName(dbname, db_absolute_path, options.db_log_dir);
const auto& clock = env->GetSystemClock();
// In case it does not exist
// In case it does not exist.
s = env->CreateDirIfMissing(dbname);
if (!s.ok()) {
return s;
if (options.db_log_dir.empty()) {
return s;
} else {
// Ignore the error returned during creation of dbname because dbname and
// db_log_dir can be on different filesystems in which case dbname will
// not exist and error should be ignored. db_log_dir creation will handle
// the error in case there is any error in the creation of dbname on same
// filesystem.
s = Status::OK();
}
}
assert(s.ok());
if (!options.db_log_dir.empty()) {
s = env->CreateDirIfMissing(options.db_log_dir);
+16 -9
View File
@@ -1902,7 +1902,8 @@ bool BlockBasedTable::PrefixRangeMayMatch(
may_match = filter->RangeMayExist(
read_options.iterate_upper_bound, user_key_without_ts, prefix_extractor,
rep_->internal_comparator.user_comparator(), const_ikey_ptr,
&filter_checked, need_upper_bound_check, no_io, lookup_context);
&filter_checked, need_upper_bound_check, no_io, lookup_context,
read_options.rate_limiter_priority);
}
if (filter_checked) {
@@ -1974,7 +1975,8 @@ FragmentedRangeTombstoneIterator* BlockBasedTable::NewRangeTombstoneIterator(
bool BlockBasedTable::FullFilterKeyMayMatch(
FilterBlockReader* filter, const Slice& internal_key, const bool no_io,
const SliceTransform* prefix_extractor, GetContext* get_context,
BlockCacheLookupContext* lookup_context) const {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const {
if (filter == nullptr) {
return true;
}
@@ -1984,13 +1986,15 @@ bool BlockBasedTable::FullFilterKeyMayMatch(
size_t ts_sz = rep_->internal_comparator.user_comparator()->timestamp_size();
Slice user_key_without_ts = StripTimestampFromUserKey(user_key, ts_sz);
if (rep_->whole_key_filtering) {
may_match = filter->KeyMayMatch(user_key_without_ts, no_io, const_ikey_ptr,
get_context, lookup_context);
may_match =
filter->KeyMayMatch(user_key_without_ts, no_io, const_ikey_ptr,
get_context, lookup_context, rate_limiter_priority);
} else if (!PrefixExtractorChanged(prefix_extractor) &&
prefix_extractor->InDomain(user_key_without_ts) &&
!filter->PrefixMayMatch(
prefix_extractor->Transform(user_key_without_ts), no_io,
const_ikey_ptr, get_context, lookup_context)) {
const_ikey_ptr, get_context, lookup_context,
rate_limiter_priority)) {
// FIXME ^^^: there should be no reason for Get() to depend on current
// prefix_extractor at all. It should always use table_prefix_extractor.
may_match = false;
@@ -2005,14 +2009,15 @@ bool BlockBasedTable::FullFilterKeyMayMatch(
void BlockBasedTable::FullFilterKeysMayMatch(
FilterBlockReader* filter, MultiGetRange* range, const bool no_io,
const SliceTransform* prefix_extractor,
BlockCacheLookupContext* lookup_context) const {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const {
if (filter == nullptr) {
return;
}
uint64_t before_keys = range->KeysLeft();
assert(before_keys > 0); // Caller should ensure
if (rep_->whole_key_filtering) {
filter->KeysMayMatch(range, no_io, lookup_context);
filter->KeysMayMatch(range, no_io, lookup_context, rate_limiter_priority);
uint64_t after_keys = range->KeysLeft();
if (after_keys) {
RecordTick(rep_->ioptions.stats, BLOOM_FILTER_FULL_POSITIVE, after_keys);
@@ -2028,7 +2033,8 @@ void BlockBasedTable::FullFilterKeysMayMatch(
} else if (!PrefixExtractorChanged(prefix_extractor)) {
// FIXME ^^^: there should be no reason for MultiGet() to depend on current
// prefix_extractor at all. It should always use table_prefix_extractor.
filter->PrefixesMayMatch(range, prefix_extractor, false, lookup_context);
filter->PrefixesMayMatch(range, prefix_extractor, false, lookup_context,
rate_limiter_priority);
RecordTick(rep_->ioptions.stats, BLOOM_FILTER_PREFIX_CHECKED, before_keys);
uint64_t after_keys = range->KeysLeft();
uint64_t filtered_keys = before_keys - after_keys;
@@ -2065,7 +2071,8 @@ Status BlockBasedTable::Get(const ReadOptions& read_options, const Slice& key,
}
TEST_SYNC_POINT("BlockBasedTable::Get:BeforeFilterMatch");
const bool may_match = FullFilterKeyMayMatch(
filter, key, no_io, prefix_extractor, get_context, &lookup_context);
filter, key, no_io, prefix_extractor, get_context, &lookup_context,
read_options.rate_limiter_priority);
TEST_SYNC_POINT("BlockBasedTable::Get:AfterFilterMatch");
if (!may_match) {
RecordTick(rep_->ioptions.stats, BLOOM_FILTER_USEFUL);
+4 -2
View File
@@ -454,12 +454,14 @@ class BlockBasedTable : public TableReader {
const bool no_io,
const SliceTransform* prefix_extractor,
GetContext* get_context,
BlockCacheLookupContext* lookup_context) const;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const;
void FullFilterKeysMayMatch(FilterBlockReader* filter, MultiGetRange* range,
const bool no_io,
const SliceTransform* prefix_extractor,
BlockCacheLookupContext* lookup_context) const;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const;
// If force_direct_prefetch is true, always prefetching to RocksDB
// buffer, rather than calling RandomAccessFile::Prefetch().
@@ -335,7 +335,7 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
TableReaderCaller::kUserMultiGet, tracing_mget_id,
/*_get_from_user_specified_snapshot=*/read_options.snapshot != nullptr};
FullFilterKeysMayMatch(filter, &sst_file_range, no_io, prefix_extractor,
&lookup_context);
&lookup_context, read_options.rate_limiter_priority);
if (!sst_file_range.empty()) {
IndexBlockIter iiter_on_stack;
@@ -610,15 +610,6 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
break;
}
bool may_exist = biter->SeekForGet(key);
if (!may_exist) {
// HashSeek cannot find the key this block and the the iter is not
// the end of the block, i.e. cannot be in the following blocks
// either. In this case, the seek_key cannot be found, so we break
// from the top level for-loop.
break;
}
// Reusing blocks complicates pinning/Cleanable, because the cache
// entry referenced by biter can only be released once all returned
// pinned values are released. This code previously did an extra
@@ -661,6 +652,15 @@ DEFINE_SYNC_AND_ASYNC(void, BlockBasedTable::MultiGet)
value_pinner = nullptr;
}
bool may_exist = biter->SeekForGet(key);
if (!may_exist) {
// HashSeek cannot find the key this block and the the iter is not
// the end of the block, i.e. cannot be in the following blocks
// either. In this case, the seek_key cannot be found, so we break
// from the top level for-loop.
break;
}
// Call the *saver function on each entry/block until it returns false
for (; biter->Valid(); biter->Next()) {
ParsedInternalKey parsed_key;
+13 -7
View File
@@ -112,16 +112,18 @@ class FilterBlockReader {
virtual bool KeyMayMatch(const Slice& key, const bool no_io,
const Slice* const const_ikey_ptr,
GetContext* get_context,
BlockCacheLookupContext* lookup_context) = 0;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) = 0;
virtual void KeysMayMatch(MultiGetRange* range, const bool no_io,
BlockCacheLookupContext* lookup_context) {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
for (auto iter = range->begin(); iter != range->end(); ++iter) {
const Slice ukey_without_ts = iter->ukey_without_ts;
const Slice ikey = iter->ikey;
GetContext* const get_context = iter->get_context;
if (!KeyMayMatch(ukey_without_ts, no_io, &ikey, get_context,
lookup_context)) {
lookup_context, rate_limiter_priority)) {
range->SkipKey(iter);
}
}
@@ -133,19 +135,22 @@ class FilterBlockReader {
virtual bool PrefixMayMatch(const Slice& prefix, const bool no_io,
const Slice* const const_ikey_ptr,
GetContext* get_context,
BlockCacheLookupContext* lookup_context) = 0;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) = 0;
virtual void PrefixesMayMatch(MultiGetRange* range,
const SliceTransform* prefix_extractor,
const bool no_io,
BlockCacheLookupContext* lookup_context) {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
for (auto iter = range->begin(); iter != range->end(); ++iter) {
const Slice ukey_without_ts = iter->ukey_without_ts;
const Slice ikey = iter->ikey;
GetContext* const get_context = iter->get_context;
if (prefix_extractor->InDomain(ukey_without_ts) &&
!PrefixMayMatch(prefix_extractor->Transform(ukey_without_ts), no_io,
&ikey, get_context, lookup_context)) {
&ikey, get_context, lookup_context,
rate_limiter_priority)) {
range->SkipKey(iter);
}
}
@@ -170,7 +175,8 @@ class FilterBlockReader {
const Slice* const const_ikey_ptr,
bool* filter_checked, bool need_upper_bound_check,
bool no_io,
BlockCacheLookupContext* lookup_context) = 0;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) = 0;
};
} // namespace ROCKSDB_NAMESPACE
@@ -67,7 +67,8 @@ template <typename TBlocklike>
Status FilterBlockReaderCommon<TBlocklike>::GetOrReadFilterBlock(
bool no_io, GetContext* get_context,
BlockCacheLookupContext* lookup_context,
CachableEntry<TBlocklike>* filter_block, BlockType block_type) const {
CachableEntry<TBlocklike>* filter_block, BlockType block_type,
Env::IOPriority rate_limiter_priority) const {
assert(filter_block);
if (!filter_block_.IsEmpty()) {
@@ -76,6 +77,7 @@ Status FilterBlockReaderCommon<TBlocklike>::GetOrReadFilterBlock(
}
ReadOptions read_options;
read_options.rate_limiter_priority = rate_limiter_priority;
if (no_io) {
read_options.read_tier = kBlockCacheTier;
}
@@ -100,7 +102,8 @@ bool FilterBlockReaderCommon<TBlocklike>::RangeMayExist(
const SliceTransform* prefix_extractor, const Comparator* comparator,
const Slice* const const_ikey_ptr, bool* filter_checked,
bool need_upper_bound_check, bool no_io,
BlockCacheLookupContext* lookup_context) {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
if (!prefix_extractor || !prefix_extractor->InDomain(user_key_without_ts)) {
*filter_checked = false;
return true;
@@ -113,7 +116,8 @@ bool FilterBlockReaderCommon<TBlocklike>::RangeMayExist(
} else {
*filter_checked = true;
return PrefixMayMatch(prefix, no_io, const_ikey_ptr,
/* get_context */ nullptr, lookup_context);
/* get_context */ nullptr, lookup_context,
rate_limiter_priority);
}
}
@@ -40,7 +40,8 @@ class FilterBlockReaderCommon : public FilterBlockReader {
const Comparator* comparator,
const Slice* const const_ikey_ptr, bool* filter_checked,
bool need_upper_bound_check, bool no_io,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
protected:
static Status ReadFilterBlock(const BlockBasedTable* table,
@@ -59,7 +60,8 @@ class FilterBlockReaderCommon : public FilterBlockReader {
Status GetOrReadFilterBlock(bool no_io, GetContext* get_context,
BlockCacheLookupContext* lookup_context,
CachableEntry<TBlocklike>* filter_block,
BlockType block_type) const;
BlockType block_type,
Env::IOPriority rate_limiter_priority) const;
size_t ApproximateFilterBlockMemoryUsage() const;
+28 -17
View File
@@ -124,13 +124,16 @@ FullFilterBlockReader::FullFilterBlockReader(
: FilterBlockReaderCommon(t, std::move(filter_block)) {
}
bool FullFilterBlockReader::KeyMayMatch(
const Slice& key, const bool no_io, const Slice* const /*const_ikey_ptr*/,
GetContext* get_context, BlockCacheLookupContext* lookup_context) {
bool FullFilterBlockReader::KeyMayMatch(const Slice& key, const bool no_io,
const Slice* const /*const_ikey_ptr*/,
GetContext* get_context,
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
if (!whole_key_filtering()) {
return true;
}
return MayMatch(key, no_io, get_context, lookup_context);
return MayMatch(key, no_io, get_context, lookup_context,
rate_limiter_priority);
}
std::unique_ptr<FilterBlockReader> FullFilterBlockReader::Create(
@@ -163,17 +166,21 @@ std::unique_ptr<FilterBlockReader> FullFilterBlockReader::Create(
bool FullFilterBlockReader::PrefixMayMatch(
const Slice& prefix, const bool no_io,
const Slice* const /*const_ikey_ptr*/, GetContext* get_context,
BlockCacheLookupContext* lookup_context) {
return MayMatch(prefix, no_io, get_context, lookup_context);
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
return MayMatch(prefix, no_io, get_context, lookup_context,
rate_limiter_priority);
}
bool FullFilterBlockReader::MayMatch(
const Slice& entry, bool no_io, GetContext* get_context,
BlockCacheLookupContext* lookup_context) const {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const {
CachableEntry<ParsedFullFilterBlock> filter_block;
const Status s = GetOrReadFilterBlock(no_io, get_context, lookup_context,
&filter_block, BlockType::kFilter);
const Status s =
GetOrReadFilterBlock(no_io, get_context, lookup_context, &filter_block,
BlockType::kFilter, rate_limiter_priority);
if (!s.ok()) {
IGNORE_STATUS_IF_ERROR(s);
return true;
@@ -198,29 +205,33 @@ bool FullFilterBlockReader::MayMatch(
void FullFilterBlockReader::KeysMayMatch(
MultiGetRange* range, const bool no_io,
BlockCacheLookupContext* lookup_context) {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
if (!whole_key_filtering()) {
// Simply return. Don't skip any key - consider all keys as likely to be
// present
return;
}
MayMatch(range, no_io, nullptr, lookup_context);
MayMatch(range, no_io, nullptr, lookup_context, rate_limiter_priority);
}
void FullFilterBlockReader::PrefixesMayMatch(
MultiGetRange* range, const SliceTransform* prefix_extractor,
const bool no_io, BlockCacheLookupContext* lookup_context) {
MayMatch(range, no_io, prefix_extractor, lookup_context);
const bool no_io, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
MayMatch(range, no_io, prefix_extractor, lookup_context,
rate_limiter_priority);
}
void FullFilterBlockReader::MayMatch(
MultiGetRange* range, bool no_io, const SliceTransform* prefix_extractor,
BlockCacheLookupContext* lookup_context) const {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const {
CachableEntry<ParsedFullFilterBlock> filter_block;
const Status s =
GetOrReadFilterBlock(no_io, range->begin()->get_context, lookup_context,
&filter_block, BlockType::kFilter);
const Status s = GetOrReadFilterBlock(
no_io, range->begin()->get_context, lookup_context, &filter_block,
BlockType::kFilter, rate_limiter_priority);
if (!s.ok()) {
IGNORE_STATUS_IF_ERROR(s);
return;
+15 -9
View File
@@ -107,34 +107,40 @@ class FullFilterBlockReader
bool KeyMayMatch(const Slice& key, const bool no_io,
const Slice* const const_ikey_ptr, GetContext* get_context,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
bool PrefixMayMatch(const Slice& prefix, const bool no_io,
const Slice* const const_ikey_ptr,
GetContext* get_context,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
void KeysMayMatch(MultiGetRange* range, const bool no_io,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
// Used in partitioned filter code
void KeysMayMatch2(MultiGetRange* range,
const SliceTransform* /*prefix_extractor*/,
const bool no_io,
BlockCacheLookupContext* lookup_context) {
KeysMayMatch(range, no_io, lookup_context);
const bool no_io, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
KeysMayMatch(range, no_io, lookup_context, rate_limiter_priority);
}
void PrefixesMayMatch(MultiGetRange* range,
const SliceTransform* prefix_extractor,
const bool no_io,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
size_t ApproximateMemoryUsage() const override;
private:
bool MayMatch(const Slice& entry, bool no_io, GetContext* get_context,
BlockCacheLookupContext* lookup_context) const;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const;
void MayMatch(MultiGetRange* range, bool no_io,
const SliceTransform* prefix_extractor,
BlockCacheLookupContext* lookup_context) const;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) const;
};
} // namespace ROCKSDB_NAMESPACE
+32 -16
View File
@@ -118,7 +118,7 @@ TEST_F(PluginFullFilterBlockTest, PluginEmptyBuilder) {
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr, Env::IO_TOTAL));
}
TEST_F(PluginFullFilterBlockTest, PluginSingleChunk) {
@@ -136,34 +136,42 @@ TEST_F(PluginFullFilterBlockTest, PluginSingleChunk) {
nullptr /* cache */, nullptr /* cache_handle */, true /* own_value */);
FullFilterBlockReader reader(table_.get(), std::move(block));
Env::IOPriority rate_limiter_priority = Env::IO_TOTAL;
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("bar",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("box",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("hello",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(!reader.KeyMayMatch("missing",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(!reader.KeyMayMatch("other",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
class FullFilterBlockTest : public mock::MockBlockBasedTableTester,
@@ -188,7 +196,7 @@ TEST_F(FullFilterBlockTest, EmptyBuilder) {
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr, Env::IO_TOTAL));
}
class CountUniqueFilterBitsBuilderWrapper : public FilterBitsBuilder {
@@ -285,34 +293,42 @@ TEST_F(FullFilterBlockTest, SingleChunk) {
nullptr /* cache */, nullptr /* cache_handle */, true /* own_value */);
FullFilterBlockReader reader(table_.get(), std::move(block));
Env::IOPriority rate_limiter_priority = Env::IO_TOTAL;
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("bar",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("box",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("hello",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(reader.KeyMayMatch("foo",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(!reader.KeyMayMatch("missing",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
ASSERT_TRUE(!reader.KeyMayMatch("other",
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
} // namespace ROCKSDB_NAMESPACE
+28 -18
View File
@@ -217,41 +217,46 @@ std::unique_ptr<FilterBlockReader> PartitionedFilterBlockReader::Create(
bool PartitionedFilterBlockReader::KeyMayMatch(
const Slice& key, const bool no_io, const Slice* const const_ikey_ptr,
GetContext* get_context, BlockCacheLookupContext* lookup_context) {
GetContext* get_context, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
assert(const_ikey_ptr != nullptr);
if (!whole_key_filtering()) {
return true;
}
return MayMatch(key, no_io, const_ikey_ptr, get_context, lookup_context,
&FullFilterBlockReader::KeyMayMatch);
rate_limiter_priority, &FullFilterBlockReader::KeyMayMatch);
}
void PartitionedFilterBlockReader::KeysMayMatch(
MultiGetRange* range, const bool no_io,
BlockCacheLookupContext* lookup_context) {
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
if (!whole_key_filtering()) {
return; // Any/all may match
}
MayMatch(range, nullptr, no_io, lookup_context,
MayMatch(range, nullptr, no_io, lookup_context, rate_limiter_priority,
&FullFilterBlockReader::KeysMayMatch2);
}
bool PartitionedFilterBlockReader::PrefixMayMatch(
const Slice& prefix, const bool no_io, const Slice* const const_ikey_ptr,
GetContext* get_context, BlockCacheLookupContext* lookup_context) {
GetContext* get_context, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
assert(const_ikey_ptr != nullptr);
return MayMatch(prefix, no_io, const_ikey_ptr, get_context, lookup_context,
rate_limiter_priority,
&FullFilterBlockReader::PrefixMayMatch);
}
void PartitionedFilterBlockReader::PrefixesMayMatch(
MultiGetRange* range, const SliceTransform* prefix_extractor,
const bool no_io, BlockCacheLookupContext* lookup_context) {
const bool no_io, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) {
assert(prefix_extractor);
MayMatch(range, prefix_extractor, no_io, lookup_context,
&FullFilterBlockReader::PrefixesMayMatch);
rate_limiter_priority, &FullFilterBlockReader::PrefixesMayMatch);
}
BlockHandle PartitionedFilterBlockReader::GetFilterPartitionHandle(
@@ -316,11 +321,12 @@ Status PartitionedFilterBlockReader::GetFilterPartitionBlock(
bool PartitionedFilterBlockReader::MayMatch(
const Slice& slice, bool no_io, const Slice* const_ikey_ptr,
GetContext* get_context, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterFunction filter_function) const {
CachableEntry<Block> filter_block;
Status s =
GetOrReadFilterBlock(no_io, get_context, lookup_context, &filter_block,
BlockType::kFilterPartitionIndex);
Status s = GetOrReadFilterBlock(
no_io, get_context, lookup_context, &filter_block,
BlockType::kFilterPartitionIndex, rate_limiter_priority);
if (UNLIKELY(!s.ok())) {
IGNORE_STATUS_IF_ERROR(s);
return true;
@@ -347,17 +353,19 @@ bool PartitionedFilterBlockReader::MayMatch(
FullFilterBlockReader filter_partition(table(),
std::move(filter_partition_block));
return (filter_partition.*filter_function)(slice, no_io, const_ikey_ptr,
get_context, lookup_context);
get_context, lookup_context,
rate_limiter_priority);
}
void PartitionedFilterBlockReader::MayMatch(
MultiGetRange* range, const SliceTransform* prefix_extractor, bool no_io,
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterManyFunction filter_function) const {
CachableEntry<Block> filter_block;
Status s =
GetOrReadFilterBlock(no_io, range->begin()->get_context, lookup_context,
&filter_block, BlockType::kFilterPartitionIndex);
Status s = GetOrReadFilterBlock(
no_io, range->begin()->get_context, lookup_context, &filter_block,
BlockType::kFilterPartitionIndex, rate_limiter_priority);
if (UNLIKELY(!s.ok())) {
IGNORE_STATUS_IF_ERROR(s);
return; // Any/all may match
@@ -381,7 +389,7 @@ void PartitionedFilterBlockReader::MayMatch(
this_filter_handle != prev_filter_handle) {
MultiGetRange subrange(*range, start_iter_same_handle, iter);
MayMatchPartition(&subrange, prefix_extractor, prev_filter_handle, no_io,
lookup_context, filter_function);
lookup_context, rate_limiter_priority, filter_function);
range->AddSkipsFrom(subrange);
start_iter_same_handle = iter;
}
@@ -397,7 +405,7 @@ void PartitionedFilterBlockReader::MayMatch(
if (!prev_filter_handle.IsNull()) {
MultiGetRange subrange(*range, start_iter_same_handle, range->end());
MayMatchPartition(&subrange, prefix_extractor, prev_filter_handle, no_io,
lookup_context, filter_function);
lookup_context, rate_limiter_priority, filter_function);
range->AddSkipsFrom(subrange);
}
}
@@ -406,6 +414,7 @@ void PartitionedFilterBlockReader::MayMatchPartition(
MultiGetRange* range, const SliceTransform* prefix_extractor,
BlockHandle filter_handle, bool no_io,
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterManyFunction filter_function) const {
CachableEntry<ParsedFullFilterBlock> filter_partition_block;
Status s = GetFilterPartitionBlock(
@@ -419,7 +428,7 @@ void PartitionedFilterBlockReader::MayMatchPartition(
FullFilterBlockReader filter_partition(table(),
std::move(filter_partition_block));
(filter_partition.*filter_function)(range, prefix_extractor, no_io,
lookup_context);
lookup_context, rate_limiter_priority);
}
size_t PartitionedFilterBlockReader::ApproximateMemoryUsage() const {
@@ -447,7 +456,8 @@ Status PartitionedFilterBlockReader::CacheDependencies(const ReadOptions& ro,
Status s = GetOrReadFilterBlock(false /* no_io */, nullptr /* get_context */,
&lookup_context, &filter_block,
BlockType::kFilterPartitionIndex);
BlockType::kFilterPartitionIndex,
ro.rate_limiter_priority);
if (!s.ok()) {
ROCKS_LOG_ERROR(rep->ioptions.logger,
"Error retrieving top-level filter block while trying to "
+15 -6
View File
@@ -111,18 +111,22 @@ class PartitionedFilterBlockReader : public FilterBlockReaderCommon<Block> {
bool KeyMayMatch(const Slice& key, const bool no_io,
const Slice* const const_ikey_ptr, GetContext* get_context,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
void KeysMayMatch(MultiGetRange* range, const bool no_io,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
bool PrefixMayMatch(const Slice& prefix, const bool no_io,
const Slice* const const_ikey_ptr,
GetContext* get_context,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
void PrefixesMayMatch(MultiGetRange* range,
const SliceTransform* prefix_extractor,
const bool no_io,
BlockCacheLookupContext* lookup_context) override;
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority) override;
size_t ApproximateMemoryUsage() const override;
@@ -137,21 +141,26 @@ class PartitionedFilterBlockReader : public FilterBlockReaderCommon<Block> {
using FilterFunction = bool (FullFilterBlockReader::*)(
const Slice& slice, const bool no_io, const Slice* const const_ikey_ptr,
GetContext* get_context, BlockCacheLookupContext* lookup_context);
GetContext* get_context, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority);
bool MayMatch(const Slice& slice, bool no_io, const Slice* const_ikey_ptr,
GetContext* get_context,
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterFunction filter_function) const;
using FilterManyFunction = void (FullFilterBlockReader::*)(
MultiGetRange* range, const SliceTransform* prefix_extractor,
const bool no_io, BlockCacheLookupContext* lookup_context);
const bool no_io, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority);
void MayMatch(MultiGetRange* range, const SliceTransform* prefix_extractor,
bool no_io, BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterManyFunction filter_function) const;
void MayMatchPartition(MultiGetRange* range,
const SliceTransform* prefix_extractor,
BlockHandle filter_handle, bool no_io,
BlockCacheLookupContext* lookup_context,
Env::IOPriority rate_limiter_priority,
FilterManyFunction filter_function) const;
Status CacheDependencies(const ReadOptions& ro, bool pin) override;
@@ -164,6 +164,7 @@ class PartitionedFilterBlockTest
PartitionedIndexBuilder* pib, bool empty = false) {
std::unique_ptr<PartitionedFilterBlockReader> reader(
NewReader(builder, pib));
Env::IOPriority rate_limiter_priority = Env::IO_TOTAL;
// Querying added keys
const bool no_io = true;
for (auto key : keys) {
@@ -171,7 +172,8 @@ class PartitionedFilterBlockTest
const Slice ikey_slice = Slice(*ikey.rep());
ASSERT_TRUE(reader->KeyMayMatch(key, !no_io, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
{
// querying a key twice
@@ -179,7 +181,8 @@ class PartitionedFilterBlockTest
const Slice ikey_slice = Slice(*ikey.rep());
ASSERT_TRUE(reader->KeyMayMatch(keys[0], !no_io, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
// querying missing keys
for (auto key : missing_keys) {
@@ -188,12 +191,14 @@ class PartitionedFilterBlockTest
if (empty) {
ASSERT_TRUE(reader->KeyMayMatch(key, !no_io, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
} else {
// assuming a good hash function
ASSERT_FALSE(reader->KeyMayMatch(key, !no_io, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
}
}
@@ -345,7 +350,8 @@ TEST_P(PartitionedFilterBlockTest, SamePrefixInMultipleBlocks) {
ASSERT_TRUE(reader->PrefixMayMatch(prefix_extractor->Transform(key),
/*no_io=*/false, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
Env::IO_TOTAL));
}
// Non-existent keys but with the same prefix
const std::string pnonkeys[4] = {"p-key9", "p-key11", "p-key21", "p-key31"};
@@ -355,7 +361,8 @@ TEST_P(PartitionedFilterBlockTest, SamePrefixInMultipleBlocks) {
ASSERT_TRUE(reader->PrefixMayMatch(prefix_extractor->Transform(key),
/*no_io=*/false, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
Env::IO_TOTAL));
}
}
@@ -386,6 +393,7 @@ TEST_P(PartitionedFilterBlockTest, PrefixInWrongPartitionBug) {
CutABlock(pib.get(), pkeys[4]);
std::unique_ptr<PartitionedFilterBlockReader> reader(
NewReader(builder.get(), pib.get()));
Env::IOPriority rate_limiter_priority = Env::IO_TOTAL;
for (auto key : pkeys) {
auto prefix = prefix_extractor->Transform(key);
auto ikey = InternalKey(prefix, 0, ValueType::kTypeValue);
@@ -393,7 +401,8 @@ TEST_P(PartitionedFilterBlockTest, PrefixInWrongPartitionBug) {
ASSERT_TRUE(reader->PrefixMayMatch(prefix,
/*no_io=*/false, &ikey_slice,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr));
/*lookup_context=*/nullptr,
rate_limiter_priority));
}
}
+5
View File
@@ -1657,6 +1657,9 @@ DEFINE_uint32(write_batch_protection_bytes_per_key, 0,
"Size of per-key-value checksum in each write batch. Currently "
"only value 0 and 8 are supported.");
DEFINE_bool(track_and_verify_wals_in_manifest, false,
"If true, enable WAL tracking in the MANIFEST");
namespace ROCKSDB_NAMESPACE {
namespace {
static Status CreateMemTableRepFactory(
@@ -4459,6 +4462,8 @@ class Benchmark {
}
options.allow_data_in_errors = FLAGS_allow_data_in_errors;
options.track_and_verify_wals_in_manifest =
FLAGS_track_and_verify_wals_in_manifest;
// Integrated BlobDB
options.enable_blob_files = FLAGS_enable_blob_files;
+1
View File
@@ -63,6 +63,7 @@ default_params = {
"clear_column_family_one_in": 0,
"compact_files_one_in": 1000000,
"compact_range_one_in": 1000000,
"data_block_index_type": lambda: random.choice([0, 1]),
"delpercent": 4,
"delrangepercent": 1,
"destroy_db_initially": 0,
+3 -1
View File
@@ -20,6 +20,7 @@ int main() {
#include "port/port.h"
#include "port/stack_trace.h"
#include "rocksdb/cache.h"
#include "rocksdb/env.h"
#include "rocksdb/system_clock.h"
#include "rocksdb/table.h"
#include "table/block_based/filter_policy_internal.h"
@@ -150,6 +151,7 @@ using ROCKSDB_NAMESPACE::Cache;
using ROCKSDB_NAMESPACE::CacheEntryRole;
using ROCKSDB_NAMESPACE::CacheEntryRoleOptions;
using ROCKSDB_NAMESPACE::EncodeFixed32;
using ROCKSDB_NAMESPACE::Env;
using ROCKSDB_NAMESPACE::FastRange32;
using ROCKSDB_NAMESPACE::FilterBitsReader;
using ROCKSDB_NAMESPACE::FilterBuildingContext;
@@ -726,7 +728,7 @@ double FilterBench::RandomQueryTest(uint32_t inside_threshold, bool dry_run,
batch_slices[i],
/*no_io=*/false, /*const_ikey_ptr=*/nullptr,
/*get_context=*/nullptr,
/*lookup_context=*/nullptr);
/*lookup_context=*/nullptr, Env::IO_TOTAL);
}
} else {
if (dry_run) {
+1 -1
View File
@@ -3066,7 +3066,7 @@ TEST_F(BackupEngineTest, OpenBackupAsReadOnlyDB) {
db = nullptr;
// Now try opening read-write and make sure it fails, for safety.
ASSERT_TRUE(DB::Open(opts, name, &db).IsAborted());
ASSERT_TRUE(DB::Open(opts, name, &db).IsIOError());
}
TEST_F(BackupEngineTest, ProgressCallbackDuringBackup) {