Summary: Currently, when the block cache is used for the filter block, it is not really the block itself that is stored in the cache but a FilterBlockReader object. Since this object is not pure data (it has, for instance, pointers that might dangle, including in one case a back pointer to the TableReader), it's not really sharable. To avoid the issues around this, the current code erases the cache entries when the TableReader is closed (which, BTW, is not sufficient since a concurrent TableReader might have picked up the object in the meantime). Instead of doing this, the patch moves the FilterBlockReader out of the cache altogether, and decouples the filter reader object from the filter block. In particular, instead of the TableReader owning, or caching/pinning the FilterBlockReader (based on the customer's settings), with the change the TableReader unconditionally owns the FilterBlockReader, which in turn owns/caches/pins the filter block. This change also enables us to reuse the code paths historically used for data blocks for filters as well. Note: Eviction statistics for filter blocks are temporarily broken. We plan to fix this in a separate phase. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5504 Test Plan: make asan_check Differential Revision: D16036974 Pulled By: ltamasi fbshipit-source-id: 770f543c5fb4ed126fd1e04bfd3809cf4ff9c091
91 lines
2.9 KiB
C++
91 lines
2.9 KiB
C++
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
//
|
|
|
|
#include "table/block_based/filter_block_reader_common.h"
|
|
#include "monitoring/perf_context_imp.h"
|
|
#include "table/block_based/block_based_table_reader.h"
|
|
|
|
namespace rocksdb {
|
|
|
|
template <typename TBlocklike>
|
|
Status FilterBlockReaderCommon<TBlocklike>::ReadFilterBlock(
|
|
const BlockBasedTable* table, FilePrefetchBuffer* prefetch_buffer,
|
|
const ReadOptions& read_options, GetContext* get_context,
|
|
BlockCacheLookupContext* lookup_context,
|
|
CachableEntry<TBlocklike>* filter_block) {
|
|
PERF_TIMER_GUARD(read_filter_block_nanos);
|
|
|
|
assert(table);
|
|
assert(filter_block);
|
|
assert(filter_block->IsEmpty());
|
|
|
|
const BlockBasedTable::Rep* const rep = table->get_rep();
|
|
assert(rep);
|
|
|
|
const Status s =
|
|
table->RetrieveBlock(prefetch_buffer, read_options, rep->filter_handle,
|
|
UncompressionDict::GetEmptyDict(), filter_block,
|
|
BlockType::kFilter, get_context, lookup_context);
|
|
|
|
return s;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
const SliceTransform*
|
|
FilterBlockReaderCommon<TBlocklike>::table_prefix_extractor() const {
|
|
assert(table_);
|
|
|
|
const BlockBasedTable::Rep* const rep = table_->get_rep();
|
|
assert(rep);
|
|
|
|
return rep->prefix_filtering ? rep->table_prefix_extractor.get() : nullptr;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
bool FilterBlockReaderCommon<TBlocklike>::whole_key_filtering() const {
|
|
assert(table_);
|
|
assert(table_->get_rep());
|
|
|
|
return table_->get_rep()->whole_key_filtering;
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
Status FilterBlockReaderCommon<TBlocklike>::GetOrReadFilterBlock(
|
|
bool no_io, GetContext* get_context,
|
|
BlockCacheLookupContext* lookup_context,
|
|
CachableEntry<TBlocklike>* filter_block) const {
|
|
assert(filter_block);
|
|
|
|
if (!filter_block_.IsEmpty()) {
|
|
filter_block->SetUnownedValue(filter_block_.GetValue());
|
|
return Status::OK();
|
|
}
|
|
|
|
ReadOptions read_options;
|
|
if (no_io) {
|
|
read_options.read_tier = kBlockCacheTier;
|
|
}
|
|
|
|
return ReadFilterBlock(table_, nullptr /* prefetch_buffer */, read_options,
|
|
get_context, lookup_context, filter_block);
|
|
}
|
|
|
|
template <typename TBlocklike>
|
|
size_t FilterBlockReaderCommon<TBlocklike>::ApproximateFilterBlockMemoryUsage()
|
|
const {
|
|
assert(!filter_block_.GetOwnValue() || filter_block_.GetValue() != nullptr);
|
|
return filter_block_.GetOwnValue()
|
|
? filter_block_.GetValue()->ApproximateMemoryUsage()
|
|
: 0;
|
|
}
|
|
|
|
// 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>;
|
|
|
|
} // namespace rocksdb
|