//
#include "table/block_based/filter_block_reader_common.h"
+
#include "monitoring/perf_context_imp.h"
#include "table/block_based/block_based_table_reader.h"
#include "table/block_based/parsed_full_filter_block.h"
const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
const ReadOptions& read_options, bool use_cache, GetContext* get_context,
BlockCacheLookupContext* lookup_context,
- CachableEntry<TBlocklike>* filter_block) {
+ CachableEntry<TBlocklike>* filter_block, BlockType block_type) {
PERF_TIMER_GUARD(read_filter_block_nanos);
assert(table);
const Status s =
table->RetrieveBlock(prefetch_buffer, read_options, rep->filter_handle,
UncompressionDict::GetEmptyDict(), filter_block,
- BlockType::kFilter, get_context, lookup_context,
- /* for_compaction */ false, use_cache);
+ block_type, get_context, lookup_context,
+ /* for_compaction */ false, use_cache,
+ /* wait_for_cache */ true, /* async_read */ false);
return s;
}
Status FilterBlockReaderCommon<TBlocklike>::GetOrReadFilterBlock(
bool no_io, GetContext* get_context,
BlockCacheLookupContext* lookup_context,
- CachableEntry<TBlocklike>* filter_block) const {
+ CachableEntry<TBlocklike>* filter_block, BlockType block_type,
+ Env::IOPriority rate_limiter_priority) const {
assert(filter_block);
if (!filter_block_.IsEmpty()) {
}
ReadOptions read_options;
+ read_options.rate_limiter_priority = rate_limiter_priority;
if (no_io) {
read_options.read_tier = kBlockCacheTier;
}
return ReadFilterBlock(table_, nullptr /* prefetch_buffer */, read_options,
cache_filter_blocks(), get_context, lookup_context,
- filter_block);
+ filter_block, block_type);
}
template <typename TBlocklike>
: 0;
}
+template <typename TBlocklike>
+bool FilterBlockReaderCommon<TBlocklike>::RangeMayExist(
+ const Slice* iterate_upper_bound, const Slice& user_key_without_ts,
+ 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,
+ Env::IOPriority rate_limiter_priority) {
+ if (!prefix_extractor || !prefix_extractor->InDomain(user_key_without_ts)) {
+ *filter_checked = false;
+ return true;
+ }
+ Slice prefix = prefix_extractor->Transform(user_key_without_ts);
+ if (need_upper_bound_check &&
+ !IsFilterCompatible(iterate_upper_bound, prefix, comparator)) {
+ *filter_checked = false;
+ return true;
+ } else {
+ *filter_checked = true;
+ return PrefixMayMatch(prefix, no_io, const_ikey_ptr,
+ /* get_context */ nullptr, lookup_context,
+ rate_limiter_priority);
+ }
+}
+
+template <typename TBlocklike>
+bool FilterBlockReaderCommon<TBlocklike>::IsFilterCompatible(
+ const Slice* iterate_upper_bound, const Slice& prefix,
+ const Comparator* comparator) const {
+ // Try to reuse the bloom filter in the SST table if prefix_extractor in
+ // mutable_cf_options has changed. If range [user_key, upper_bound) all
+ // share the same prefix then we may still be able to use the bloom filter.
+ const SliceTransform* const prefix_extractor = table_prefix_extractor();
+ if (iterate_upper_bound != nullptr && prefix_extractor) {
+ if (!prefix_extractor->InDomain(*iterate_upper_bound)) {
+ return false;
+ }
+ Slice upper_bound_xform = prefix_extractor->Transform(*iterate_upper_bound);
+ // first check if user_key and upper_bound all share the same prefix
+ if (comparator->CompareWithoutTimestamp(prefix, false, upper_bound_xform,
+ false) != 0) {
+ // second check if user_key's prefix is the immediate predecessor of
+ // upper_bound and have the same length. If so, we know for sure all
+ // keys in the range [user_key, upper_bound) share the same prefix.
+ // Also need to make sure upper_bound are full length to ensure
+ // correctness
+ if (!full_length_enabled_ ||
+ iterate_upper_bound->size() != prefix_extractor_full_length_ ||
+ !comparator->IsSameLengthImmediateSuccessor(prefix,
+ *iterate_upper_bound)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
// Explicitly instantiate templates for both "blocklike" types we use.
// This makes it possible to keep the template definitions in the .cc file.
-template class FilterBlockReaderCommon<BlockContents>;
template class FilterBlockReaderCommon<Block>;
template class FilterBlockReaderCommon<ParsedFullFilterBlock>;