mirror of
https://github.com/facebook/rocksdb.git
synced 2026-07-08 07:05:23 +08:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 050027c35d | |||
| 41be9ec937 | |||
| 4fd1285584 | |||
| d74333c500 | |||
| 57adbf0e91 | |||
| 0b8c8cf13a | |||
| 1bee5e0254 | |||
| c79e43d0dc | |||
| c26abd4c25 |
+14
@@ -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.
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
@@ -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
@@ -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_);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, "",
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user