1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
10 // A filter block is stored near the end of a Table file. It contains
11 // filters (e.g., bloom filters) for all data blocks in the table combined
12 // into a single filter block.
23 #include "rocksdb/options.h"
24 #include "rocksdb/slice.h"
25 #include "rocksdb/slice_transform.h"
26 #include "rocksdb/table.h"
27 #include "table/format.h"
28 #include "table/multiget_context.h"
29 #include "trace_replay/block_cache_tracer.h"
30 #include "util/hash.h"
32 namespace ROCKSDB_NAMESPACE
{
34 const uint64_t kNotValid
= ULLONG_MAX
;
38 using MultiGetRange
= MultiGetContext::Range
;
40 // A FilterBlockBuilder is used to construct all of the filters for a
41 // particular Table. It generates a single string which is stored as
42 // a special block in the Table, or partitioned into smaller filters.
44 // The sequence of calls to FilterBlockBuilder must match the regexp:
46 class FilterBlockBuilder
{
48 explicit FilterBlockBuilder() {}
50 FilterBlockBuilder(const FilterBlockBuilder
&) = delete;
51 void operator=(const FilterBlockBuilder
&) = delete;
53 virtual ~FilterBlockBuilder() {}
56 const Slice
& key_without_ts
) = 0; // Add a key to current filter
57 virtual bool IsEmpty() const = 0; // Empty == none added
58 // For reporting stats on how many entries the builder considered unique
59 virtual size_t EstimateEntriesAdded() = 0;
60 Slice
Finish() { // Generate Filter
61 const BlockHandle empty_handle
;
62 Status dont_care_status
;
63 auto ret
= Finish(empty_handle
, &dont_care_status
);
64 assert(dont_care_status
.ok());
67 // If filter_data is not nullptr, Finish() may transfer ownership of
68 // underlying filter data to the caller, so that it can be freed as soon as
69 // possible. BlockBasedFilterBlock will ignore this parameter.
72 const BlockHandle
& tmp
/* only used in PartitionedFilterBlock as
73 last_partition_block_handle */
75 Status
* status
, std::unique_ptr
<const char[]>* filter_data
= nullptr) = 0;
77 // This is called when finishes using the FilterBitsBuilder
78 // in order to release memory usage and cache charge
79 // associated with it timely
80 virtual void ResetFilterBitsBuilder() {}
82 // To optionally post-verify the filter returned from
83 // FilterBlockBuilder::Finish.
84 // Return Status::OK() if skipped.
85 virtual Status
MaybePostVerifyFilter(const Slice
& /* filter_content */) {
90 // A FilterBlockReader is used to parse filter from SST table.
91 // KeyMayMatch and PrefixMayMatch would trigger filter checking
93 // BlockBased/Full FilterBlock would be called in the same way.
94 class FilterBlockReader
{
96 FilterBlockReader() = default;
97 virtual ~FilterBlockReader() = default;
99 FilterBlockReader(const FilterBlockReader
&) = delete;
100 FilterBlockReader
& operator=(const FilterBlockReader
&) = delete;
103 * If no_io is set, then it returns true if it cannot answer the query without
104 * reading data from disk. This is used in PartitionedFilterBlockReader to
105 * avoid reading partitions that are not in block cache already
107 * Normally filters are built on only the user keys and the InternalKey is not
108 * needed for a query. The index in PartitionedFilterBlockReader however is
109 * built upon InternalKey and must be provided via const_ikey_ptr when running
112 virtual bool KeyMayMatch(const Slice
& key
, const bool no_io
,
113 const Slice
* const const_ikey_ptr
,
114 GetContext
* get_context
,
115 BlockCacheLookupContext
* lookup_context
,
116 Env::IOPriority rate_limiter_priority
) = 0;
118 virtual void KeysMayMatch(MultiGetRange
* range
, const bool no_io
,
119 BlockCacheLookupContext
* lookup_context
,
120 Env::IOPriority rate_limiter_priority
) {
121 for (auto iter
= range
->begin(); iter
!= range
->end(); ++iter
) {
122 const Slice ukey_without_ts
= iter
->ukey_without_ts
;
123 const Slice ikey
= iter
->ikey
;
124 GetContext
* const get_context
= iter
->get_context
;
125 if (!KeyMayMatch(ukey_without_ts
, no_io
, &ikey
, get_context
,
126 lookup_context
, rate_limiter_priority
)) {
127 range
->SkipKey(iter
);
133 * no_io and const_ikey_ptr here means the same as in KeyMayMatch
135 virtual bool PrefixMayMatch(const Slice
& prefix
, const bool no_io
,
136 const Slice
* const const_ikey_ptr
,
137 GetContext
* get_context
,
138 BlockCacheLookupContext
* lookup_context
,
139 Env::IOPriority rate_limiter_priority
) = 0;
141 virtual void PrefixesMayMatch(MultiGetRange
* range
,
142 const SliceTransform
* prefix_extractor
,
144 BlockCacheLookupContext
* lookup_context
,
145 Env::IOPriority rate_limiter_priority
) {
146 for (auto iter
= range
->begin(); iter
!= range
->end(); ++iter
) {
147 const Slice ukey_without_ts
= iter
->ukey_without_ts
;
148 const Slice ikey
= iter
->ikey
;
149 GetContext
* const get_context
= iter
->get_context
;
150 if (prefix_extractor
->InDomain(ukey_without_ts
) &&
151 !PrefixMayMatch(prefix_extractor
->Transform(ukey_without_ts
), no_io
,
152 &ikey
, get_context
, lookup_context
,
153 rate_limiter_priority
)) {
154 range
->SkipKey(iter
);
159 virtual size_t ApproximateMemoryUsage() const = 0;
161 // convert this object to a human readable form
162 virtual std::string
ToString() const {
163 std::string
error_msg("Unsupported filter \n");
167 virtual Status
CacheDependencies(const ReadOptions
& /*ro*/, bool /*pin*/) {
171 virtual bool RangeMayExist(const Slice
* /*iterate_upper_bound*/,
172 const Slice
& user_key_without_ts
,
173 const SliceTransform
* prefix_extractor
,
174 const Comparator
* /*comparator*/,
175 const Slice
* const const_ikey_ptr
,
176 bool* filter_checked
, bool need_upper_bound_check
,
178 BlockCacheLookupContext
* lookup_context
,
179 Env::IOPriority rate_limiter_priority
) = 0;
182 } // namespace ROCKSDB_NAMESPACE