]>
Commit | Line | Data |
---|---|---|
f67539c2 | 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. |
7c673cae FG |
2 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
3 | // Use of this source code is governed by a BSD-style license that can be | |
4 | // found in the LICENSE file. See the AUTHORS file for names of contributors. | |
5 | ||
f67539c2 | 6 | #include "table/plain/plain_table_factory.h" |
7c673cae | 7 | |
7c673cae | 8 | #include <stdint.h> |
20effc67 | 9 | |
11fdf7f2 | 10 | #include <memory> |
20effc67 | 11 | |
7c673cae | 12 | #include "db/dbformat.h" |
11fdf7f2 TL |
13 | #include "port/port.h" |
14 | #include "rocksdb/convenience.h" | |
1e59de90 TL |
15 | #include "rocksdb/utilities/customizable_util.h" |
16 | #include "rocksdb/utilities/object_registry.h" | |
20effc67 | 17 | #include "rocksdb/utilities/options_type.h" |
f67539c2 TL |
18 | #include "table/plain/plain_table_builder.h" |
19 | #include "table/plain/plain_table_reader.h" | |
11fdf7f2 | 20 | #include "util/string_util.h" |
7c673cae | 21 | |
f67539c2 | 22 | namespace ROCKSDB_NAMESPACE { |
1e59de90 | 23 | #ifndef ROCKSDB_LITE |
20effc67 TL |
24 | static std::unordered_map<std::string, OptionTypeInfo> plain_table_type_info = { |
25 | {"user_key_len", | |
26 | {offsetof(struct PlainTableOptions, user_key_len), OptionType::kUInt32T, | |
27 | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, | |
28 | {"bloom_bits_per_key", | |
29 | {offsetof(struct PlainTableOptions, bloom_bits_per_key), OptionType::kInt, | |
30 | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, | |
31 | {"hash_table_ratio", | |
32 | {offsetof(struct PlainTableOptions, hash_table_ratio), OptionType::kDouble, | |
33 | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, | |
34 | {"index_sparseness", | |
35 | {offsetof(struct PlainTableOptions, index_sparseness), OptionType::kSizeT, | |
36 | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, | |
37 | {"huge_page_tlb_size", | |
38 | {offsetof(struct PlainTableOptions, huge_page_tlb_size), | |
39 | OptionType::kSizeT, OptionVerificationType::kNormal, | |
40 | OptionTypeFlags::kNone}}, | |
41 | {"encoding_type", | |
42 | {offsetof(struct PlainTableOptions, encoding_type), | |
43 | OptionType::kEncodingType, OptionVerificationType::kNormal, | |
44 | OptionTypeFlags::kNone}}, | |
45 | {"full_scan_mode", | |
46 | {offsetof(struct PlainTableOptions, full_scan_mode), OptionType::kBoolean, | |
47 | OptionVerificationType::kNormal, OptionTypeFlags::kNone}}, | |
48 | {"store_index_in_file", | |
49 | {offsetof(struct PlainTableOptions, store_index_in_file), | |
50 | OptionType::kBoolean, OptionVerificationType::kNormal, | |
51 | OptionTypeFlags::kNone}}, | |
52 | }; | |
53 | ||
54 | PlainTableFactory::PlainTableFactory(const PlainTableOptions& options) | |
55 | : table_options_(options) { | |
1e59de90 | 56 | RegisterOptions(&table_options_, &plain_table_type_info); |
20effc67 | 57 | } |
7c673cae FG |
58 | |
59 | Status PlainTableFactory::NewTableReader( | |
20effc67 | 60 | const ReadOptions& /*ro*/, const TableReaderOptions& table_reader_options, |
494da23a TL |
61 | std::unique_ptr<RandomAccessFileReader>&& file, uint64_t file_size, |
62 | std::unique_ptr<TableReader>* table, | |
11fdf7f2 | 63 | bool /*prefetch_index_and_filter_in_cache*/) const { |
7c673cae FG |
64 | return PlainTableReader::Open( |
65 | table_reader_options.ioptions, table_reader_options.env_options, | |
66 | table_reader_options.internal_comparator, std::move(file), file_size, | |
67 | table, table_options_.bloom_bits_per_key, table_options_.hash_table_ratio, | |
68 | table_options_.index_sparseness, table_options_.huge_page_tlb_size, | |
494da23a | 69 | table_options_.full_scan_mode, table_reader_options.immortal, |
1e59de90 | 70 | table_reader_options.prefix_extractor.get()); |
7c673cae FG |
71 | } |
72 | ||
73 | TableBuilder* PlainTableFactory::NewTableBuilder( | |
1e59de90 | 74 | const TableBuilderOptions& table_builder_options, |
7c673cae FG |
75 | WritableFileWriter* file) const { |
76 | // Ignore the skip_filters flag. PlainTable format is optimized for small | |
77 | // in-memory dbs. The skip_filters optimization is not useful for plain | |
78 | // tables | |
79 | // | |
80 | return new PlainTableBuilder( | |
11fdf7f2 | 81 | table_builder_options.ioptions, table_builder_options.moptions, |
1e59de90 TL |
82 | table_builder_options.int_tbl_prop_collector_factories, |
83 | table_builder_options.column_family_id, | |
84 | table_builder_options.level_at_creation, file, | |
85 | table_options_.user_key_len, table_options_.encoding_type, | |
7c673cae FG |
86 | table_options_.index_sparseness, table_options_.bloom_bits_per_key, |
87 | table_builder_options.column_family_name, 6, | |
88 | table_options_.huge_page_tlb_size, table_options_.hash_table_ratio, | |
20effc67 | 89 | table_options_.store_index_in_file, table_builder_options.db_id, |
1e59de90 | 90 | table_builder_options.db_session_id, table_builder_options.cur_file_num); |
7c673cae FG |
91 | } |
92 | ||
20effc67 | 93 | std::string PlainTableFactory::GetPrintableOptions() const { |
7c673cae FG |
94 | std::string ret; |
95 | ret.reserve(20000); | |
96 | const int kBufferSize = 200; | |
97 | char buffer[kBufferSize]; | |
98 | ||
99 | snprintf(buffer, kBufferSize, " user_key_len: %u\n", | |
100 | table_options_.user_key_len); | |
101 | ret.append(buffer); | |
102 | snprintf(buffer, kBufferSize, " bloom_bits_per_key: %d\n", | |
103 | table_options_.bloom_bits_per_key); | |
104 | ret.append(buffer); | |
105 | snprintf(buffer, kBufferSize, " hash_table_ratio: %lf\n", | |
106 | table_options_.hash_table_ratio); | |
107 | ret.append(buffer); | |
108 | snprintf(buffer, kBufferSize, " index_sparseness: %" ROCKSDB_PRIszt "\n", | |
109 | table_options_.index_sparseness); | |
110 | ret.append(buffer); | |
111 | snprintf(buffer, kBufferSize, " huge_page_tlb_size: %" ROCKSDB_PRIszt "\n", | |
112 | table_options_.huge_page_tlb_size); | |
113 | ret.append(buffer); | |
114 | snprintf(buffer, kBufferSize, " encoding_type: %d\n", | |
115 | table_options_.encoding_type); | |
116 | ret.append(buffer); | |
117 | snprintf(buffer, kBufferSize, " full_scan_mode: %d\n", | |
118 | table_options_.full_scan_mode); | |
119 | ret.append(buffer); | |
120 | snprintf(buffer, kBufferSize, " store_index_in_file: %d\n", | |
121 | table_options_.store_index_in_file); | |
122 | ret.append(buffer); | |
123 | return ret; | |
124 | } | |
125 | ||
20effc67 TL |
126 | Status GetPlainTableOptionsFromString(const PlainTableOptions& table_options, |
127 | const std::string& opts_str, | |
128 | PlainTableOptions* new_table_options) { | |
129 | ConfigOptions config_options; | |
130 | config_options.input_strings_escaped = false; | |
131 | config_options.ignore_unknown_options = false; | |
132 | config_options.invoke_prepare_options = false; | |
133 | return GetPlainTableOptionsFromString(config_options, table_options, opts_str, | |
134 | new_table_options); | |
7c673cae FG |
135 | } |
136 | ||
20effc67 TL |
137 | Status GetPlainTableOptionsFromString(const ConfigOptions& config_options, |
138 | const PlainTableOptions& table_options, | |
11fdf7f2 TL |
139 | const std::string& opts_str, |
140 | PlainTableOptions* new_table_options) { | |
141 | std::unordered_map<std::string, std::string> opts_map; | |
142 | Status s = StringToMap(opts_str, &opts_map); | |
143 | if (!s.ok()) { | |
144 | return s; | |
145 | } | |
20effc67 TL |
146 | |
147 | s = GetPlainTableOptionsFromMap(config_options, table_options, opts_map, | |
148 | new_table_options); | |
149 | // Translate any errors (NotFound, NotSupported, to InvalidArgument | |
150 | if (s.ok() || s.IsInvalidArgument()) { | |
151 | return s; | |
152 | } else { | |
153 | return Status::InvalidArgument(s.getState()); | |
154 | } | |
11fdf7f2 | 155 | } |
1e59de90 | 156 | #endif // ROCKSDB_LITE |
11fdf7f2 | 157 | |
1e59de90 TL |
158 | #ifndef ROCKSDB_LITE |
159 | static int RegisterBuiltinMemTableRepFactory(ObjectLibrary& library, | |
160 | const std::string& /*arg*/) { | |
161 | // The MemTableRepFactory built-in classes will be either a class | |
162 | // (VectorRepFactory) or a nickname (vector), followed optionally by ":#", | |
163 | // where # is the "size" of the factory. | |
164 | auto AsPattern = [](const std::string& name, const std::string& alt) { | |
165 | auto pattern = ObjectLibrary::PatternEntry(name, true); | |
166 | pattern.AnotherName(alt); | |
167 | pattern.AddNumber(":"); | |
168 | return pattern; | |
169 | }; | |
170 | library.AddFactory<MemTableRepFactory>( | |
171 | AsPattern(VectorRepFactory::kClassName(), VectorRepFactory::kNickName()), | |
172 | [](const std::string& uri, std::unique_ptr<MemTableRepFactory>* guard, | |
173 | std::string* /*errmsg*/) { | |
174 | auto colon = uri.find(":"); | |
175 | if (colon != std::string::npos) { | |
176 | size_t count = ParseSizeT(uri.substr(colon + 1)); | |
177 | guard->reset(new VectorRepFactory(count)); | |
178 | } else { | |
179 | guard->reset(new VectorRepFactory()); | |
180 | } | |
181 | return guard->get(); | |
182 | }); | |
183 | library.AddFactory<MemTableRepFactory>( | |
184 | AsPattern(SkipListFactory::kClassName(), SkipListFactory::kNickName()), | |
185 | [](const std::string& uri, std::unique_ptr<MemTableRepFactory>* guard, | |
186 | std::string* /*errmsg*/) { | |
187 | auto colon = uri.find(":"); | |
188 | if (colon != std::string::npos) { | |
189 | size_t lookahead = ParseSizeT(uri.substr(colon + 1)); | |
190 | guard->reset(new SkipListFactory(lookahead)); | |
191 | } else { | |
192 | guard->reset(new SkipListFactory()); | |
193 | } | |
194 | return guard->get(); | |
195 | }); | |
196 | library.AddFactory<MemTableRepFactory>( | |
197 | AsPattern("HashLinkListRepFactory", "hash_linkedlist"), | |
198 | [](const std::string& uri, std::unique_ptr<MemTableRepFactory>* guard, | |
199 | std::string* /*errmsg*/) { | |
200 | // Expecting format: hash_linkedlist:<hash_bucket_count> | |
201 | auto colon = uri.find(":"); | |
202 | if (colon != std::string::npos) { | |
203 | size_t hash_bucket_count = ParseSizeT(uri.substr(colon + 1)); | |
204 | guard->reset(NewHashLinkListRepFactory(hash_bucket_count)); | |
205 | } else { | |
206 | guard->reset(NewHashLinkListRepFactory()); | |
207 | } | |
208 | return guard->get(); | |
209 | }); | |
210 | library.AddFactory<MemTableRepFactory>( | |
211 | AsPattern("HashSkipListRepFactory", "prefix_hash"), | |
212 | [](const std::string& uri, std::unique_ptr<MemTableRepFactory>* guard, | |
213 | std::string* /*errmsg*/) { | |
214 | // Expecting format: prefix_hash:<hash_bucket_count> | |
215 | auto colon = uri.find(":"); | |
216 | if (colon != std::string::npos) { | |
217 | size_t hash_bucket_count = ParseSizeT(uri.substr(colon + 1)); | |
218 | guard->reset(NewHashSkipListRepFactory(hash_bucket_count)); | |
219 | } else { | |
220 | guard->reset(NewHashSkipListRepFactory()); | |
221 | } | |
222 | return guard->get(); | |
223 | }); | |
224 | library.AddFactory<MemTableRepFactory>( | |
225 | "cuckoo", | |
226 | [](const std::string& /*uri*/, | |
227 | std::unique_ptr<MemTableRepFactory>* /*guard*/, std::string* errmsg) { | |
228 | *errmsg = "cuckoo hash memtable is not supported anymore."; | |
229 | return nullptr; | |
230 | }); | |
11fdf7f2 | 231 | |
1e59de90 TL |
232 | size_t num_types; |
233 | return static_cast<int>(library.GetFactoryCount(&num_types)); | |
234 | } | |
235 | #endif // ROCKSDB_LITE | |
11fdf7f2 | 236 | |
1e59de90 TL |
237 | Status GetMemTableRepFactoryFromString( |
238 | const std::string& opts_str, std::unique_ptr<MemTableRepFactory>* result) { | |
239 | ConfigOptions config_options; | |
240 | config_options.ignore_unsupported_options = false; | |
241 | config_options.ignore_unknown_options = false; | |
242 | return MemTableRepFactory::CreateFromString(config_options, opts_str, result); | |
243 | } | |
11fdf7f2 | 244 | |
1e59de90 TL |
245 | Status MemTableRepFactory::CreateFromString( |
246 | const ConfigOptions& config_options, const std::string& value, | |
247 | std::unique_ptr<MemTableRepFactory>* result) { | |
248 | #ifndef ROCKSDB_LITE | |
249 | static std::once_flag once; | |
250 | std::call_once(once, [&]() { | |
251 | RegisterBuiltinMemTableRepFactory(*(ObjectLibrary::Default().get()), ""); | |
252 | }); | |
253 | #endif // ROCKSDB_LITE | |
254 | std::string id; | |
255 | std::unordered_map<std::string, std::string> opt_map; | |
256 | Status status = Customizable::GetOptionsMap(config_options, result->get(), | |
257 | value, &id, &opt_map); | |
258 | if (!status.ok()) { // GetOptionsMap failed | |
259 | return status; | |
260 | } else if (value.empty()) { | |
261 | // No Id and no options. Clear the object | |
262 | result->reset(); | |
263 | return Status::OK(); | |
264 | } else if (id.empty()) { // We have no Id but have options. Not good | |
265 | return Status::NotSupported("Cannot reset object ", id); | |
11fdf7f2 | 266 | } else { |
1e59de90 TL |
267 | #ifndef ROCKSDB_LITE |
268 | status = NewUniqueObject<MemTableRepFactory>(config_options, id, opt_map, | |
269 | result); | |
270 | #else | |
271 | // To make it possible to configure the memtables in LITE mode, the ID | |
272 | // is of the form <name>:<size>, where name is the name of the class and | |
273 | // <size> is the length of the object (e.g. skip_list:10). | |
274 | std::vector<std::string> opts_list = StringSplit(id, ':'); | |
275 | if (opts_list.empty() || opts_list.size() > 2 || !opt_map.empty()) { | |
276 | status = Status::InvalidArgument("Can't parse memtable_factory option ", | |
277 | value); | |
278 | } else if (opts_list[0] == SkipListFactory::kNickName() || | |
279 | opts_list[0] == SkipListFactory::kClassName()) { | |
280 | // Expecting format | |
281 | // skip_list:<lookahead> | |
282 | if (opts_list.size() == 2) { | |
283 | size_t lookahead = ParseSizeT(opts_list[1]); | |
284 | result->reset(new SkipListFactory(lookahead)); | |
285 | } else { | |
286 | result->reset(new SkipListFactory()); | |
287 | } | |
288 | } else if (!config_options.ignore_unsupported_options) { | |
289 | status = Status::NotSupported("Cannot load object in LITE mode ", id); | |
290 | } | |
291 | #endif // ROCKSDB_LITE | |
11fdf7f2 | 292 | } |
1e59de90 TL |
293 | return status; |
294 | } | |
11fdf7f2 | 295 | |
1e59de90 TL |
296 | Status MemTableRepFactory::CreateFromString( |
297 | const ConfigOptions& config_options, const std::string& value, | |
298 | std::shared_ptr<MemTableRepFactory>* result) { | |
299 | std::unique_ptr<MemTableRepFactory> factory; | |
300 | Status s = CreateFromString(config_options, value, &factory); | |
301 | if (factory && s.ok()) { | |
302 | result->reset(factory.release()); | |
11fdf7f2 | 303 | } |
1e59de90 | 304 | return s; |
11fdf7f2 TL |
305 | } |
306 | ||
1e59de90 | 307 | #ifndef ROCKSDB_LITE |
11fdf7f2 TL |
308 | Status GetPlainTableOptionsFromMap( |
309 | const PlainTableOptions& table_options, | |
310 | const std::unordered_map<std::string, std::string>& opts_map, | |
311 | PlainTableOptions* new_table_options, bool input_strings_escaped, | |
20effc67 TL |
312 | bool ignore_unknown_options) { |
313 | ConfigOptions config_options; | |
314 | config_options.input_strings_escaped = input_strings_escaped; | |
315 | config_options.ignore_unknown_options = ignore_unknown_options; | |
316 | return GetPlainTableOptionsFromMap(config_options, table_options, opts_map, | |
317 | new_table_options); | |
318 | } | |
319 | ||
320 | Status GetPlainTableOptionsFromMap( | |
321 | const ConfigOptions& config_options, const PlainTableOptions& table_options, | |
322 | const std::unordered_map<std::string, std::string>& opts_map, | |
323 | PlainTableOptions* new_table_options) { | |
11fdf7f2 | 324 | assert(new_table_options); |
20effc67 TL |
325 | PlainTableFactory ptf(table_options); |
326 | Status s = ptf.ConfigureFromMap(config_options, opts_map); | |
327 | if (s.ok()) { | |
328 | *new_table_options = *(ptf.GetOptions<PlainTableOptions>()); | |
329 | } else { | |
330 | // Restore "new_options" to the default "base_options". | |
331 | *new_table_options = table_options; | |
11fdf7f2 | 332 | } |
20effc67 | 333 | return s; |
11fdf7f2 TL |
334 | } |
335 | ||
7c673cae FG |
336 | extern TableFactory* NewPlainTableFactory(const PlainTableOptions& options) { |
337 | return new PlainTableFactory(options); | |
338 | } | |
339 | ||
340 | const std::string PlainTablePropertyNames::kEncodingType = | |
341 | "rocksdb.plain.table.encoding.type"; | |
342 | ||
343 | const std::string PlainTablePropertyNames::kBloomVersion = | |
344 | "rocksdb.plain.table.bloom.version"; | |
345 | ||
346 | const std::string PlainTablePropertyNames::kNumBloomBlocks = | |
347 | "rocksdb.plain.table.bloom.numblocks"; | |
348 | ||
7c673cae | 349 | #endif // ROCKSDB_LITE |
1e59de90 | 350 | } // namespace ROCKSDB_NAMESPACE |