1 // Copyright (c) Facebook, Inc. and its affiliates. 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).
5
6 #pragma once
7
8 #include "cache/cache_entry_roles.h"
9 #include "port/lang.h"
10 #include "table/block_based/block.h"
11 #include "table/block_based/block_type.h"
12 #include "table/block_based/parsed_full_filter_block.h"
13 #include "table/format.h"
14
15 namespace ROCKSDB_NAMESPACE {
16
17 template <typename TBlocklike>
18 class BlocklikeTraits;
19
20 template <typename T, CacheEntryRole R>
21 Cache::CacheItemHelper* GetCacheItemHelperForRole();
22
23 template <typename TBlocklike>
GetCreateCallback(size_t read_amp_bytes_per_bit,Statistics * statistics,bool using_zstd,const FilterPolicy * filter_policy)24 Cache::CreateCallback GetCreateCallback(size_t read_amp_bytes_per_bit,
25 Statistics* statistics, bool using_zstd,
26 const FilterPolicy* filter_policy) {
27 return [read_amp_bytes_per_bit, statistics, using_zstd, filter_policy](
28 void* buf, size_t size, void** out_obj, size_t* charge) -> Status {
29 assert(buf != nullptr);
30 std::unique_ptr<char[]> buf_data(new char[size]());
31 memcpy(buf_data.get(), buf, size);
32 BlockContents bc = BlockContents(std::move(buf_data), size);
33 TBlocklike* ucd_ptr = BlocklikeTraits<TBlocklike>::Create(
34 std::move(bc), read_amp_bytes_per_bit, statistics, using_zstd,
35 filter_policy);
36 *out_obj = reinterpret_cast<void*>(ucd_ptr);
37 *charge = size;
38 return Status::OK();
39 };
40 }
41
42 template <>
43 class BlocklikeTraits<BlockContents> {
44 public:
Create(BlockContents && contents,size_t,Statistics *,bool,const FilterPolicy *)45 static BlockContents* Create(BlockContents&& contents,
46 size_t /* read_amp_bytes_per_bit */,
47 Statistics* /* statistics */,
48 bool /* using_zstd */,
49 const FilterPolicy* /* filter_policy */) {
50 return new BlockContents(std::move(contents));
51 }
52
GetNumRestarts(const BlockContents &)53 static uint32_t GetNumRestarts(const BlockContents& /* contents */) {
54 return 0;
55 }
56
SizeCallback(void * obj)57 static size_t SizeCallback(void* obj) {
58 assert(obj != nullptr);
59 BlockContents* ptr = static_cast<BlockContents*>(obj);
60 return ptr->data.size();
61 }
62
SaveToCallback(void * from_obj,size_t from_offset,size_t length,void * out)63 static Status SaveToCallback(void* from_obj, size_t from_offset,
64 size_t length, void* out) {
65 assert(from_obj != nullptr);
66 BlockContents* ptr = static_cast<BlockContents*>(from_obj);
67 const char* buf = ptr->data.data();
68 assert(length == ptr->data.size());
69 (void)from_offset;
70 memcpy(out, buf, length);
71 return Status::OK();
72 }
73
GetCacheItemHelper(BlockType block_type)74 static Cache::CacheItemHelper* GetCacheItemHelper(BlockType block_type) {
75 if (block_type == BlockType::kFilter) {
76 return GetCacheItemHelperForRole<
77 BlockContents, CacheEntryRole::kDeprecatedFilterBlock>();
78 } else {
79 // E.g. compressed cache
80 return GetCacheItemHelperForRole<BlockContents,
81 CacheEntryRole::kOtherBlock>();
82 }
83 }
84 };
85
86 template <>
87 class BlocklikeTraits<ParsedFullFilterBlock> {
88 public:
Create(BlockContents && contents,size_t,Statistics *,bool,const FilterPolicy * filter_policy)89 static ParsedFullFilterBlock* Create(BlockContents&& contents,
90 size_t /* read_amp_bytes_per_bit */,
91 Statistics* /* statistics */,
92 bool /* using_zstd */,
93 const FilterPolicy* filter_policy) {
94 return new ParsedFullFilterBlock(filter_policy, std::move(contents));
95 }
96
GetNumRestarts(const ParsedFullFilterBlock &)97 static uint32_t GetNumRestarts(const ParsedFullFilterBlock& /* block */) {
98 return 0;
99 }
100
SizeCallback(void * obj)101 static size_t SizeCallback(void* obj) {
102 assert(obj != nullptr);
103 ParsedFullFilterBlock* ptr = static_cast<ParsedFullFilterBlock*>(obj);
104 return ptr->GetBlockContentsData().size();
105 }
106
SaveToCallback(void * from_obj,size_t from_offset,size_t length,void * out)107 static Status SaveToCallback(void* from_obj, size_t from_offset,
108 size_t length, void* out) {
109 assert(from_obj != nullptr);
110 ParsedFullFilterBlock* ptr = static_cast<ParsedFullFilterBlock*>(from_obj);
111 const char* buf = ptr->GetBlockContentsData().data();
112 assert(length == ptr->GetBlockContentsData().size());
113 (void)from_offset;
114 memcpy(out, buf, length);
115 return Status::OK();
116 }
117
GetCacheItemHelper(BlockType block_type)118 static Cache::CacheItemHelper* GetCacheItemHelper(BlockType block_type) {
119 (void)block_type;
120 assert(block_type == BlockType::kFilter);
121 return GetCacheItemHelperForRole<ParsedFullFilterBlock,
122 CacheEntryRole::kFilterBlock>();
123 }
124 };
125
126 template <>
127 class BlocklikeTraits<Block> {
128 public:
Create(BlockContents && contents,size_t read_amp_bytes_per_bit,Statistics * statistics,bool,const FilterPolicy *)129 static Block* Create(BlockContents&& contents, size_t read_amp_bytes_per_bit,
130 Statistics* statistics, bool /* using_zstd */,
131 const FilterPolicy* /* filter_policy */) {
132 return new Block(std::move(contents), read_amp_bytes_per_bit, statistics);
133 }
134
GetNumRestarts(const Block & block)135 static uint32_t GetNumRestarts(const Block& block) {
136 return block.NumRestarts();
137 }
138
SizeCallback(void * obj)139 static size_t SizeCallback(void* obj) {
140 assert(obj != nullptr);
141 Block* ptr = static_cast<Block*>(obj);
142 return ptr->size();
143 }
144
SaveToCallback(void * from_obj,size_t from_offset,size_t length,void * out)145 static Status SaveToCallback(void* from_obj, size_t from_offset,
146 size_t length, void* out) {
147 assert(from_obj != nullptr);
148 Block* ptr = static_cast<Block*>(from_obj);
149 const char* buf = ptr->data();
150 assert(length == ptr->size());
151 (void)from_offset;
152 memcpy(out, buf, length);
153 return Status::OK();
154 }
155
GetCacheItemHelper(BlockType block_type)156 static Cache::CacheItemHelper* GetCacheItemHelper(BlockType block_type) {
157 switch (block_type) {
158 case BlockType::kData:
159 return GetCacheItemHelperForRole<Block, CacheEntryRole::kDataBlock>();
160 case BlockType::kIndex:
161 return GetCacheItemHelperForRole<Block, CacheEntryRole::kIndexBlock>();
162 case BlockType::kFilter:
163 return GetCacheItemHelperForRole<Block,
164 CacheEntryRole::kFilterMetaBlock>();
165 default:
166 // Not a recognized combination
167 assert(false);
168 FALLTHROUGH_INTENDED;
169 case BlockType::kRangeDeletion:
170 return GetCacheItemHelperForRole<Block, CacheEntryRole::kOtherBlock>();
171 }
172 }
173 };
174
175 template <>
176 class BlocklikeTraits<UncompressionDict> {
177 public:
Create(BlockContents && contents,size_t,Statistics *,bool using_zstd,const FilterPolicy *)178 static UncompressionDict* Create(BlockContents&& contents,
179 size_t /* read_amp_bytes_per_bit */,
180 Statistics* /* statistics */,
181 bool using_zstd,
182 const FilterPolicy* /* filter_policy */) {
183 return new UncompressionDict(contents.data, std::move(contents.allocation),
184 using_zstd);
185 }
186
GetNumRestarts(const UncompressionDict &)187 static uint32_t GetNumRestarts(const UncompressionDict& /* dict */) {
188 return 0;
189 }
190
SizeCallback(void * obj)191 static size_t SizeCallback(void* obj) {
192 assert(obj != nullptr);
193 UncompressionDict* ptr = static_cast<UncompressionDict*>(obj);
194 return ptr->slice_.size();
195 }
196
SaveToCallback(void * from_obj,size_t from_offset,size_t length,void * out)197 static Status SaveToCallback(void* from_obj, size_t from_offset,
198 size_t length, void* out) {
199 assert(from_obj != nullptr);
200 UncompressionDict* ptr = static_cast<UncompressionDict*>(from_obj);
201 const char* buf = ptr->slice_.data();
202 assert(length == ptr->slice_.size());
203 (void)from_offset;
204 memcpy(out, buf, length);
205 return Status::OK();
206 }
207
GetCacheItemHelper(BlockType block_type)208 static Cache::CacheItemHelper* GetCacheItemHelper(BlockType block_type) {
209 (void)block_type;
210 assert(block_type == BlockType::kCompressionDictionary);
211 return GetCacheItemHelperForRole<UncompressionDict,
212 CacheEntryRole::kOtherBlock>();
213 }
214 };
215
216 // Get an CacheItemHelper pointer for value type T and role R.
217 template <typename T, CacheEntryRole R>
GetCacheItemHelperForRole()218 Cache::CacheItemHelper* GetCacheItemHelperForRole() {
219 static Cache::CacheItemHelper cache_helper(
220 BlocklikeTraits<T>::SizeCallback, BlocklikeTraits<T>::SaveToCallback,
221 GetCacheEntryDeleterForRole<T, R>());
222 return &cache_helper;
223 }
224
225 } // namespace ROCKSDB_NAMESPACE
226