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).
5 #include "options/options_helper.h"
6
7 #include <cassert>
8 #include <cctype>
9 #include <cstdlib>
10 #include <unordered_set>
11 #include <vector>
12
13 #include "rocksdb/cache.h"
14 #include "rocksdb/compaction_filter.h"
15 #include "rocksdb/convenience.h"
16 #include "rocksdb/filter_policy.h"
17 #include "rocksdb/memtablerep.h"
18 #include "rocksdb/merge_operator.h"
19 #include "rocksdb/options.h"
20 #include "rocksdb/rate_limiter.h"
21 #include "rocksdb/slice_transform.h"
22 #include "rocksdb/table.h"
23 #include "rocksdb/utilities/object_registry.h"
24 #include "table/block_based/block_based_table_factory.h"
25 #include "table/plain/plain_table_factory.h"
26 #include "util/cast_util.h"
27 #include "util/string_util.h"
28
29 namespace ROCKSDB_NAMESPACE {
30
BuildDBOptions(const ImmutableDBOptions & immutable_db_options,const MutableDBOptions & mutable_db_options)31 DBOptions BuildDBOptions(const ImmutableDBOptions& immutable_db_options,
32 const MutableDBOptions& mutable_db_options) {
33 DBOptions options;
34
35 options.create_if_missing = immutable_db_options.create_if_missing;
36 options.create_missing_column_families =
37 immutable_db_options.create_missing_column_families;
38 options.error_if_exists = immutable_db_options.error_if_exists;
39 options.paranoid_checks = immutable_db_options.paranoid_checks;
40 options.env = immutable_db_options.env;
41 options.file_system = immutable_db_options.fs;
42 options.rate_limiter = immutable_db_options.rate_limiter;
43 options.sst_file_manager = immutable_db_options.sst_file_manager;
44 options.info_log = immutable_db_options.info_log;
45 options.info_log_level = immutable_db_options.info_log_level;
46 options.max_open_files = mutable_db_options.max_open_files;
47 options.max_file_opening_threads =
48 immutable_db_options.max_file_opening_threads;
49 options.max_total_wal_size = mutable_db_options.max_total_wal_size;
50 options.statistics = immutable_db_options.statistics;
51 options.use_fsync = immutable_db_options.use_fsync;
52 options.db_paths = immutable_db_options.db_paths;
53 options.db_log_dir = immutable_db_options.db_log_dir;
54 options.wal_dir = immutable_db_options.wal_dir;
55 options.delete_obsolete_files_period_micros =
56 mutable_db_options.delete_obsolete_files_period_micros;
57 options.max_background_jobs = mutable_db_options.max_background_jobs;
58 options.base_background_compactions =
59 mutable_db_options.base_background_compactions;
60 options.max_background_compactions =
61 mutable_db_options.max_background_compactions;
62 options.bytes_per_sync = mutable_db_options.bytes_per_sync;
63 options.wal_bytes_per_sync = mutable_db_options.wal_bytes_per_sync;
64 options.strict_bytes_per_sync = mutable_db_options.strict_bytes_per_sync;
65 options.max_subcompactions = immutable_db_options.max_subcompactions;
66 options.max_background_flushes = immutable_db_options.max_background_flushes;
67 options.max_log_file_size = immutable_db_options.max_log_file_size;
68 options.log_file_time_to_roll = immutable_db_options.log_file_time_to_roll;
69 options.keep_log_file_num = immutable_db_options.keep_log_file_num;
70 options.recycle_log_file_num = immutable_db_options.recycle_log_file_num;
71 options.max_manifest_file_size = immutable_db_options.max_manifest_file_size;
72 options.table_cache_numshardbits =
73 immutable_db_options.table_cache_numshardbits;
74 options.WAL_ttl_seconds = immutable_db_options.wal_ttl_seconds;
75 options.WAL_size_limit_MB = immutable_db_options.wal_size_limit_mb;
76 options.manifest_preallocation_size =
77 immutable_db_options.manifest_preallocation_size;
78 options.allow_mmap_reads = immutable_db_options.allow_mmap_reads;
79 options.allow_mmap_writes = immutable_db_options.allow_mmap_writes;
80 options.use_direct_reads = immutable_db_options.use_direct_reads;
81 options.use_direct_io_for_flush_and_compaction =
82 immutable_db_options.use_direct_io_for_flush_and_compaction;
83 options.allow_fallocate = immutable_db_options.allow_fallocate;
84 options.is_fd_close_on_exec = immutable_db_options.is_fd_close_on_exec;
85 options.stats_dump_period_sec = mutable_db_options.stats_dump_period_sec;
86 options.stats_persist_period_sec =
87 mutable_db_options.stats_persist_period_sec;
88 options.persist_stats_to_disk = immutable_db_options.persist_stats_to_disk;
89 options.stats_history_buffer_size =
90 mutable_db_options.stats_history_buffer_size;
91 options.advise_random_on_open = immutable_db_options.advise_random_on_open;
92 options.db_write_buffer_size = immutable_db_options.db_write_buffer_size;
93 options.write_buffer_manager = immutable_db_options.write_buffer_manager;
94 options.access_hint_on_compaction_start =
95 immutable_db_options.access_hint_on_compaction_start;
96 options.new_table_reader_for_compaction_inputs =
97 immutable_db_options.new_table_reader_for_compaction_inputs;
98 options.compaction_readahead_size =
99 mutable_db_options.compaction_readahead_size;
100 options.random_access_max_buffer_size =
101 immutable_db_options.random_access_max_buffer_size;
102 options.writable_file_max_buffer_size =
103 mutable_db_options.writable_file_max_buffer_size;
104 options.use_adaptive_mutex = immutable_db_options.use_adaptive_mutex;
105 options.listeners = immutable_db_options.listeners;
106 options.enable_thread_tracking = immutable_db_options.enable_thread_tracking;
107 options.delayed_write_rate = mutable_db_options.delayed_write_rate;
108 options.enable_pipelined_write = immutable_db_options.enable_pipelined_write;
109 options.unordered_write = immutable_db_options.unordered_write;
110 options.allow_concurrent_memtable_write =
111 immutable_db_options.allow_concurrent_memtable_write;
112 options.enable_write_thread_adaptive_yield =
113 immutable_db_options.enable_write_thread_adaptive_yield;
114 options.max_write_batch_group_size_bytes =
115 immutable_db_options.max_write_batch_group_size_bytes;
116 options.write_thread_max_yield_usec =
117 immutable_db_options.write_thread_max_yield_usec;
118 options.write_thread_slow_yield_usec =
119 immutable_db_options.write_thread_slow_yield_usec;
120 options.skip_stats_update_on_db_open =
121 immutable_db_options.skip_stats_update_on_db_open;
122 options.skip_checking_sst_file_sizes_on_db_open =
123 immutable_db_options.skip_checking_sst_file_sizes_on_db_open;
124 options.wal_recovery_mode = immutable_db_options.wal_recovery_mode;
125 options.allow_2pc = immutable_db_options.allow_2pc;
126 options.row_cache = immutable_db_options.row_cache;
127 #ifndef ROCKSDB_LITE
128 options.wal_filter = immutable_db_options.wal_filter;
129 #endif // ROCKSDB_LITE
130 options.fail_if_options_file_error =
131 immutable_db_options.fail_if_options_file_error;
132 options.dump_malloc_stats = immutable_db_options.dump_malloc_stats;
133 options.avoid_flush_during_recovery =
134 immutable_db_options.avoid_flush_during_recovery;
135 options.avoid_flush_during_shutdown =
136 mutable_db_options.avoid_flush_during_shutdown;
137 options.allow_ingest_behind =
138 immutable_db_options.allow_ingest_behind;
139 options.preserve_deletes =
140 immutable_db_options.preserve_deletes;
141 options.two_write_queues = immutable_db_options.two_write_queues;
142 options.manual_wal_flush = immutable_db_options.manual_wal_flush;
143 options.atomic_flush = immutable_db_options.atomic_flush;
144 options.avoid_unnecessary_blocking_io =
145 immutable_db_options.avoid_unnecessary_blocking_io;
146 options.log_readahead_size = immutable_db_options.log_readahead_size;
147 options.sst_file_checksum_func = immutable_db_options.sst_file_checksum_func;
148 return options;
149 }
150
BuildColumnFamilyOptions(const ColumnFamilyOptions & options,const MutableCFOptions & mutable_cf_options)151 ColumnFamilyOptions BuildColumnFamilyOptions(
152 const ColumnFamilyOptions& options,
153 const MutableCFOptions& mutable_cf_options) {
154 ColumnFamilyOptions cf_opts(options);
155
156 // Memtable related options
157 cf_opts.write_buffer_size = mutable_cf_options.write_buffer_size;
158 cf_opts.max_write_buffer_number = mutable_cf_options.max_write_buffer_number;
159 cf_opts.arena_block_size = mutable_cf_options.arena_block_size;
160 cf_opts.memtable_prefix_bloom_size_ratio =
161 mutable_cf_options.memtable_prefix_bloom_size_ratio;
162 cf_opts.memtable_whole_key_filtering =
163 mutable_cf_options.memtable_whole_key_filtering;
164 cf_opts.memtable_huge_page_size = mutable_cf_options.memtable_huge_page_size;
165 cf_opts.max_successive_merges = mutable_cf_options.max_successive_merges;
166 cf_opts.inplace_update_num_locks =
167 mutable_cf_options.inplace_update_num_locks;
168 cf_opts.prefix_extractor = mutable_cf_options.prefix_extractor;
169
170 // Compaction related options
171 cf_opts.disable_auto_compactions =
172 mutable_cf_options.disable_auto_compactions;
173 cf_opts.soft_pending_compaction_bytes_limit =
174 mutable_cf_options.soft_pending_compaction_bytes_limit;
175 cf_opts.hard_pending_compaction_bytes_limit =
176 mutable_cf_options.hard_pending_compaction_bytes_limit;
177 cf_opts.level0_file_num_compaction_trigger =
178 mutable_cf_options.level0_file_num_compaction_trigger;
179 cf_opts.level0_slowdown_writes_trigger =
180 mutable_cf_options.level0_slowdown_writes_trigger;
181 cf_opts.level0_stop_writes_trigger =
182 mutable_cf_options.level0_stop_writes_trigger;
183 cf_opts.max_compaction_bytes = mutable_cf_options.max_compaction_bytes;
184 cf_opts.target_file_size_base = mutable_cf_options.target_file_size_base;
185 cf_opts.target_file_size_multiplier =
186 mutable_cf_options.target_file_size_multiplier;
187 cf_opts.max_bytes_for_level_base =
188 mutable_cf_options.max_bytes_for_level_base;
189 cf_opts.max_bytes_for_level_multiplier =
190 mutable_cf_options.max_bytes_for_level_multiplier;
191 cf_opts.ttl = mutable_cf_options.ttl;
192 cf_opts.periodic_compaction_seconds =
193 mutable_cf_options.periodic_compaction_seconds;
194
195 cf_opts.max_bytes_for_level_multiplier_additional.clear();
196 for (auto value :
197 mutable_cf_options.max_bytes_for_level_multiplier_additional) {
198 cf_opts.max_bytes_for_level_multiplier_additional.emplace_back(value);
199 }
200
201 cf_opts.compaction_options_fifo = mutable_cf_options.compaction_options_fifo;
202 cf_opts.compaction_options_universal =
203 mutable_cf_options.compaction_options_universal;
204
205 // Misc options
206 cf_opts.max_sequential_skip_in_iterations =
207 mutable_cf_options.max_sequential_skip_in_iterations;
208 cf_opts.paranoid_file_checks = mutable_cf_options.paranoid_file_checks;
209 cf_opts.report_bg_io_stats = mutable_cf_options.report_bg_io_stats;
210 cf_opts.compression = mutable_cf_options.compression;
211 cf_opts.sample_for_compression = mutable_cf_options.sample_for_compression;
212
213 cf_opts.table_factory = options.table_factory;
214 // TODO(yhchiang): find some way to handle the following derived options
215 // * max_file_size
216
217 return cf_opts;
218 }
219
220 std::map<CompactionStyle, std::string>
221 OptionsHelper::compaction_style_to_string = {
222 {kCompactionStyleLevel, "kCompactionStyleLevel"},
223 {kCompactionStyleUniversal, "kCompactionStyleUniversal"},
224 {kCompactionStyleFIFO, "kCompactionStyleFIFO"},
225 {kCompactionStyleNone, "kCompactionStyleNone"}};
226
227 std::map<CompactionPri, std::string> OptionsHelper::compaction_pri_to_string = {
228 {kByCompensatedSize, "kByCompensatedSize"},
229 {kOldestLargestSeqFirst, "kOldestLargestSeqFirst"},
230 {kOldestSmallestSeqFirst, "kOldestSmallestSeqFirst"},
231 {kMinOverlappingRatio, "kMinOverlappingRatio"}};
232
233 std::map<CompactionStopStyle, std::string>
234 OptionsHelper::compaction_stop_style_to_string = {
235 {kCompactionStopStyleSimilarSize, "kCompactionStopStyleSimilarSize"},
236 {kCompactionStopStyleTotalSize, "kCompactionStopStyleTotalSize"}};
237
238 std::unordered_map<std::string, ChecksumType>
239 OptionsHelper::checksum_type_string_map = {{"kNoChecksum", kNoChecksum},
240 {"kCRC32c", kCRC32c},
241 {"kxxHash", kxxHash},
242 {"kxxHash64", kxxHash64}};
243
244 std::unordered_map<std::string, CompressionType>
245 OptionsHelper::compression_type_string_map = {
246 {"kNoCompression", kNoCompression},
247 {"kSnappyCompression", kSnappyCompression},
248 {"kZlibCompression", kZlibCompression},
249 {"kBZip2Compression", kBZip2Compression},
250 {"kLZ4Compression", kLZ4Compression},
251 {"kLZ4HCCompression", kLZ4HCCompression},
252 {"kXpressCompression", kXpressCompression},
253 {"kZSTD", kZSTD},
254 {"kZSTDNotFinalCompression", kZSTDNotFinalCompression},
255 {"kDisableCompressionOption", kDisableCompressionOption}};
256 #ifndef ROCKSDB_LITE
257
258 const std::string kNameComparator = "comparator";
259 const std::string kNameEnv = "env";
260 const std::string kNameMergeOperator = "merge_operator";
261
262 template <typename T>
263 Status GetStringFromStruct(
264 std::string* opt_string, const T& options,
265 const std::unordered_map<std::string, OptionTypeInfo>& type_info,
266 const std::string& delimiter);
267
268 namespace {
269 template <typename T>
ParseEnum(const std::unordered_map<std::string,T> & type_map,const std::string & type,T * value)270 bool ParseEnum(const std::unordered_map<std::string, T>& type_map,
271 const std::string& type, T* value) {
272 auto iter = type_map.find(type);
273 if (iter != type_map.end()) {
274 *value = iter->second;
275 return true;
276 }
277 return false;
278 }
279
280 template <typename T>
SerializeEnum(const std::unordered_map<std::string,T> & type_map,const T & type,std::string * value)281 bool SerializeEnum(const std::unordered_map<std::string, T>& type_map,
282 const T& type, std::string* value) {
283 for (const auto& pair : type_map) {
284 if (pair.second == type) {
285 *value = pair.first;
286 return true;
287 }
288 }
289 return false;
290 }
291
SerializeVectorCompressionType(const std::vector<CompressionType> & types,std::string * value)292 bool SerializeVectorCompressionType(const std::vector<CompressionType>& types,
293 std::string* value) {
294 std::stringstream ss;
295 bool result;
296 for (size_t i = 0; i < types.size(); ++i) {
297 if (i > 0) {
298 ss << ':';
299 }
300 std::string string_type;
301 result = SerializeEnum<CompressionType>(compression_type_string_map,
302 types[i], &string_type);
303 if (result == false) {
304 return result;
305 }
306 ss << string_type;
307 }
308 *value = ss.str();
309 return true;
310 }
311
ParseVectorCompressionType(const std::string & value,std::vector<CompressionType> * compression_per_level)312 bool ParseVectorCompressionType(
313 const std::string& value,
314 std::vector<CompressionType>* compression_per_level) {
315 compression_per_level->clear();
316 size_t start = 0;
317 while (start < value.size()) {
318 size_t end = value.find(':', start);
319 bool is_ok;
320 CompressionType type;
321 if (end == std::string::npos) {
322 is_ok = ParseEnum<CompressionType>(compression_type_string_map,
323 value.substr(start), &type);
324 if (!is_ok) {
325 return false;
326 }
327 compression_per_level->emplace_back(type);
328 break;
329 } else {
330 is_ok = ParseEnum<CompressionType>(
331 compression_type_string_map, value.substr(start, end - start), &type);
332 if (!is_ok) {
333 return false;
334 }
335 compression_per_level->emplace_back(type);
336 start = end + 1;
337 }
338 }
339 return true;
340 }
341
342 // This is to handle backward compatibility, where compaction_options_fifo
343 // could be assigned a single scalar value, say, like "23", which would be
344 // assigned to max_table_files_size.
FIFOCompactionOptionsSpecialCase(const std::string & opt_str,CompactionOptionsFIFO * options)345 bool FIFOCompactionOptionsSpecialCase(const std::string& opt_str,
346 CompactionOptionsFIFO* options) {
347 if (opt_str.find("=") != std::string::npos) {
348 // New format. Go do your new parsing using ParseStructOptions.
349 return false;
350 }
351
352 // Old format. Parse just a single uint64_t value.
353 options->max_table_files_size = ParseUint64(opt_str);
354 return true;
355 }
356
357 template <typename T>
SerializeStruct(const T & options,std::string * value,const std::unordered_map<std::string,OptionTypeInfo> & type_info_map)358 bool SerializeStruct(
359 const T& options, std::string* value,
360 const std::unordered_map<std::string, OptionTypeInfo>& type_info_map) {
361 std::string opt_str;
362 Status s = GetStringFromStruct(&opt_str, options, type_info_map, ";");
363 if (!s.ok()) {
364 return false;
365 }
366 *value = "{" + opt_str + "}";
367 return true;
368 }
369
370 template <typename T>
ParseSingleStructOption(const std::string & opt_val_str,T * options,const std::unordered_map<std::string,OptionTypeInfo> & type_info_map)371 bool ParseSingleStructOption(
372 const std::string& opt_val_str, T* options,
373 const std::unordered_map<std::string, OptionTypeInfo>& type_info_map) {
374 size_t end = opt_val_str.find('=');
375 std::string key = opt_val_str.substr(0, end);
376 std::string value = opt_val_str.substr(end + 1);
377 auto iter = type_info_map.find(key);
378 if (iter == type_info_map.end()) {
379 return false;
380 }
381 const auto& opt_info = iter->second;
382 if (opt_info.verification == OptionVerificationType::kDeprecated) {
383 // Should also skip deprecated sub-options such as
384 // fifo_compaction_options_type_info.ttl
385 return true;
386 }
387 return ParseOptionHelper(
388 reinterpret_cast<char*>(options) + opt_info.mutable_offset, opt_info.type,
389 value);
390 }
391
392 template <typename T>
ParseStructOptions(const std::string & opt_str,T * options,const std::unordered_map<std::string,OptionTypeInfo> & type_info_map)393 bool ParseStructOptions(
394 const std::string& opt_str, T* options,
395 const std::unordered_map<std::string, OptionTypeInfo>& type_info_map) {
396 assert(!opt_str.empty());
397
398 size_t start = 0;
399 if (opt_str[0] == '{') {
400 start++;
401 }
402 while ((start != std::string::npos) && (start < opt_str.size())) {
403 if (opt_str[start] == '}') {
404 break;
405 }
406 size_t end = opt_str.find(';', start);
407 size_t len = (end == std::string::npos) ? end : end - start;
408 if (!ParseSingleStructOption(opt_str.substr(start, len), options,
409 type_info_map)) {
410 return false;
411 }
412 start = (end == std::string::npos) ? end : end + 1;
413 }
414 return true;
415 }
416 } // anonymouse namespace
417
ParseSliceTransformHelper(const std::string & kFixedPrefixName,const std::string & kCappedPrefixName,const std::string & value,std::shared_ptr<const SliceTransform> * slice_transform)418 bool ParseSliceTransformHelper(
419 const std::string& kFixedPrefixName, const std::string& kCappedPrefixName,
420 const std::string& value,
421 std::shared_ptr<const SliceTransform>* slice_transform) {
422 const char* no_op_name = "rocksdb.Noop";
423 size_t no_op_length = strlen(no_op_name);
424 auto& pe_value = value;
425 if (pe_value.size() > kFixedPrefixName.size() &&
426 pe_value.compare(0, kFixedPrefixName.size(), kFixedPrefixName) == 0) {
427 int prefix_length = ParseInt(trim(value.substr(kFixedPrefixName.size())));
428 slice_transform->reset(NewFixedPrefixTransform(prefix_length));
429 } else if (pe_value.size() > kCappedPrefixName.size() &&
430 pe_value.compare(0, kCappedPrefixName.size(), kCappedPrefixName) ==
431 0) {
432 int prefix_length =
433 ParseInt(trim(pe_value.substr(kCappedPrefixName.size())));
434 slice_transform->reset(NewCappedPrefixTransform(prefix_length));
435 } else if (pe_value.size() == no_op_length &&
436 pe_value.compare(0, no_op_length, no_op_name) == 0) {
437 const SliceTransform* no_op_transform = NewNoopTransform();
438 slice_transform->reset(no_op_transform);
439 } else if (value == kNullptrString) {
440 slice_transform->reset();
441 } else {
442 return false;
443 }
444
445 return true;
446 }
447
ParseSliceTransform(const std::string & value,std::shared_ptr<const SliceTransform> * slice_transform)448 bool ParseSliceTransform(
449 const std::string& value,
450 std::shared_ptr<const SliceTransform>* slice_transform) {
451 // While we normally don't convert the string representation of a
452 // pointer-typed option into its instance, here we do so for backward
453 // compatibility as we allow this action in SetOption().
454
455 // TODO(yhchiang): A possible better place for these serialization /
456 // deserialization is inside the class definition of pointer-typed
457 // option itself, but this requires a bigger change of public API.
458 bool result =
459 ParseSliceTransformHelper("fixed:", "capped:", value, slice_transform);
460 if (result) {
461 return result;
462 }
463 result = ParseSliceTransformHelper(
464 "rocksdb.FixedPrefix.", "rocksdb.CappedPrefix.", value, slice_transform);
465 if (result) {
466 return result;
467 }
468 // TODO(yhchiang): we can further support other default
469 // SliceTransforms here.
470 return false;
471 }
472
ParseOptionHelper(char * opt_address,const OptionType & opt_type,const std::string & value)473 bool ParseOptionHelper(char* opt_address, const OptionType& opt_type,
474 const std::string& value) {
475 switch (opt_type) {
476 case OptionType::kBoolean:
477 *reinterpret_cast<bool*>(opt_address) = ParseBoolean("", value);
478 break;
479 case OptionType::kInt:
480 *reinterpret_cast<int*>(opt_address) = ParseInt(value);
481 break;
482 case OptionType::kInt32T:
483 *reinterpret_cast<int32_t*>(opt_address) = ParseInt32(value);
484 break;
485 case OptionType::kInt64T:
486 PutUnaligned(reinterpret_cast<int64_t*>(opt_address), ParseInt64(value));
487 break;
488 case OptionType::kVectorInt:
489 *reinterpret_cast<std::vector<int>*>(opt_address) = ParseVectorInt(value);
490 break;
491 case OptionType::kUInt:
492 *reinterpret_cast<unsigned int*>(opt_address) = ParseUint32(value);
493 break;
494 case OptionType::kUInt32T:
495 *reinterpret_cast<uint32_t*>(opt_address) = ParseUint32(value);
496 break;
497 case OptionType::kUInt64T:
498 PutUnaligned(reinterpret_cast<uint64_t*>(opt_address), ParseUint64(value));
499 break;
500 case OptionType::kSizeT:
501 PutUnaligned(reinterpret_cast<size_t*>(opt_address), ParseSizeT(value));
502 break;
503 case OptionType::kString:
504 *reinterpret_cast<std::string*>(opt_address) = value;
505 break;
506 case OptionType::kDouble:
507 *reinterpret_cast<double*>(opt_address) = ParseDouble(value);
508 break;
509 case OptionType::kCompactionStyle:
510 return ParseEnum<CompactionStyle>(
511 compaction_style_string_map, value,
512 reinterpret_cast<CompactionStyle*>(opt_address));
513 case OptionType::kCompactionPri:
514 return ParseEnum<CompactionPri>(
515 compaction_pri_string_map, value,
516 reinterpret_cast<CompactionPri*>(opt_address));
517 case OptionType::kCompressionType:
518 return ParseEnum<CompressionType>(
519 compression_type_string_map, value,
520 reinterpret_cast<CompressionType*>(opt_address));
521 case OptionType::kVectorCompressionType:
522 return ParseVectorCompressionType(
523 value, reinterpret_cast<std::vector<CompressionType>*>(opt_address));
524 case OptionType::kSliceTransform:
525 return ParseSliceTransform(
526 value, reinterpret_cast<std::shared_ptr<const SliceTransform>*>(
527 opt_address));
528 case OptionType::kChecksumType:
529 return ParseEnum<ChecksumType>(
530 checksum_type_string_map, value,
531 reinterpret_cast<ChecksumType*>(opt_address));
532 case OptionType::kBlockBasedTableIndexType:
533 return ParseEnum<BlockBasedTableOptions::IndexType>(
534 block_base_table_index_type_string_map, value,
535 reinterpret_cast<BlockBasedTableOptions::IndexType*>(opt_address));
536 case OptionType::kBlockBasedTableDataBlockIndexType:
537 return ParseEnum<BlockBasedTableOptions::DataBlockIndexType>(
538 block_base_table_data_block_index_type_string_map, value,
539 reinterpret_cast<BlockBasedTableOptions::DataBlockIndexType*>(
540 opt_address));
541 case OptionType::kBlockBasedTableIndexShorteningMode:
542 return ParseEnum<BlockBasedTableOptions::IndexShorteningMode>(
543 block_base_table_index_shortening_mode_string_map, value,
544 reinterpret_cast<BlockBasedTableOptions::IndexShorteningMode*>(
545 opt_address));
546 case OptionType::kEncodingType:
547 return ParseEnum<EncodingType>(
548 encoding_type_string_map, value,
549 reinterpret_cast<EncodingType*>(opt_address));
550 case OptionType::kWALRecoveryMode:
551 return ParseEnum<WALRecoveryMode>(
552 wal_recovery_mode_string_map, value,
553 reinterpret_cast<WALRecoveryMode*>(opt_address));
554 case OptionType::kAccessHint:
555 return ParseEnum<DBOptions::AccessHint>(
556 access_hint_string_map, value,
557 reinterpret_cast<DBOptions::AccessHint*>(opt_address));
558 case OptionType::kInfoLogLevel:
559 return ParseEnum<InfoLogLevel>(
560 info_log_level_string_map, value,
561 reinterpret_cast<InfoLogLevel*>(opt_address));
562 case OptionType::kCompactionOptionsFIFO: {
563 if (!FIFOCompactionOptionsSpecialCase(
564 value, reinterpret_cast<CompactionOptionsFIFO*>(opt_address))) {
565 return ParseStructOptions<CompactionOptionsFIFO>(
566 value, reinterpret_cast<CompactionOptionsFIFO*>(opt_address),
567 fifo_compaction_options_type_info);
568 }
569 return true;
570 }
571 case OptionType::kLRUCacheOptions: {
572 return ParseStructOptions<LRUCacheOptions>(value,
573 reinterpret_cast<LRUCacheOptions*>(opt_address),
574 lru_cache_options_type_info);
575 }
576 case OptionType::kCompactionOptionsUniversal:
577 return ParseStructOptions<CompactionOptionsUniversal>(
578 value, reinterpret_cast<CompactionOptionsUniversal*>(opt_address),
579 universal_compaction_options_type_info);
580 case OptionType::kCompactionStopStyle:
581 return ParseEnum<CompactionStopStyle>(
582 compaction_stop_style_string_map, value,
583 reinterpret_cast<CompactionStopStyle*>(opt_address));
584 default:
585 return false;
586 }
587 return true;
588 }
589
SerializeSingleOptionHelper(const char * opt_address,const OptionType opt_type,std::string * value)590 bool SerializeSingleOptionHelper(const char* opt_address,
591 const OptionType opt_type,
592 std::string* value) {
593
594 assert(value);
595 switch (opt_type) {
596 case OptionType::kBoolean:
597 *value = *(reinterpret_cast<const bool*>(opt_address)) ? "true" : "false";
598 break;
599 case OptionType::kInt:
600 *value = ToString(*(reinterpret_cast<const int*>(opt_address)));
601 break;
602 case OptionType::kInt32T:
603 *value = ToString(*(reinterpret_cast<const int32_t*>(opt_address)));
604 break;
605 case OptionType::kInt64T:
606 {
607 int64_t v;
608 GetUnaligned(reinterpret_cast<const int64_t*>(opt_address), &v);
609 *value = ToString(v);
610 }
611 break;
612 case OptionType::kVectorInt:
613 return SerializeIntVector(
614 *reinterpret_cast<const std::vector<int>*>(opt_address), value);
615 case OptionType::kUInt:
616 *value = ToString(*(reinterpret_cast<const unsigned int*>(opt_address)));
617 break;
618 case OptionType::kUInt32T:
619 *value = ToString(*(reinterpret_cast<const uint32_t*>(opt_address)));
620 break;
621 case OptionType::kUInt64T:
622 {
623 uint64_t v;
624 GetUnaligned(reinterpret_cast<const uint64_t*>(opt_address), &v);
625 *value = ToString(v);
626 }
627 break;
628 case OptionType::kSizeT:
629 {
630 size_t v;
631 GetUnaligned(reinterpret_cast<const size_t*>(opt_address), &v);
632 *value = ToString(v);
633 }
634 break;
635 case OptionType::kDouble:
636 *value = ToString(*(reinterpret_cast<const double*>(opt_address)));
637 break;
638 case OptionType::kString:
639 *value = EscapeOptionString(
640 *(reinterpret_cast<const std::string*>(opt_address)));
641 break;
642 case OptionType::kCompactionStyle:
643 return SerializeEnum<CompactionStyle>(
644 compaction_style_string_map,
645 *(reinterpret_cast<const CompactionStyle*>(opt_address)), value);
646 case OptionType::kCompactionPri:
647 return SerializeEnum<CompactionPri>(
648 compaction_pri_string_map,
649 *(reinterpret_cast<const CompactionPri*>(opt_address)), value);
650 case OptionType::kCompressionType:
651 return SerializeEnum<CompressionType>(
652 compression_type_string_map,
653 *(reinterpret_cast<const CompressionType*>(opt_address)), value);
654 case OptionType::kVectorCompressionType:
655 return SerializeVectorCompressionType(
656 *(reinterpret_cast<const std::vector<CompressionType>*>(opt_address)),
657 value);
658 break;
659 case OptionType::kSliceTransform: {
660 const auto* slice_transform_ptr =
661 reinterpret_cast<const std::shared_ptr<const SliceTransform>*>(
662 opt_address);
663 *value = slice_transform_ptr->get() ? slice_transform_ptr->get()->Name()
664 : kNullptrString;
665 break;
666 }
667 case OptionType::kTableFactory: {
668 const auto* table_factory_ptr =
669 reinterpret_cast<const std::shared_ptr<const TableFactory>*>(
670 opt_address);
671 *value = table_factory_ptr->get() ? table_factory_ptr->get()->Name()
672 : kNullptrString;
673 break;
674 }
675 case OptionType::kComparator: {
676 // it's a const pointer of const Comparator*
677 const auto* ptr = reinterpret_cast<const Comparator* const*>(opt_address);
678 // Since the user-specified comparator will be wrapped by
679 // InternalKeyComparator, we should persist the user-specified one
680 // instead of InternalKeyComparator.
681 if (*ptr == nullptr) {
682 *value = kNullptrString;
683 } else {
684 const Comparator* root_comp = (*ptr)->GetRootComparator();
685 if (root_comp == nullptr) {
686 root_comp = (*ptr);
687 }
688 *value = root_comp->Name();
689 }
690 break;
691 }
692 case OptionType::kCompactionFilter: {
693 // it's a const pointer of const CompactionFilter*
694 const auto* ptr =
695 reinterpret_cast<const CompactionFilter* const*>(opt_address);
696 *value = *ptr ? (*ptr)->Name() : kNullptrString;
697 break;
698 }
699 case OptionType::kCompactionFilterFactory: {
700 const auto* ptr =
701 reinterpret_cast<const std::shared_ptr<CompactionFilterFactory>*>(
702 opt_address);
703 *value = ptr->get() ? ptr->get()->Name() : kNullptrString;
704 break;
705 }
706 case OptionType::kMemTableRepFactory: {
707 const auto* ptr =
708 reinterpret_cast<const std::shared_ptr<MemTableRepFactory>*>(
709 opt_address);
710 *value = ptr->get() ? ptr->get()->Name() : kNullptrString;
711 break;
712 }
713 case OptionType::kMergeOperator: {
714 const auto* ptr =
715 reinterpret_cast<const std::shared_ptr<MergeOperator>*>(opt_address);
716 *value = ptr->get() ? ptr->get()->Name() : kNullptrString;
717 break;
718 }
719 case OptionType::kFilterPolicy: {
720 const auto* ptr =
721 reinterpret_cast<const std::shared_ptr<FilterPolicy>*>(opt_address);
722 *value = ptr->get() ? ptr->get()->Name() : kNullptrString;
723 break;
724 }
725 case OptionType::kChecksumType:
726 return SerializeEnum<ChecksumType>(
727 checksum_type_string_map,
728 *reinterpret_cast<const ChecksumType*>(opt_address), value);
729 case OptionType::kBlockBasedTableIndexType:
730 return SerializeEnum<BlockBasedTableOptions::IndexType>(
731 block_base_table_index_type_string_map,
732 *reinterpret_cast<const BlockBasedTableOptions::IndexType*>(
733 opt_address),
734 value);
735 case OptionType::kBlockBasedTableDataBlockIndexType:
736 return SerializeEnum<BlockBasedTableOptions::DataBlockIndexType>(
737 block_base_table_data_block_index_type_string_map,
738 *reinterpret_cast<const BlockBasedTableOptions::DataBlockIndexType*>(
739 opt_address),
740 value);
741 case OptionType::kBlockBasedTableIndexShorteningMode:
742 return SerializeEnum<BlockBasedTableOptions::IndexShorteningMode>(
743 block_base_table_index_shortening_mode_string_map,
744 *reinterpret_cast<const BlockBasedTableOptions::IndexShorteningMode*>(
745 opt_address),
746 value);
747 case OptionType::kFlushBlockPolicyFactory: {
748 const auto* ptr =
749 reinterpret_cast<const std::shared_ptr<FlushBlockPolicyFactory>*>(
750 opt_address);
751 *value = ptr->get() ? ptr->get()->Name() : kNullptrString;
752 break;
753 }
754 case OptionType::kEncodingType:
755 return SerializeEnum<EncodingType>(
756 encoding_type_string_map,
757 *reinterpret_cast<const EncodingType*>(opt_address), value);
758 case OptionType::kWALRecoveryMode:
759 return SerializeEnum<WALRecoveryMode>(
760 wal_recovery_mode_string_map,
761 *reinterpret_cast<const WALRecoveryMode*>(opt_address), value);
762 case OptionType::kAccessHint:
763 return SerializeEnum<DBOptions::AccessHint>(
764 access_hint_string_map,
765 *reinterpret_cast<const DBOptions::AccessHint*>(opt_address), value);
766 case OptionType::kInfoLogLevel:
767 return SerializeEnum<InfoLogLevel>(
768 info_log_level_string_map,
769 *reinterpret_cast<const InfoLogLevel*>(opt_address), value);
770 case OptionType::kCompactionOptionsFIFO:
771 return SerializeStruct<CompactionOptionsFIFO>(
772 *reinterpret_cast<const CompactionOptionsFIFO*>(opt_address), value,
773 fifo_compaction_options_type_info);
774 case OptionType::kCompactionOptionsUniversal:
775 return SerializeStruct<CompactionOptionsUniversal>(
776 *reinterpret_cast<const CompactionOptionsUniversal*>(opt_address),
777 value, universal_compaction_options_type_info);
778 case OptionType::kCompactionStopStyle:
779 return SerializeEnum<CompactionStopStyle>(
780 compaction_stop_style_string_map,
781 *reinterpret_cast<const CompactionStopStyle*>(opt_address), value);
782 default:
783 return false;
784 }
785 return true;
786 }
787
GetMutableOptionsFromStrings(const MutableCFOptions & base_options,const std::unordered_map<std::string,std::string> & options_map,Logger * info_log,MutableCFOptions * new_options)788 Status GetMutableOptionsFromStrings(
789 const MutableCFOptions& base_options,
790 const std::unordered_map<std::string, std::string>& options_map,
791 Logger* info_log, MutableCFOptions* new_options) {
792 assert(new_options);
793 *new_options = base_options;
794 for (const auto& o : options_map) {
795 try {
796 auto iter = cf_options_type_info.find(o.first);
797 if (iter == cf_options_type_info.end()) {
798 return Status::InvalidArgument("Unrecognized option: " + o.first);
799 }
800 const auto& opt_info = iter->second;
801 if (!opt_info.is_mutable) {
802 return Status::InvalidArgument("Option not changeable: " + o.first);
803 }
804 if (opt_info.verification == OptionVerificationType::kDeprecated) {
805 // log warning when user tries to set a deprecated option but don't fail
806 // the call for compatibility.
807 ROCKS_LOG_WARN(info_log, "%s is a deprecated option and cannot be set",
808 o.first.c_str());
809 continue;
810 }
811 bool is_ok = ParseOptionHelper(
812 reinterpret_cast<char*>(new_options) + opt_info.mutable_offset,
813 opt_info.type, o.second);
814 if (!is_ok) {
815 return Status::InvalidArgument("Error parsing " + o.first);
816 }
817 } catch (std::exception& e) {
818 return Status::InvalidArgument("Error parsing " + o.first + ":" +
819 std::string(e.what()));
820 }
821 }
822 return Status::OK();
823 }
824
GetMutableDBOptionsFromStrings(const MutableDBOptions & base_options,const std::unordered_map<std::string,std::string> & options_map,MutableDBOptions * new_options)825 Status GetMutableDBOptionsFromStrings(
826 const MutableDBOptions& base_options,
827 const std::unordered_map<std::string, std::string>& options_map,
828 MutableDBOptions* new_options) {
829 assert(new_options);
830 *new_options = base_options;
831 for (const auto& o : options_map) {
832 try {
833 auto iter = db_options_type_info.find(o.first);
834 if (iter == db_options_type_info.end()) {
835 return Status::InvalidArgument("Unrecognized option: " + o.first);
836 }
837 const auto& opt_info = iter->second;
838 if (!opt_info.is_mutable) {
839 return Status::InvalidArgument("Option not changeable: " + o.first);
840 }
841 bool is_ok = ParseOptionHelper(
842 reinterpret_cast<char*>(new_options) + opt_info.mutable_offset,
843 opt_info.type, o.second);
844 if (!is_ok) {
845 return Status::InvalidArgument("Error parsing " + o.first);
846 }
847 } catch (std::exception& e) {
848 return Status::InvalidArgument("Error parsing " + o.first + ":" +
849 std::string(e.what()));
850 }
851 }
852 return Status::OK();
853 }
854
StringToMap(const std::string & opts_str,std::unordered_map<std::string,std::string> * opts_map)855 Status StringToMap(const std::string& opts_str,
856 std::unordered_map<std::string, std::string>* opts_map) {
857 assert(opts_map);
858 // Example:
859 // opts_str = "write_buffer_size=1024;max_write_buffer_number=2;"
860 // "nested_opt={opt1=1;opt2=2};max_bytes_for_level_base=100"
861 size_t pos = 0;
862 std::string opts = trim(opts_str);
863 while (pos < opts.size()) {
864 size_t eq_pos = opts.find('=', pos);
865 if (eq_pos == std::string::npos) {
866 return Status::InvalidArgument("Mismatched key value pair, '=' expected");
867 }
868 std::string key = trim(opts.substr(pos, eq_pos - pos));
869 if (key.empty()) {
870 return Status::InvalidArgument("Empty key found");
871 }
872
873 // skip space after '=' and look for '{' for possible nested options
874 pos = eq_pos + 1;
875 while (pos < opts.size() && isspace(opts[pos])) {
876 ++pos;
877 }
878 // Empty value at the end
879 if (pos >= opts.size()) {
880 (*opts_map)[key] = "";
881 break;
882 }
883 if (opts[pos] == '{') {
884 int count = 1;
885 size_t brace_pos = pos + 1;
886 while (brace_pos < opts.size()) {
887 if (opts[brace_pos] == '{') {
888 ++count;
889 } else if (opts[brace_pos] == '}') {
890 --count;
891 if (count == 0) {
892 break;
893 }
894 }
895 ++brace_pos;
896 }
897 // found the matching closing brace
898 if (count == 0) {
899 (*opts_map)[key] = trim(opts.substr(pos + 1, brace_pos - pos - 1));
900 // skip all whitespace and move to the next ';'
901 // brace_pos points to the next position after the matching '}'
902 pos = brace_pos + 1;
903 while (pos < opts.size() && isspace(opts[pos])) {
904 ++pos;
905 }
906 if (pos < opts.size() && opts[pos] != ';') {
907 return Status::InvalidArgument(
908 "Unexpected chars after nested options");
909 }
910 ++pos;
911 } else {
912 return Status::InvalidArgument(
913 "Mismatched curly braces for nested options");
914 }
915 } else {
916 size_t sc_pos = opts.find(';', pos);
917 if (sc_pos == std::string::npos) {
918 (*opts_map)[key] = trim(opts.substr(pos));
919 // It either ends with a trailing semi-colon or the last key-value pair
920 break;
921 } else {
922 (*opts_map)[key] = trim(opts.substr(pos, sc_pos - pos));
923 }
924 pos = sc_pos + 1;
925 }
926 }
927
928 return Status::OK();
929 }
930
ParseCompressionOptions(const std::string & value,const std::string & name,CompressionOptions & compression_opts)931 Status ParseCompressionOptions(const std::string& value, const std::string& name,
932 CompressionOptions& compression_opts) {
933 size_t start = 0;
934 size_t end = value.find(':');
935 if (end == std::string::npos) {
936 return Status::InvalidArgument("unable to parse the specified CF option " +
937 name);
938 }
939 compression_opts.window_bits = ParseInt(value.substr(start, end - start));
940 start = end + 1;
941 end = value.find(':', start);
942 if (end == std::string::npos) {
943 return Status::InvalidArgument("unable to parse the specified CF option " +
944 name);
945 }
946 compression_opts.level = ParseInt(value.substr(start, end - start));
947 start = end + 1;
948 if (start >= value.size()) {
949 return Status::InvalidArgument("unable to parse the specified CF option " +
950 name);
951 }
952 end = value.find(':', start);
953 compression_opts.strategy =
954 ParseInt(value.substr(start, value.size() - start));
955 // max_dict_bytes is optional for backwards compatibility
956 if (end != std::string::npos) {
957 start = end + 1;
958 if (start >= value.size()) {
959 return Status::InvalidArgument(
960 "unable to parse the specified CF option " + name);
961 }
962 compression_opts.max_dict_bytes =
963 ParseInt(value.substr(start, value.size() - start));
964 end = value.find(':', start);
965 }
966 // zstd_max_train_bytes is optional for backwards compatibility
967 if (end != std::string::npos) {
968 start = end + 1;
969 if (start >= value.size()) {
970 return Status::InvalidArgument(
971 "unable to parse the specified CF option " + name);
972 }
973 compression_opts.zstd_max_train_bytes =
974 ParseInt(value.substr(start, value.size() - start));
975 end = value.find(':', start);
976 }
977 // enabled is optional for backwards compatibility
978 if (end != std::string::npos) {
979 start = end + 1;
980 if (start >= value.size()) {
981 return Status::InvalidArgument(
982 "unable to parse the specified CF option " + name);
983 }
984 compression_opts.enabled =
985 ParseBoolean("", value.substr(start, value.size() - start));
986 }
987 return Status::OK();
988 }
989
ParseColumnFamilyOption(const std::string & name,const std::string & org_value,ColumnFamilyOptions * new_options,bool input_strings_escaped=false)990 Status ParseColumnFamilyOption(const std::string& name,
991 const std::string& org_value,
992 ColumnFamilyOptions* new_options,
993 bool input_strings_escaped = false) {
994 const std::string& value =
995 input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
996 try {
997 if (name == "block_based_table_factory") {
998 // Nested options
999 BlockBasedTableOptions table_opt, base_table_options;
1000 BlockBasedTableFactory* block_based_table_factory =
1001 static_cast_with_check<BlockBasedTableFactory, TableFactory>(
1002 new_options->table_factory.get());
1003 if (block_based_table_factory != nullptr) {
1004 base_table_options = block_based_table_factory->table_options();
1005 }
1006 Status table_opt_s = GetBlockBasedTableOptionsFromString(
1007 base_table_options, value, &table_opt);
1008 if (!table_opt_s.ok()) {
1009 return Status::InvalidArgument(
1010 "unable to parse the specified CF option " + name);
1011 }
1012 new_options->table_factory.reset(NewBlockBasedTableFactory(table_opt));
1013 } else if (name == "plain_table_factory") {
1014 // Nested options
1015 PlainTableOptions table_opt, base_table_options;
1016 PlainTableFactory* plain_table_factory =
1017 static_cast_with_check<PlainTableFactory, TableFactory>(
1018 new_options->table_factory.get());
1019 if (plain_table_factory != nullptr) {
1020 base_table_options = plain_table_factory->table_options();
1021 }
1022 Status table_opt_s = GetPlainTableOptionsFromString(
1023 base_table_options, value, &table_opt);
1024 if (!table_opt_s.ok()) {
1025 return Status::InvalidArgument(
1026 "unable to parse the specified CF option " + name);
1027 }
1028 new_options->table_factory.reset(NewPlainTableFactory(table_opt));
1029 } else if (name == "memtable") {
1030 std::unique_ptr<MemTableRepFactory> new_mem_factory;
1031 Status mem_factory_s =
1032 GetMemTableRepFactoryFromString(value, &new_mem_factory);
1033 if (!mem_factory_s.ok()) {
1034 return Status::InvalidArgument(
1035 "unable to parse the specified CF option " + name);
1036 }
1037 new_options->memtable_factory.reset(new_mem_factory.release());
1038 } else if (name == "bottommost_compression_opts") {
1039 Status s = ParseCompressionOptions(
1040 value, name, new_options->bottommost_compression_opts);
1041 if (!s.ok()) {
1042 return s;
1043 }
1044 } else if (name == "compression_opts") {
1045 Status s =
1046 ParseCompressionOptions(value, name, new_options->compression_opts);
1047 if (!s.ok()) {
1048 return s;
1049 }
1050 } else {
1051 if (name == kNameComparator) {
1052 // Try to get comparator from object registry first.
1053 // Only support static comparator for now.
1054 Status status = ObjectRegistry::NewInstance()->NewStaticObject(
1055 value, &new_options->comparator);
1056 if (status.ok()) {
1057 return status;
1058 }
1059 } else if (name == kNameMergeOperator) {
1060 // Try to get merge operator from object registry first.
1061 std::shared_ptr<MergeOperator> mo;
1062 Status status =
1063 ObjectRegistry::NewInstance()->NewSharedObject<MergeOperator>(
1064 value, &new_options->merge_operator);
1065 // Only support static comparator for now.
1066 if (status.ok()) {
1067 return status;
1068 }
1069 }
1070
1071 auto iter = cf_options_type_info.find(name);
1072 if (iter == cf_options_type_info.end()) {
1073 return Status::InvalidArgument(
1074 "Unable to parse the specified CF option " + name);
1075 }
1076 const auto& opt_info = iter->second;
1077 if (opt_info.verification != OptionVerificationType::kDeprecated &&
1078 ParseOptionHelper(
1079 reinterpret_cast<char*>(new_options) + opt_info.offset,
1080 opt_info.type, value)) {
1081 return Status::OK();
1082 }
1083 switch (opt_info.verification) {
1084 case OptionVerificationType::kByName:
1085 case OptionVerificationType::kByNameAllowNull:
1086 case OptionVerificationType::kByNameAllowFromNull:
1087 return Status::NotSupported(
1088 "Deserializing the specified CF option " + name +
1089 " is not supported");
1090 case OptionVerificationType::kDeprecated:
1091 return Status::OK();
1092 default:
1093 return Status::InvalidArgument(
1094 "Unable to parse the specified CF option " + name);
1095 }
1096 }
1097 } catch (const std::exception&) {
1098 return Status::InvalidArgument(
1099 "unable to parse the specified option " + name);
1100 }
1101 return Status::OK();
1102 }
1103
1104 template <typename T>
SerializeSingleStructOption(std::string * opt_string,const T & options,const std::unordered_map<std::string,OptionTypeInfo> & type_info,const std::string & name,const std::string & delimiter)1105 bool SerializeSingleStructOption(
1106 std::string* opt_string, const T& options,
1107 const std::unordered_map<std::string, OptionTypeInfo>& type_info,
1108 const std::string& name, const std::string& delimiter) {
1109 auto iter = type_info.find(name);
1110 if (iter == type_info.end()) {
1111 return false;
1112 }
1113 auto& opt_info = iter->second;
1114 const char* opt_address =
1115 reinterpret_cast<const char*>(&options) + opt_info.offset;
1116 std::string value;
1117 bool result = SerializeSingleOptionHelper(opt_address, opt_info.type, &value);
1118 if (result) {
1119 *opt_string = name + "=" + value + delimiter;
1120 }
1121 return result;
1122 }
1123
1124 template <typename T>
GetStringFromStruct(std::string * opt_string,const T & options,const std::unordered_map<std::string,OptionTypeInfo> & type_info,const std::string & delimiter)1125 Status GetStringFromStruct(
1126 std::string* opt_string, const T& options,
1127 const std::unordered_map<std::string, OptionTypeInfo>& type_info,
1128 const std::string& delimiter) {
1129 assert(opt_string);
1130 opt_string->clear();
1131 for (auto iter = type_info.begin(); iter != type_info.end(); ++iter) {
1132 if (iter->second.verification == OptionVerificationType::kDeprecated) {
1133 // If the option is no longer used in rocksdb and marked as deprecated,
1134 // we skip it in the serialization.
1135 continue;
1136 }
1137 std::string single_output;
1138 bool result = SerializeSingleStructOption<T>(
1139 &single_output, options, type_info, iter->first, delimiter);
1140 if (result) {
1141 opt_string->append(single_output);
1142 } else {
1143 return Status::InvalidArgument("failed to serialize %s\n",
1144 iter->first.c_str());
1145 }
1146 assert(result);
1147 }
1148 return Status::OK();
1149 }
1150
GetStringFromDBOptions(std::string * opt_string,const DBOptions & db_options,const std::string & delimiter)1151 Status GetStringFromDBOptions(std::string* opt_string,
1152 const DBOptions& db_options,
1153 const std::string& delimiter) {
1154 return GetStringFromStruct<DBOptions>(opt_string, db_options,
1155 db_options_type_info, delimiter);
1156 }
1157
GetStringFromColumnFamilyOptions(std::string * opt_string,const ColumnFamilyOptions & cf_options,const std::string & delimiter)1158 Status GetStringFromColumnFamilyOptions(std::string* opt_string,
1159 const ColumnFamilyOptions& cf_options,
1160 const std::string& delimiter) {
1161 return GetStringFromStruct<ColumnFamilyOptions>(
1162 opt_string, cf_options, cf_options_type_info, delimiter);
1163 }
1164
GetStringFromCompressionType(std::string * compression_str,CompressionType compression_type)1165 Status GetStringFromCompressionType(std::string* compression_str,
1166 CompressionType compression_type) {
1167 bool ok = SerializeEnum<CompressionType>(compression_type_string_map,
1168 compression_type, compression_str);
1169 if (ok) {
1170 return Status::OK();
1171 } else {
1172 return Status::InvalidArgument("Invalid compression types");
1173 }
1174 }
1175
GetSupportedCompressions()1176 std::vector<CompressionType> GetSupportedCompressions() {
1177 std::vector<CompressionType> supported_compressions;
1178 for (const auto& comp_to_name : compression_type_string_map) {
1179 CompressionType t = comp_to_name.second;
1180 if (t != kDisableCompressionOption && CompressionTypeSupported(t)) {
1181 supported_compressions.push_back(t);
1182 }
1183 }
1184 return supported_compressions;
1185 }
1186
ParseDBOption(const std::string & name,const std::string & org_value,DBOptions * new_options,bool input_strings_escaped=false)1187 Status ParseDBOption(const std::string& name,
1188 const std::string& org_value,
1189 DBOptions* new_options,
1190 bool input_strings_escaped = false) {
1191 const std::string& value =
1192 input_strings_escaped ? UnescapeOptionString(org_value) : org_value;
1193 try {
1194 if (name == "rate_limiter_bytes_per_sec") {
1195 new_options->rate_limiter.reset(
1196 NewGenericRateLimiter(static_cast<int64_t>(ParseUint64(value))));
1197 } else if (name == kNameEnv) {
1198 // Currently `Env` can be deserialized from object registry only.
1199 Env* env = new_options->env;
1200 Status status = Env::LoadEnv(value, &env);
1201 // Only support static env for now.
1202 if (status.ok()) {
1203 new_options->env = env;
1204 }
1205 } else {
1206 auto iter = db_options_type_info.find(name);
1207 if (iter == db_options_type_info.end()) {
1208 return Status::InvalidArgument("Unrecognized option DBOptions:", name);
1209 }
1210 const auto& opt_info = iter->second;
1211 if (opt_info.verification != OptionVerificationType::kDeprecated &&
1212 ParseOptionHelper(
1213 reinterpret_cast<char*>(new_options) + opt_info.offset,
1214 opt_info.type, value)) {
1215 return Status::OK();
1216 }
1217 switch (opt_info.verification) {
1218 case OptionVerificationType::kByName:
1219 case OptionVerificationType::kByNameAllowNull:
1220 return Status::NotSupported(
1221 "Deserializing the specified DB option " + name +
1222 " is not supported");
1223 case OptionVerificationType::kDeprecated:
1224 return Status::OK();
1225 default:
1226 return Status::InvalidArgument(
1227 "Unable to parse the specified DB option " + name);
1228 }
1229 }
1230 } catch (const std::exception&) {
1231 return Status::InvalidArgument("Unable to parse DBOptions:", name);
1232 }
1233 return Status::OK();
1234 }
1235
GetColumnFamilyOptionsFromMap(const ColumnFamilyOptions & base_options,const std::unordered_map<std::string,std::string> & opts_map,ColumnFamilyOptions * new_options,bool input_strings_escaped,bool ignore_unknown_options)1236 Status GetColumnFamilyOptionsFromMap(
1237 const ColumnFamilyOptions& base_options,
1238 const std::unordered_map<std::string, std::string>& opts_map,
1239 ColumnFamilyOptions* new_options, bool input_strings_escaped,
1240 bool ignore_unknown_options) {
1241 return GetColumnFamilyOptionsFromMapInternal(
1242 base_options, opts_map, new_options, input_strings_escaped, nullptr,
1243 ignore_unknown_options);
1244 }
1245
GetColumnFamilyOptionsFromMapInternal(const ColumnFamilyOptions & base_options,const std::unordered_map<std::string,std::string> & opts_map,ColumnFamilyOptions * new_options,bool input_strings_escaped,std::vector<std::string> * unsupported_options_names,bool ignore_unknown_options)1246 Status GetColumnFamilyOptionsFromMapInternal(
1247 const ColumnFamilyOptions& base_options,
1248 const std::unordered_map<std::string, std::string>& opts_map,
1249 ColumnFamilyOptions* new_options, bool input_strings_escaped,
1250 std::vector<std::string>* unsupported_options_names,
1251 bool ignore_unknown_options) {
1252 assert(new_options);
1253 *new_options = base_options;
1254 if (unsupported_options_names) {
1255 unsupported_options_names->clear();
1256 }
1257 for (const auto& o : opts_map) {
1258 auto s = ParseColumnFamilyOption(o.first, o.second, new_options,
1259 input_strings_escaped);
1260 if (!s.ok()) {
1261 if (s.IsNotSupported()) {
1262 // If the deserialization of the specified option is not supported
1263 // and an output vector of unsupported_options is provided, then
1264 // we log the name of the unsupported option and proceed.
1265 if (unsupported_options_names != nullptr) {
1266 unsupported_options_names->push_back(o.first);
1267 }
1268 // Note that we still return Status::OK in such case to maintain
1269 // the backward compatibility in the old public API defined in
1270 // rocksdb/convenience.h
1271 } else if (s.IsInvalidArgument() && ignore_unknown_options) {
1272 continue;
1273 } else {
1274 // Restore "new_options" to the default "base_options".
1275 *new_options = base_options;
1276 return s;
1277 }
1278 }
1279 }
1280 return Status::OK();
1281 }
1282
GetColumnFamilyOptionsFromString(const ColumnFamilyOptions & base_options,const std::string & opts_str,ColumnFamilyOptions * new_options)1283 Status GetColumnFamilyOptionsFromString(
1284 const ColumnFamilyOptions& base_options,
1285 const std::string& opts_str,
1286 ColumnFamilyOptions* new_options) {
1287 std::unordered_map<std::string, std::string> opts_map;
1288 Status s = StringToMap(opts_str, &opts_map);
1289 if (!s.ok()) {
1290 *new_options = base_options;
1291 return s;
1292 }
1293 return GetColumnFamilyOptionsFromMap(base_options, opts_map, new_options);
1294 }
1295
GetDBOptionsFromMap(const DBOptions & base_options,const std::unordered_map<std::string,std::string> & opts_map,DBOptions * new_options,bool input_strings_escaped,bool ignore_unknown_options)1296 Status GetDBOptionsFromMap(
1297 const DBOptions& base_options,
1298 const std::unordered_map<std::string, std::string>& opts_map,
1299 DBOptions* new_options, bool input_strings_escaped,
1300 bool ignore_unknown_options) {
1301 return GetDBOptionsFromMapInternal(base_options, opts_map, new_options,
1302 input_strings_escaped, nullptr,
1303 ignore_unknown_options);
1304 }
1305
GetDBOptionsFromMapInternal(const DBOptions & base_options,const std::unordered_map<std::string,std::string> & opts_map,DBOptions * new_options,bool input_strings_escaped,std::vector<std::string> * unsupported_options_names,bool ignore_unknown_options)1306 Status GetDBOptionsFromMapInternal(
1307 const DBOptions& base_options,
1308 const std::unordered_map<std::string, std::string>& opts_map,
1309 DBOptions* new_options, bool input_strings_escaped,
1310 std::vector<std::string>* unsupported_options_names,
1311 bool ignore_unknown_options) {
1312 assert(new_options);
1313 *new_options = base_options;
1314 if (unsupported_options_names) {
1315 unsupported_options_names->clear();
1316 }
1317 for (const auto& o : opts_map) {
1318 auto s = ParseDBOption(o.first, o.second,
1319 new_options, input_strings_escaped);
1320 if (!s.ok()) {
1321 if (s.IsNotSupported()) {
1322 // If the deserialization of the specified option is not supported
1323 // and an output vector of unsupported_options is provided, then
1324 // we log the name of the unsupported option and proceed.
1325 if (unsupported_options_names != nullptr) {
1326 unsupported_options_names->push_back(o.first);
1327 }
1328 // Note that we still return Status::OK in such case to maintain
1329 // the backward compatibility in the old public API defined in
1330 // rocksdb/convenience.h
1331 } else if (s.IsInvalidArgument() && ignore_unknown_options) {
1332 continue;
1333 } else {
1334 // Restore "new_options" to the default "base_options".
1335 *new_options = base_options;
1336 return s;
1337 }
1338 }
1339 }
1340 return Status::OK();
1341 }
1342
GetDBOptionsFromString(const DBOptions & base_options,const std::string & opts_str,DBOptions * new_options)1343 Status GetDBOptionsFromString(
1344 const DBOptions& base_options,
1345 const std::string& opts_str,
1346 DBOptions* new_options) {
1347 std::unordered_map<std::string, std::string> opts_map;
1348 Status s = StringToMap(opts_str, &opts_map);
1349 if (!s.ok()) {
1350 *new_options = base_options;
1351 return s;
1352 }
1353 return GetDBOptionsFromMap(base_options, opts_map, new_options);
1354 }
1355
GetOptionsFromString(const Options & base_options,const std::string & opts_str,Options * new_options)1356 Status GetOptionsFromString(const Options& base_options,
1357 const std::string& opts_str, Options* new_options) {
1358 std::unordered_map<std::string, std::string> opts_map;
1359 Status s = StringToMap(opts_str, &opts_map);
1360 if (!s.ok()) {
1361 return s;
1362 }
1363 DBOptions new_db_options(base_options);
1364 ColumnFamilyOptions new_cf_options(base_options);
1365 for (const auto& o : opts_map) {
1366 if (ParseDBOption(o.first, o.second, &new_db_options).ok()) {
1367 } else if (ParseColumnFamilyOption(
1368 o.first, o.second, &new_cf_options).ok()) {
1369 } else {
1370 return Status::InvalidArgument("Can't parse option " + o.first);
1371 }
1372 }
1373 *new_options = Options(new_db_options, new_cf_options);
1374 return Status::OK();
1375 }
1376
GetTableFactoryFromMap(const std::string & factory_name,const std::unordered_map<std::string,std::string> & opt_map,std::shared_ptr<TableFactory> * table_factory,bool ignore_unknown_options)1377 Status GetTableFactoryFromMap(
1378 const std::string& factory_name,
1379 const std::unordered_map<std::string, std::string>& opt_map,
1380 std::shared_ptr<TableFactory>* table_factory, bool ignore_unknown_options) {
1381 Status s;
1382 if (factory_name == BlockBasedTableFactory().Name()) {
1383 BlockBasedTableOptions bbt_opt;
1384 s = GetBlockBasedTableOptionsFromMap(BlockBasedTableOptions(), opt_map,
1385 &bbt_opt,
1386 true, /* input_strings_escaped */
1387 ignore_unknown_options);
1388 if (!s.ok()) {
1389 return s;
1390 }
1391 table_factory->reset(new BlockBasedTableFactory(bbt_opt));
1392 return Status::OK();
1393 } else if (factory_name == PlainTableFactory().Name()) {
1394 PlainTableOptions pt_opt;
1395 s = GetPlainTableOptionsFromMap(PlainTableOptions(), opt_map, &pt_opt,
1396 true, /* input_strings_escaped */
1397 ignore_unknown_options);
1398 if (!s.ok()) {
1399 return s;
1400 }
1401 table_factory->reset(new PlainTableFactory(pt_opt));
1402 return Status::OK();
1403 }
1404 // Return OK for not supported table factories as TableFactory
1405 // Deserialization is optional.
1406 table_factory->reset();
1407 return Status::OK();
1408 }
1409
1410 std::unordered_map<std::string, OptionTypeInfo>
1411 OptionsHelper::db_options_type_info = {
1412 /*
1413 // not yet supported
1414 std::shared_ptr<Cache> row_cache;
1415 std::shared_ptr<DeleteScheduler> delete_scheduler;
1416 std::shared_ptr<Logger> info_log;
1417 std::shared_ptr<RateLimiter> rate_limiter;
1418 std::shared_ptr<Statistics> statistics;
1419 std::vector<DbPath> db_paths;
1420 std::vector<std::shared_ptr<EventListener>> listeners;
1421 */
1422 {"advise_random_on_open",
1423 {offsetof(struct DBOptions, advise_random_on_open),
1424 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1425 {"allow_mmap_reads",
1426 {offsetof(struct DBOptions, allow_mmap_reads), OptionType::kBoolean,
1427 OptionVerificationType::kNormal, false, 0}},
1428 {"allow_fallocate",
1429 {offsetof(struct DBOptions, allow_fallocate), OptionType::kBoolean,
1430 OptionVerificationType::kNormal, false, 0}},
1431 {"allow_mmap_writes",
1432 {offsetof(struct DBOptions, allow_mmap_writes), OptionType::kBoolean,
1433 OptionVerificationType::kNormal, false, 0}},
1434 {"use_direct_reads",
1435 {offsetof(struct DBOptions, use_direct_reads), OptionType::kBoolean,
1436 OptionVerificationType::kNormal, false, 0}},
1437 {"use_direct_writes",
1438 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1439 0}},
1440 {"use_direct_io_for_flush_and_compaction",
1441 {offsetof(struct DBOptions, use_direct_io_for_flush_and_compaction),
1442 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1443 {"allow_2pc",
1444 {offsetof(struct DBOptions, allow_2pc), OptionType::kBoolean,
1445 OptionVerificationType::kNormal, false, 0}},
1446 {"allow_os_buffer",
1447 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, true,
1448 0}},
1449 {"create_if_missing",
1450 {offsetof(struct DBOptions, create_if_missing), OptionType::kBoolean,
1451 OptionVerificationType::kNormal, false, 0}},
1452 {"create_missing_column_families",
1453 {offsetof(struct DBOptions, create_missing_column_families),
1454 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1455 {"disableDataSync",
1456 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1457 0}},
1458 {"disable_data_sync", // for compatibility
1459 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1460 0}},
1461 {"enable_thread_tracking",
1462 {offsetof(struct DBOptions, enable_thread_tracking),
1463 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1464 {"error_if_exists",
1465 {offsetof(struct DBOptions, error_if_exists), OptionType::kBoolean,
1466 OptionVerificationType::kNormal, false, 0}},
1467 {"is_fd_close_on_exec",
1468 {offsetof(struct DBOptions, is_fd_close_on_exec), OptionType::kBoolean,
1469 OptionVerificationType::kNormal, false, 0}},
1470 {"paranoid_checks",
1471 {offsetof(struct DBOptions, paranoid_checks), OptionType::kBoolean,
1472 OptionVerificationType::kNormal, false, 0}},
1473 {"skip_log_error_on_recovery",
1474 {offsetof(struct DBOptions, skip_log_error_on_recovery),
1475 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1476 {"skip_stats_update_on_db_open",
1477 {offsetof(struct DBOptions, skip_stats_update_on_db_open),
1478 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1479 {"skip_checking_sst_file_sizes_on_db_open",
1480 {offsetof(struct DBOptions, skip_checking_sst_file_sizes_on_db_open),
1481 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1482 {"new_table_reader_for_compaction_inputs",
1483 {offsetof(struct DBOptions, new_table_reader_for_compaction_inputs),
1484 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1485 {"compaction_readahead_size",
1486 {offsetof(struct DBOptions, compaction_readahead_size),
1487 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1488 offsetof(struct MutableDBOptions, compaction_readahead_size)}},
1489 {"random_access_max_buffer_size",
1490 {offsetof(struct DBOptions, random_access_max_buffer_size),
1491 OptionType::kSizeT, OptionVerificationType::kNormal, false, 0}},
1492 {"use_adaptive_mutex",
1493 {offsetof(struct DBOptions, use_adaptive_mutex), OptionType::kBoolean,
1494 OptionVerificationType::kNormal, false, 0}},
1495 {"use_fsync",
1496 {offsetof(struct DBOptions, use_fsync), OptionType::kBoolean,
1497 OptionVerificationType::kNormal, false, 0}},
1498 {"max_background_jobs",
1499 {offsetof(struct DBOptions, max_background_jobs), OptionType::kInt,
1500 OptionVerificationType::kNormal, true,
1501 offsetof(struct MutableDBOptions, max_background_jobs)}},
1502 {"max_background_compactions",
1503 {offsetof(struct DBOptions, max_background_compactions),
1504 OptionType::kInt, OptionVerificationType::kNormal, true,
1505 offsetof(struct MutableDBOptions, max_background_compactions)}},
1506 {"base_background_compactions",
1507 {offsetof(struct DBOptions, base_background_compactions),
1508 OptionType::kInt, OptionVerificationType::kNormal, true,
1509 offsetof(struct MutableDBOptions, base_background_compactions)}},
1510 {"max_background_flushes",
1511 {offsetof(struct DBOptions, max_background_flushes), OptionType::kInt,
1512 OptionVerificationType::kNormal, false, 0}},
1513 {"max_file_opening_threads",
1514 {offsetof(struct DBOptions, max_file_opening_threads),
1515 OptionType::kInt, OptionVerificationType::kNormal, false, 0}},
1516 {"max_open_files",
1517 {offsetof(struct DBOptions, max_open_files), OptionType::kInt,
1518 OptionVerificationType::kNormal, true,
1519 offsetof(struct MutableDBOptions, max_open_files)}},
1520 {"table_cache_numshardbits",
1521 {offsetof(struct DBOptions, table_cache_numshardbits),
1522 OptionType::kInt, OptionVerificationType::kNormal, false, 0}},
1523 {"db_write_buffer_size",
1524 {offsetof(struct DBOptions, db_write_buffer_size), OptionType::kSizeT,
1525 OptionVerificationType::kNormal, false, 0}},
1526 {"keep_log_file_num",
1527 {offsetof(struct DBOptions, keep_log_file_num), OptionType::kSizeT,
1528 OptionVerificationType::kNormal, false, 0}},
1529 {"recycle_log_file_num",
1530 {offsetof(struct DBOptions, recycle_log_file_num), OptionType::kSizeT,
1531 OptionVerificationType::kNormal, false, 0}},
1532 {"log_file_time_to_roll",
1533 {offsetof(struct DBOptions, log_file_time_to_roll), OptionType::kSizeT,
1534 OptionVerificationType::kNormal, false, 0}},
1535 {"manifest_preallocation_size",
1536 {offsetof(struct DBOptions, manifest_preallocation_size),
1537 OptionType::kSizeT, OptionVerificationType::kNormal, false, 0}},
1538 {"max_log_file_size",
1539 {offsetof(struct DBOptions, max_log_file_size), OptionType::kSizeT,
1540 OptionVerificationType::kNormal, false, 0}},
1541 {"db_log_dir",
1542 {offsetof(struct DBOptions, db_log_dir), OptionType::kString,
1543 OptionVerificationType::kNormal, false, 0}},
1544 {"wal_dir",
1545 {offsetof(struct DBOptions, wal_dir), OptionType::kString,
1546 OptionVerificationType::kNormal, false, 0}},
1547 {"max_subcompactions",
1548 {offsetof(struct DBOptions, max_subcompactions), OptionType::kUInt32T,
1549 OptionVerificationType::kNormal, false, 0}},
1550 {"WAL_size_limit_MB",
1551 {offsetof(struct DBOptions, WAL_size_limit_MB), OptionType::kUInt64T,
1552 OptionVerificationType::kNormal, false, 0}},
1553 {"WAL_ttl_seconds",
1554 {offsetof(struct DBOptions, WAL_ttl_seconds), OptionType::kUInt64T,
1555 OptionVerificationType::kNormal, false, 0}},
1556 {"bytes_per_sync",
1557 {offsetof(struct DBOptions, bytes_per_sync), OptionType::kUInt64T,
1558 OptionVerificationType::kNormal, true,
1559 offsetof(struct MutableDBOptions, bytes_per_sync)}},
1560 {"delayed_write_rate",
1561 {offsetof(struct DBOptions, delayed_write_rate), OptionType::kUInt64T,
1562 OptionVerificationType::kNormal, true,
1563 offsetof(struct MutableDBOptions, delayed_write_rate)}},
1564 {"delete_obsolete_files_period_micros",
1565 {offsetof(struct DBOptions, delete_obsolete_files_period_micros),
1566 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1567 offsetof(struct MutableDBOptions,
1568 delete_obsolete_files_period_micros)}},
1569 {"max_manifest_file_size",
1570 {offsetof(struct DBOptions, max_manifest_file_size),
1571 OptionType::kUInt64T, OptionVerificationType::kNormal, false, 0}},
1572 {"max_total_wal_size",
1573 {offsetof(struct DBOptions, max_total_wal_size), OptionType::kUInt64T,
1574 OptionVerificationType::kNormal, true,
1575 offsetof(struct MutableDBOptions, max_total_wal_size)}},
1576 {"wal_bytes_per_sync",
1577 {offsetof(struct DBOptions, wal_bytes_per_sync), OptionType::kUInt64T,
1578 OptionVerificationType::kNormal, true,
1579 offsetof(struct MutableDBOptions, wal_bytes_per_sync)}},
1580 {"strict_bytes_per_sync",
1581 {offsetof(struct DBOptions, strict_bytes_per_sync),
1582 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1583 offsetof(struct MutableDBOptions, strict_bytes_per_sync)}},
1584 {"stats_dump_period_sec",
1585 {offsetof(struct DBOptions, stats_dump_period_sec), OptionType::kUInt,
1586 OptionVerificationType::kNormal, true,
1587 offsetof(struct MutableDBOptions, stats_dump_period_sec)}},
1588 {"stats_persist_period_sec",
1589 {offsetof(struct DBOptions, stats_persist_period_sec),
1590 OptionType::kUInt, OptionVerificationType::kNormal, true,
1591 offsetof(struct MutableDBOptions, stats_persist_period_sec)}},
1592 {"persist_stats_to_disk",
1593 {offsetof(struct DBOptions, persist_stats_to_disk),
1594 OptionType::kBoolean, OptionVerificationType::kNormal, false,
1595 offsetof(struct ImmutableDBOptions, persist_stats_to_disk)}},
1596 {"stats_history_buffer_size",
1597 {offsetof(struct DBOptions, stats_history_buffer_size),
1598 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1599 offsetof(struct MutableDBOptions, stats_history_buffer_size)}},
1600 {"fail_if_options_file_error",
1601 {offsetof(struct DBOptions, fail_if_options_file_error),
1602 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1603 {"enable_pipelined_write",
1604 {offsetof(struct DBOptions, enable_pipelined_write),
1605 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1606 {"unordered_write",
1607 {offsetof(struct DBOptions, unordered_write), OptionType::kBoolean,
1608 OptionVerificationType::kNormal, false, 0}},
1609 {"allow_concurrent_memtable_write",
1610 {offsetof(struct DBOptions, allow_concurrent_memtable_write),
1611 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1612 {"wal_recovery_mode",
1613 {offsetof(struct DBOptions, wal_recovery_mode),
1614 OptionType::kWALRecoveryMode, OptionVerificationType::kNormal, false,
1615 0}},
1616 {"enable_write_thread_adaptive_yield",
1617 {offsetof(struct DBOptions, enable_write_thread_adaptive_yield),
1618 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1619 {"write_thread_slow_yield_usec",
1620 {offsetof(struct DBOptions, write_thread_slow_yield_usec),
1621 OptionType::kUInt64T, OptionVerificationType::kNormal, false, 0}},
1622 {"max_write_batch_group_size_bytes",
1623 {offsetof(struct DBOptions, max_write_batch_group_size_bytes),
1624 OptionType::kUInt64T, OptionVerificationType::kNormal, false, 0}},
1625 {"write_thread_max_yield_usec",
1626 {offsetof(struct DBOptions, write_thread_max_yield_usec),
1627 OptionType::kUInt64T, OptionVerificationType::kNormal, false, 0}},
1628 {"access_hint_on_compaction_start",
1629 {offsetof(struct DBOptions, access_hint_on_compaction_start),
1630 OptionType::kAccessHint, OptionVerificationType::kNormal, false, 0}},
1631 {"info_log_level",
1632 {offsetof(struct DBOptions, info_log_level), OptionType::kInfoLogLevel,
1633 OptionVerificationType::kNormal, false, 0}},
1634 {"dump_malloc_stats",
1635 {offsetof(struct DBOptions, dump_malloc_stats), OptionType::kBoolean,
1636 OptionVerificationType::kNormal, false, 0}},
1637 {"avoid_flush_during_recovery",
1638 {offsetof(struct DBOptions, avoid_flush_during_recovery),
1639 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1640 {"avoid_flush_during_shutdown",
1641 {offsetof(struct DBOptions, avoid_flush_during_shutdown),
1642 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1643 offsetof(struct MutableDBOptions, avoid_flush_during_shutdown)}},
1644 {"writable_file_max_buffer_size",
1645 {offsetof(struct DBOptions, writable_file_max_buffer_size),
1646 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1647 offsetof(struct MutableDBOptions, writable_file_max_buffer_size)}},
1648 {"allow_ingest_behind",
1649 {offsetof(struct DBOptions, allow_ingest_behind), OptionType::kBoolean,
1650 OptionVerificationType::kNormal, false,
1651 offsetof(struct ImmutableDBOptions, allow_ingest_behind)}},
1652 {"preserve_deletes",
1653 {offsetof(struct DBOptions, preserve_deletes), OptionType::kBoolean,
1654 OptionVerificationType::kNormal, false,
1655 offsetof(struct ImmutableDBOptions, preserve_deletes)}},
1656 {"concurrent_prepare", // Deprecated by two_write_queues
1657 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1658 0}},
1659 {"two_write_queues",
1660 {offsetof(struct DBOptions, two_write_queues), OptionType::kBoolean,
1661 OptionVerificationType::kNormal, false,
1662 offsetof(struct ImmutableDBOptions, two_write_queues)}},
1663 {"manual_wal_flush",
1664 {offsetof(struct DBOptions, manual_wal_flush), OptionType::kBoolean,
1665 OptionVerificationType::kNormal, false,
1666 offsetof(struct ImmutableDBOptions, manual_wal_flush)}},
1667 {"seq_per_batch",
1668 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1669 0}},
1670 {"atomic_flush",
1671 {offsetof(struct DBOptions, atomic_flush), OptionType::kBoolean,
1672 OptionVerificationType::kNormal, false,
1673 offsetof(struct ImmutableDBOptions, atomic_flush)}},
1674 {"avoid_unnecessary_blocking_io",
1675 {offsetof(struct DBOptions, avoid_unnecessary_blocking_io),
1676 OptionType::kBoolean, OptionVerificationType::kNormal, false,
1677 offsetof(struct ImmutableDBOptions, avoid_unnecessary_blocking_io)}},
1678 {"write_dbid_to_manifest",
1679 {offsetof(struct DBOptions, write_dbid_to_manifest),
1680 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1681 {"log_readahead_size",
1682 {offsetof(struct DBOptions, log_readahead_size), OptionType::kSizeT,
1683 OptionVerificationType::kNormal, false, 0}},
1684 };
1685
1686 std::unordered_map<std::string, BlockBasedTableOptions::IndexType>
1687 OptionsHelper::block_base_table_index_type_string_map = {
1688 {"kBinarySearch", BlockBasedTableOptions::IndexType::kBinarySearch},
1689 {"kHashSearch", BlockBasedTableOptions::IndexType::kHashSearch},
1690 {"kTwoLevelIndexSearch",
1691 BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch},
1692 {"kBinarySearchWithFirstKey",
1693 BlockBasedTableOptions::IndexType::kBinarySearchWithFirstKey}};
1694
1695 std::unordered_map<std::string, BlockBasedTableOptions::DataBlockIndexType>
1696 OptionsHelper::block_base_table_data_block_index_type_string_map = {
1697 {"kDataBlockBinarySearch",
1698 BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch},
1699 {"kDataBlockBinaryAndHash",
1700 BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinaryAndHash}};
1701
1702 std::unordered_map<std::string, BlockBasedTableOptions::IndexShorteningMode>
1703 OptionsHelper::block_base_table_index_shortening_mode_string_map = {
1704 {"kNoShortening",
1705 BlockBasedTableOptions::IndexShorteningMode::kNoShortening},
1706 {"kShortenSeparators",
1707 BlockBasedTableOptions::IndexShorteningMode::kShortenSeparators},
1708 {"kShortenSeparatorsAndSuccessor",
1709 BlockBasedTableOptions::IndexShorteningMode::
1710 kShortenSeparatorsAndSuccessor}};
1711
1712 std::unordered_map<std::string, EncodingType>
1713 OptionsHelper::encoding_type_string_map = {{"kPlain", kPlain},
1714 {"kPrefix", kPrefix}};
1715
1716 std::unordered_map<std::string, CompactionStyle>
1717 OptionsHelper::compaction_style_string_map = {
1718 {"kCompactionStyleLevel", kCompactionStyleLevel},
1719 {"kCompactionStyleUniversal", kCompactionStyleUniversal},
1720 {"kCompactionStyleFIFO", kCompactionStyleFIFO},
1721 {"kCompactionStyleNone", kCompactionStyleNone}};
1722
1723 std::unordered_map<std::string, CompactionPri>
1724 OptionsHelper::compaction_pri_string_map = {
1725 {"kByCompensatedSize", kByCompensatedSize},
1726 {"kOldestLargestSeqFirst", kOldestLargestSeqFirst},
1727 {"kOldestSmallestSeqFirst", kOldestSmallestSeqFirst},
1728 {"kMinOverlappingRatio", kMinOverlappingRatio}};
1729
1730 std::unordered_map<std::string, WALRecoveryMode>
1731 OptionsHelper::wal_recovery_mode_string_map = {
1732 {"kTolerateCorruptedTailRecords",
1733 WALRecoveryMode::kTolerateCorruptedTailRecords},
1734 {"kAbsoluteConsistency", WALRecoveryMode::kAbsoluteConsistency},
1735 {"kPointInTimeRecovery", WALRecoveryMode::kPointInTimeRecovery},
1736 {"kSkipAnyCorruptedRecords",
1737 WALRecoveryMode::kSkipAnyCorruptedRecords}};
1738
1739 std::unordered_map<std::string, DBOptions::AccessHint>
1740 OptionsHelper::access_hint_string_map = {
1741 {"NONE", DBOptions::AccessHint::NONE},
1742 {"NORMAL", DBOptions::AccessHint::NORMAL},
1743 {"SEQUENTIAL", DBOptions::AccessHint::SEQUENTIAL},
1744 {"WILLNEED", DBOptions::AccessHint::WILLNEED}};
1745
1746 std::unordered_map<std::string, InfoLogLevel>
1747 OptionsHelper::info_log_level_string_map = {
1748 {"DEBUG_LEVEL", InfoLogLevel::DEBUG_LEVEL},
1749 {"INFO_LEVEL", InfoLogLevel::INFO_LEVEL},
1750 {"WARN_LEVEL", InfoLogLevel::WARN_LEVEL},
1751 {"ERROR_LEVEL", InfoLogLevel::ERROR_LEVEL},
1752 {"FATAL_LEVEL", InfoLogLevel::FATAL_LEVEL},
1753 {"HEADER_LEVEL", InfoLogLevel::HEADER_LEVEL}};
1754
1755 ColumnFamilyOptions OptionsHelper::dummy_cf_options;
1756 CompactionOptionsFIFO OptionsHelper::dummy_comp_options;
1757 LRUCacheOptions OptionsHelper::dummy_lru_cache_options;
1758 CompactionOptionsUniversal OptionsHelper::dummy_comp_options_universal;
1759
1760 // offset_of is used to get the offset of a class data member
1761 // ex: offset_of(&ColumnFamilyOptions::num_levels)
1762 // This call will return the offset of num_levels in ColumnFamilyOptions class
1763 //
1764 // This is the same as offsetof() but allow us to work with non standard-layout
1765 // classes and structures
1766 // refs:
1767 // http://en.cppreference.com/w/cpp/concept/StandardLayoutType
1768 // https://gist.github.com/graphitemaster/494f21190bb2c63c5516
1769 template <typename T1>
offset_of(T1 ColumnFamilyOptions::* member)1770 int offset_of(T1 ColumnFamilyOptions::*member) {
1771 return int(size_t(&(OptionsHelper::dummy_cf_options.*member)) -
1772 size_t(&OptionsHelper::dummy_cf_options));
1773 }
1774 template <typename T1>
offset_of(T1 AdvancedColumnFamilyOptions::* member)1775 int offset_of(T1 AdvancedColumnFamilyOptions::*member) {
1776 return int(size_t(&(OptionsHelper::dummy_cf_options.*member)) -
1777 size_t(&OptionsHelper::dummy_cf_options));
1778 }
1779 template <typename T1>
offset_of(T1 CompactionOptionsFIFO::* member)1780 int offset_of(T1 CompactionOptionsFIFO::*member) {
1781 return int(size_t(&(OptionsHelper::dummy_comp_options.*member)) -
1782 size_t(&OptionsHelper::dummy_comp_options));
1783 }
1784 template <typename T1>
offset_of(T1 LRUCacheOptions::* member)1785 int offset_of(T1 LRUCacheOptions::*member) {
1786 return int(size_t(&(OptionsHelper::dummy_lru_cache_options.*member)) -
1787 size_t(&OptionsHelper::dummy_lru_cache_options));
1788 }
1789 template <typename T1>
offset_of(T1 CompactionOptionsUniversal::* member)1790 int offset_of(T1 CompactionOptionsUniversal::*member) {
1791 return int(size_t(&(OptionsHelper::dummy_comp_options_universal.*member)) -
1792 size_t(&OptionsHelper::dummy_comp_options_universal));
1793 }
1794
1795 std::unordered_map<std::string, OptionTypeInfo>
1796 OptionsHelper::cf_options_type_info = {
1797 /* not yet supported
1798 CompressionOptions compression_opts;
1799 TablePropertiesCollectorFactories table_properties_collector_factories;
1800 typedef std::vector<std::shared_ptr<TablePropertiesCollectorFactory>>
1801 TablePropertiesCollectorFactories;
1802 UpdateStatus (*inplace_callback)(char* existing_value,
1803 uint34_t* existing_value_size,
1804 Slice delta_value,
1805 std::string* merged_value);
1806 std::vector<DbPath> cf_paths;
1807 */
1808 {"report_bg_io_stats",
1809 {offset_of(&ColumnFamilyOptions::report_bg_io_stats),
1810 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1811 offsetof(struct MutableCFOptions, report_bg_io_stats)}},
1812 {"compaction_measure_io_stats",
1813 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, false,
1814 0}},
1815 {"disable_auto_compactions",
1816 {offset_of(&ColumnFamilyOptions::disable_auto_compactions),
1817 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1818 offsetof(struct MutableCFOptions, disable_auto_compactions)}},
1819 {"filter_deletes",
1820 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, true,
1821 0}},
1822 {"inplace_update_support",
1823 {offset_of(&ColumnFamilyOptions::inplace_update_support),
1824 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1825 {"level_compaction_dynamic_level_bytes",
1826 {offset_of(&ColumnFamilyOptions::level_compaction_dynamic_level_bytes),
1827 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1828 {"optimize_filters_for_hits",
1829 {offset_of(&ColumnFamilyOptions::optimize_filters_for_hits),
1830 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1831 {"paranoid_file_checks",
1832 {offset_of(&ColumnFamilyOptions::paranoid_file_checks),
1833 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1834 offsetof(struct MutableCFOptions, paranoid_file_checks)}},
1835 {"force_consistency_checks",
1836 {offset_of(&ColumnFamilyOptions::force_consistency_checks),
1837 OptionType::kBoolean, OptionVerificationType::kNormal, false, 0}},
1838 {"purge_redundant_kvs_while_flush",
1839 {offset_of(&ColumnFamilyOptions::purge_redundant_kvs_while_flush),
1840 OptionType::kBoolean, OptionVerificationType::kDeprecated, false, 0}},
1841 {"verify_checksums_in_compaction",
1842 {0, OptionType::kBoolean, OptionVerificationType::kDeprecated, true,
1843 0}},
1844 {"soft_pending_compaction_bytes_limit",
1845 {offset_of(&ColumnFamilyOptions::soft_pending_compaction_bytes_limit),
1846 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1847 offsetof(struct MutableCFOptions,
1848 soft_pending_compaction_bytes_limit)}},
1849 {"hard_pending_compaction_bytes_limit",
1850 {offset_of(&ColumnFamilyOptions::hard_pending_compaction_bytes_limit),
1851 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1852 offsetof(struct MutableCFOptions,
1853 hard_pending_compaction_bytes_limit)}},
1854 {"hard_rate_limit",
1855 {0, OptionType::kDouble, OptionVerificationType::kDeprecated, true,
1856 0}},
1857 {"soft_rate_limit",
1858 {0, OptionType::kDouble, OptionVerificationType::kDeprecated, true,
1859 0}},
1860 {"max_compaction_bytes",
1861 {offset_of(&ColumnFamilyOptions::max_compaction_bytes),
1862 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1863 offsetof(struct MutableCFOptions, max_compaction_bytes)}},
1864 {"expanded_compaction_factor",
1865 {0, OptionType::kInt, OptionVerificationType::kDeprecated, true, 0}},
1866 {"level0_file_num_compaction_trigger",
1867 {offset_of(&ColumnFamilyOptions::level0_file_num_compaction_trigger),
1868 OptionType::kInt, OptionVerificationType::kNormal, true,
1869 offsetof(struct MutableCFOptions,
1870 level0_file_num_compaction_trigger)}},
1871 {"level0_slowdown_writes_trigger",
1872 {offset_of(&ColumnFamilyOptions::level0_slowdown_writes_trigger),
1873 OptionType::kInt, OptionVerificationType::kNormal, true,
1874 offsetof(struct MutableCFOptions, level0_slowdown_writes_trigger)}},
1875 {"level0_stop_writes_trigger",
1876 {offset_of(&ColumnFamilyOptions::level0_stop_writes_trigger),
1877 OptionType::kInt, OptionVerificationType::kNormal, true,
1878 offsetof(struct MutableCFOptions, level0_stop_writes_trigger)}},
1879 {"max_grandparent_overlap_factor",
1880 {0, OptionType::kInt, OptionVerificationType::kDeprecated, true, 0}},
1881 {"max_mem_compaction_level",
1882 {0, OptionType::kInt, OptionVerificationType::kDeprecated, false, 0}},
1883 {"max_write_buffer_number",
1884 {offset_of(&ColumnFamilyOptions::max_write_buffer_number),
1885 OptionType::kInt, OptionVerificationType::kNormal, true,
1886 offsetof(struct MutableCFOptions, max_write_buffer_number)}},
1887 {"max_write_buffer_number_to_maintain",
1888 {offset_of(&ColumnFamilyOptions::max_write_buffer_number_to_maintain),
1889 OptionType::kInt, OptionVerificationType::kNormal, false, 0}},
1890 {"max_write_buffer_size_to_maintain",
1891 {offset_of(&ColumnFamilyOptions::max_write_buffer_size_to_maintain),
1892 OptionType::kInt64T, OptionVerificationType::kNormal, false, 0}},
1893 {"min_write_buffer_number_to_merge",
1894 {offset_of(&ColumnFamilyOptions::min_write_buffer_number_to_merge),
1895 OptionType::kInt, OptionVerificationType::kNormal, false, 0}},
1896 {"num_levels",
1897 {offset_of(&ColumnFamilyOptions::num_levels), OptionType::kInt,
1898 OptionVerificationType::kNormal, false, 0}},
1899 {"source_compaction_factor",
1900 {0, OptionType::kInt, OptionVerificationType::kDeprecated, true, 0}},
1901 {"target_file_size_multiplier",
1902 {offset_of(&ColumnFamilyOptions::target_file_size_multiplier),
1903 OptionType::kInt, OptionVerificationType::kNormal, true,
1904 offsetof(struct MutableCFOptions, target_file_size_multiplier)}},
1905 {"arena_block_size",
1906 {offset_of(&ColumnFamilyOptions::arena_block_size), OptionType::kSizeT,
1907 OptionVerificationType::kNormal, true,
1908 offsetof(struct MutableCFOptions, arena_block_size)}},
1909 {"inplace_update_num_locks",
1910 {offset_of(&ColumnFamilyOptions::inplace_update_num_locks),
1911 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1912 offsetof(struct MutableCFOptions, inplace_update_num_locks)}},
1913 {"max_successive_merges",
1914 {offset_of(&ColumnFamilyOptions::max_successive_merges),
1915 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1916 offsetof(struct MutableCFOptions, max_successive_merges)}},
1917 {"memtable_huge_page_size",
1918 {offset_of(&ColumnFamilyOptions::memtable_huge_page_size),
1919 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1920 offsetof(struct MutableCFOptions, memtable_huge_page_size)}},
1921 {"memtable_prefix_bloom_huge_page_tlb_size",
1922 {0, OptionType::kSizeT, OptionVerificationType::kDeprecated, true, 0}},
1923 {"write_buffer_size",
1924 {offset_of(&ColumnFamilyOptions::write_buffer_size),
1925 OptionType::kSizeT, OptionVerificationType::kNormal, true,
1926 offsetof(struct MutableCFOptions, write_buffer_size)}},
1927 {"bloom_locality",
1928 {offset_of(&ColumnFamilyOptions::bloom_locality), OptionType::kUInt32T,
1929 OptionVerificationType::kNormal, false, 0}},
1930 {"memtable_prefix_bloom_bits",
1931 {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated, true,
1932 0}},
1933 {"memtable_prefix_bloom_size_ratio",
1934 {offset_of(&ColumnFamilyOptions::memtable_prefix_bloom_size_ratio),
1935 OptionType::kDouble, OptionVerificationType::kNormal, true,
1936 offsetof(struct MutableCFOptions, memtable_prefix_bloom_size_ratio)}},
1937 {"memtable_prefix_bloom_probes",
1938 {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated, true,
1939 0}},
1940 {"memtable_whole_key_filtering",
1941 {offset_of(&ColumnFamilyOptions::memtable_whole_key_filtering),
1942 OptionType::kBoolean, OptionVerificationType::kNormal, true,
1943 offsetof(struct MutableCFOptions, memtable_whole_key_filtering)}},
1944 {"min_partial_merge_operands",
1945 {0, OptionType::kUInt32T, OptionVerificationType::kDeprecated, true,
1946 0}},
1947 {"max_bytes_for_level_base",
1948 {offset_of(&ColumnFamilyOptions::max_bytes_for_level_base),
1949 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1950 offsetof(struct MutableCFOptions, max_bytes_for_level_base)}},
1951 {"snap_refresh_nanos",
1952 {0, OptionType::kUInt64T, OptionVerificationType::kDeprecated, true,
1953 0}},
1954 {"max_bytes_for_level_multiplier",
1955 {offset_of(&ColumnFamilyOptions::max_bytes_for_level_multiplier),
1956 OptionType::kDouble, OptionVerificationType::kNormal, true,
1957 offsetof(struct MutableCFOptions, max_bytes_for_level_multiplier)}},
1958 {"max_bytes_for_level_multiplier_additional",
1959 {offset_of(
1960 &ColumnFamilyOptions::max_bytes_for_level_multiplier_additional),
1961 OptionType::kVectorInt, OptionVerificationType::kNormal, true,
1962 offsetof(struct MutableCFOptions,
1963 max_bytes_for_level_multiplier_additional)}},
1964 {"max_sequential_skip_in_iterations",
1965 {offset_of(&ColumnFamilyOptions::max_sequential_skip_in_iterations),
1966 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1967 offsetof(struct MutableCFOptions,
1968 max_sequential_skip_in_iterations)}},
1969 {"target_file_size_base",
1970 {offset_of(&ColumnFamilyOptions::target_file_size_base),
1971 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
1972 offsetof(struct MutableCFOptions, target_file_size_base)}},
1973 {"rate_limit_delay_max_milliseconds",
1974 {0, OptionType::kUInt, OptionVerificationType::kDeprecated, false, 0}},
1975 {"compression",
1976 {offset_of(&ColumnFamilyOptions::compression),
1977 OptionType::kCompressionType, OptionVerificationType::kNormal, true,
1978 offsetof(struct MutableCFOptions, compression)}},
1979 {"compression_per_level",
1980 {offset_of(&ColumnFamilyOptions::compression_per_level),
1981 OptionType::kVectorCompressionType, OptionVerificationType::kNormal,
1982 false, 0}},
1983 {"bottommost_compression",
1984 {offset_of(&ColumnFamilyOptions::bottommost_compression),
1985 OptionType::kCompressionType, OptionVerificationType::kNormal, false,
1986 0}},
1987 {kNameComparator,
1988 {offset_of(&ColumnFamilyOptions::comparator), OptionType::kComparator,
1989 OptionVerificationType::kByName, false, 0}},
1990 {"prefix_extractor",
1991 {offset_of(&ColumnFamilyOptions::prefix_extractor),
1992 OptionType::kSliceTransform, OptionVerificationType::kByNameAllowNull,
1993 true, offsetof(struct MutableCFOptions, prefix_extractor)}},
1994 {"memtable_insert_with_hint_prefix_extractor",
1995 {offset_of(
1996 &ColumnFamilyOptions::memtable_insert_with_hint_prefix_extractor),
1997 OptionType::kSliceTransform, OptionVerificationType::kByNameAllowNull,
1998 false, 0}},
1999 {"memtable_factory",
2000 {offset_of(&ColumnFamilyOptions::memtable_factory),
2001 OptionType::kMemTableRepFactory, OptionVerificationType::kByName,
2002 false, 0}},
2003 {"table_factory",
2004 {offset_of(&ColumnFamilyOptions::table_factory),
2005 OptionType::kTableFactory, OptionVerificationType::kByName, false,
2006 0}},
2007 {"compaction_filter",
2008 {offset_of(&ColumnFamilyOptions::compaction_filter),
2009 OptionType::kCompactionFilter, OptionVerificationType::kByName, false,
2010 0}},
2011 {"compaction_filter_factory",
2012 {offset_of(&ColumnFamilyOptions::compaction_filter_factory),
2013 OptionType::kCompactionFilterFactory, OptionVerificationType::kByName,
2014 false, 0}},
2015 {kNameMergeOperator,
2016 {offset_of(&ColumnFamilyOptions::merge_operator),
2017 OptionType::kMergeOperator,
2018 OptionVerificationType::kByNameAllowFromNull, false, 0}},
2019 {"compaction_style",
2020 {offset_of(&ColumnFamilyOptions::compaction_style),
2021 OptionType::kCompactionStyle, OptionVerificationType::kNormal, false,
2022 0}},
2023 {"compaction_pri",
2024 {offset_of(&ColumnFamilyOptions::compaction_pri),
2025 OptionType::kCompactionPri, OptionVerificationType::kNormal, false,
2026 0}},
2027 {"compaction_options_fifo",
2028 {offset_of(&ColumnFamilyOptions::compaction_options_fifo),
2029 OptionType::kCompactionOptionsFIFO, OptionVerificationType::kNormal,
2030 true, offsetof(struct MutableCFOptions, compaction_options_fifo)}},
2031 {"compaction_options_universal",
2032 {offset_of(&ColumnFamilyOptions::compaction_options_universal),
2033 OptionType::kCompactionOptionsUniversal,
2034 OptionVerificationType::kNormal, true,
2035 offsetof(struct MutableCFOptions, compaction_options_universal)}},
2036 {"ttl",
2037 {offset_of(&ColumnFamilyOptions::ttl), OptionType::kUInt64T,
2038 OptionVerificationType::kNormal, true,
2039 offsetof(struct MutableCFOptions, ttl)}},
2040 {"periodic_compaction_seconds",
2041 {offset_of(&ColumnFamilyOptions::periodic_compaction_seconds),
2042 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
2043 offsetof(struct MutableCFOptions, periodic_compaction_seconds)}},
2044 {"sample_for_compression",
2045 {offset_of(&ColumnFamilyOptions::sample_for_compression),
2046 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
2047 offsetof(struct MutableCFOptions, sample_for_compression)}}};
2048
2049 std::unordered_map<std::string, OptionTypeInfo>
2050 OptionsHelper::fifo_compaction_options_type_info = {
2051 {"max_table_files_size",
2052 {offset_of(&CompactionOptionsFIFO::max_table_files_size),
2053 OptionType::kUInt64T, OptionVerificationType::kNormal, true,
2054 offsetof(struct CompactionOptionsFIFO, max_table_files_size)}},
2055 {"ttl",
2056 {0, OptionType::kUInt64T,
2057 OptionVerificationType::kDeprecated, false,
2058 0}},
2059 {"allow_compaction",
2060 {offset_of(&CompactionOptionsFIFO::allow_compaction),
2061 OptionType::kBoolean, OptionVerificationType::kNormal, true,
2062 offsetof(struct CompactionOptionsFIFO, allow_compaction)}}};
2063
2064 std::unordered_map<std::string, OptionTypeInfo>
2065 OptionsHelper::universal_compaction_options_type_info = {
2066 {"size_ratio",
2067 {offset_of(&CompactionOptionsUniversal::size_ratio), OptionType::kUInt,
2068 OptionVerificationType::kNormal, true,
2069 offsetof(class CompactionOptionsUniversal, size_ratio)}},
2070 {"min_merge_width",
2071 {offset_of(&CompactionOptionsUniversal::min_merge_width),
2072 OptionType::kUInt, OptionVerificationType::kNormal, true,
2073 offsetof(class CompactionOptionsUniversal, min_merge_width)}},
2074 {"max_merge_width",
2075 {offset_of(&CompactionOptionsUniversal::max_merge_width),
2076 OptionType::kUInt, OptionVerificationType::kNormal, true,
2077 offsetof(class CompactionOptionsUniversal, max_merge_width)}},
2078 {"max_size_amplification_percent",
2079 {offset_of(
2080 &CompactionOptionsUniversal::max_size_amplification_percent),
2081 OptionType::kUInt, OptionVerificationType::kNormal, true,
2082 offsetof(class CompactionOptionsUniversal,
2083 max_size_amplification_percent)}},
2084 {"compression_size_percent",
2085 {offset_of(&CompactionOptionsUniversal::compression_size_percent),
2086 OptionType::kInt, OptionVerificationType::kNormal, true,
2087 offsetof(class CompactionOptionsUniversal,
2088 compression_size_percent)}},
2089 {"stop_style",
2090 {offset_of(&CompactionOptionsUniversal::stop_style),
2091 OptionType::kCompactionStopStyle, OptionVerificationType::kNormal,
2092 true, offsetof(class CompactionOptionsUniversal, stop_style)}},
2093 {"allow_trivial_move",
2094 {offset_of(&CompactionOptionsUniversal::allow_trivial_move),
2095 OptionType::kBoolean, OptionVerificationType::kNormal, true,
2096 offsetof(class CompactionOptionsUniversal, allow_trivial_move)}}};
2097
2098 std::unordered_map<std::string, CompactionStopStyle>
2099 OptionsHelper::compaction_stop_style_string_map = {
2100 {"kCompactionStopStyleSimilarSize", kCompactionStopStyleSimilarSize},
2101 {"kCompactionStopStyleTotalSize", kCompactionStopStyleTotalSize}};
2102
2103 std::unordered_map<std::string, OptionTypeInfo>
2104 OptionsHelper::lru_cache_options_type_info = {
2105 {"capacity",
2106 {offset_of(&LRUCacheOptions::capacity), OptionType::kSizeT,
2107 OptionVerificationType::kNormal, true,
2108 offsetof(struct LRUCacheOptions, capacity)}},
2109 {"num_shard_bits",
2110 {offset_of(&LRUCacheOptions::num_shard_bits), OptionType::kInt,
2111 OptionVerificationType::kNormal, true,
2112 offsetof(struct LRUCacheOptions, num_shard_bits)}},
2113 {"strict_capacity_limit",
2114 {offset_of(&LRUCacheOptions::strict_capacity_limit),
2115 OptionType::kBoolean, OptionVerificationType::kNormal, true,
2116 offsetof(struct LRUCacheOptions, strict_capacity_limit)}},
2117 {"high_pri_pool_ratio",
2118 {offset_of(&LRUCacheOptions::high_pri_pool_ratio), OptionType::kDouble,
2119 OptionVerificationType::kNormal, true,
2120 offsetof(struct LRUCacheOptions, high_pri_pool_ratio)}}};
2121
2122 #endif // !ROCKSDB_LITE
2123
2124 } // namespace ROCKSDB_NAMESPACE
2125