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