Coverage Report

Created: 2026-02-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/options/options_helper.cc
Line
Count
Source
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 <atomic>
8
#include <cassert>
9
#include <cctype>
10
#include <cstdlib>
11
#include <set>
12
#include <unordered_set>
13
#include <vector>
14
15
#include "options/cf_options.h"
16
#include "options/db_options.h"
17
#include "rocksdb/cache.h"
18
#include "rocksdb/compaction_filter.h"
19
#include "rocksdb/convenience.h"
20
#include "rocksdb/filter_policy.h"
21
#include "rocksdb/flush_block_policy.h"
22
#include "rocksdb/memtablerep.h"
23
#include "rocksdb/merge_operator.h"
24
#include "rocksdb/options.h"
25
#include "rocksdb/rate_limiter.h"
26
#include "rocksdb/slice_transform.h"
27
#include "rocksdb/table.h"
28
#include "rocksdb/utilities/object_registry.h"
29
#include "rocksdb/utilities/options_type.h"
30
#include "util/string_util.h"
31
32
namespace ROCKSDB_NAMESPACE {
33
107k
ConfigOptions::ConfigOptions() : registry(ObjectRegistry::NewInstance()) {
34
107k
  env = Env::Default();
35
107k
}
36
37
0
ConfigOptions::ConfigOptions(const DBOptions& db_opts) : env(db_opts.env) {
38
0
  registry = ObjectRegistry::NewInstance();
39
0
}
40
41
Status ValidateOptions(const DBOptions& db_opts,
42
28.5k
                       const ColumnFamilyOptions& cf_opts) {
43
28.5k
  Status s;
44
28.5k
  auto db_cfg = DBOptionsAsConfigurable(db_opts);
45
28.5k
  auto cf_cfg = CFOptionsAsConfigurable(cf_opts);
46
28.5k
  s = db_cfg->ValidateOptions(db_opts, cf_opts);
47
28.5k
  if (s.ok()) {
48
28.5k
    s = cf_cfg->ValidateOptions(db_opts, cf_opts);
49
28.5k
  }
50
28.5k
  return s;
51
28.5k
}
52
53
DBOptions BuildDBOptions(const ImmutableDBOptions& immutable_db_options,
54
140k
                         const MutableDBOptions& mutable_db_options) {
55
140k
  DBOptions options;
56
140k
  BuildDBOptions(immutable_db_options, mutable_db_options, options);
57
140k
  return options;
58
140k
}
59
60
void BuildDBOptions(const ImmutableDBOptions& immutable_db_options,
61
                    const MutableDBOptions& mutable_db_options,
62
140k
                    DBOptions& options) {
63
140k
  options.create_if_missing = immutable_db_options.create_if_missing;
64
140k
  options.create_missing_column_families =
65
140k
      immutable_db_options.create_missing_column_families;
66
140k
  options.error_if_exists = immutable_db_options.error_if_exists;
67
140k
  options.paranoid_checks = immutable_db_options.paranoid_checks;
68
140k
  options.flush_verify_memtable_count =
69
140k
      immutable_db_options.flush_verify_memtable_count;
70
140k
  options.compaction_verify_record_count =
71
140k
      immutable_db_options.compaction_verify_record_count;
72
140k
  options.track_and_verify_wals_in_manifest =
73
140k
      immutable_db_options.track_and_verify_wals_in_manifest;
74
140k
  options.track_and_verify_wals = immutable_db_options.track_and_verify_wals;
75
140k
  options.verify_sst_unique_id_in_manifest =
76
140k
      immutable_db_options.verify_sst_unique_id_in_manifest;
77
140k
  options.env = immutable_db_options.env;
78
140k
  options.rate_limiter = immutable_db_options.rate_limiter;
79
140k
  options.sst_file_manager = immutable_db_options.sst_file_manager;
80
140k
  options.info_log = immutable_db_options.info_log;
81
140k
  options.info_log_level = immutable_db_options.info_log_level;
82
140k
  options.max_open_files = mutable_db_options.max_open_files;
83
140k
  options.max_file_opening_threads =
84
140k
      immutable_db_options.max_file_opening_threads;
85
140k
  options.max_total_wal_size = mutable_db_options.max_total_wal_size;
86
140k
  options.statistics = immutable_db_options.statistics;
87
140k
  options.use_fsync = immutable_db_options.use_fsync;
88
140k
  options.db_paths = immutable_db_options.db_paths;
89
140k
  options.db_log_dir = immutable_db_options.db_log_dir;
90
140k
  options.wal_dir = immutable_db_options.wal_dir;
91
140k
  options.delete_obsolete_files_period_micros =
92
140k
      mutable_db_options.delete_obsolete_files_period_micros;
93
140k
  options.max_background_jobs = mutable_db_options.max_background_jobs;
94
140k
  options.max_background_compactions =
95
140k
      mutable_db_options.max_background_compactions;
96
140k
  options.max_subcompactions = mutable_db_options.max_subcompactions;
97
140k
  options.max_background_flushes = mutable_db_options.max_background_flushes;
98
140k
  options.max_log_file_size = immutable_db_options.max_log_file_size;
99
140k
  options.log_file_time_to_roll = immutable_db_options.log_file_time_to_roll;
100
140k
  options.keep_log_file_num = immutable_db_options.keep_log_file_num;
101
140k
  options.recycle_log_file_num = immutable_db_options.recycle_log_file_num;
102
140k
  options.max_manifest_file_size = mutable_db_options.max_manifest_file_size;
103
140k
  options.max_manifest_space_amp_pct =
104
140k
      mutable_db_options.max_manifest_space_amp_pct;
105
140k
  options.table_cache_numshardbits =
106
140k
      immutable_db_options.table_cache_numshardbits;
107
140k
  options.WAL_ttl_seconds = immutable_db_options.WAL_ttl_seconds;
108
140k
  options.WAL_size_limit_MB = immutable_db_options.WAL_size_limit_MB;
109
140k
  options.manifest_preallocation_size =
110
140k
      mutable_db_options.manifest_preallocation_size;
111
140k
  options.allow_mmap_reads = immutable_db_options.allow_mmap_reads;
112
140k
  options.allow_mmap_writes = immutable_db_options.allow_mmap_writes;
113
140k
  options.use_direct_reads = immutable_db_options.use_direct_reads;
114
140k
  options.use_direct_io_for_flush_and_compaction =
115
140k
      immutable_db_options.use_direct_io_for_flush_and_compaction;
116
140k
  options.allow_fallocate = immutable_db_options.allow_fallocate;
117
140k
  options.is_fd_close_on_exec = immutable_db_options.is_fd_close_on_exec;
118
140k
  options.stats_dump_period_sec = mutable_db_options.stats_dump_period_sec;
119
140k
  options.stats_persist_period_sec =
120
140k
      mutable_db_options.stats_persist_period_sec;
121
140k
  options.persist_stats_to_disk = immutable_db_options.persist_stats_to_disk;
122
140k
  options.stats_history_buffer_size =
123
140k
      mutable_db_options.stats_history_buffer_size;
124
140k
  options.advise_random_on_open = immutable_db_options.advise_random_on_open;
125
140k
  options.db_write_buffer_size = immutable_db_options.db_write_buffer_size;
126
140k
  options.write_buffer_manager = immutable_db_options.write_buffer_manager;
127
140k
  options.compaction_readahead_size =
128
140k
      mutable_db_options.compaction_readahead_size;
129
140k
  options.writable_file_max_buffer_size =
130
140k
      mutable_db_options.writable_file_max_buffer_size;
131
140k
  options.use_adaptive_mutex = immutable_db_options.use_adaptive_mutex;
132
140k
  options.bytes_per_sync = mutable_db_options.bytes_per_sync;
133
140k
  options.wal_bytes_per_sync = mutable_db_options.wal_bytes_per_sync;
134
140k
  options.strict_bytes_per_sync = mutable_db_options.strict_bytes_per_sync;
135
140k
  options.listeners = immutable_db_options.listeners;
136
140k
  options.enable_thread_tracking = immutable_db_options.enable_thread_tracking;
137
140k
  options.delayed_write_rate = mutable_db_options.delayed_write_rate;
138
140k
  options.enable_pipelined_write = immutable_db_options.enable_pipelined_write;
139
140k
  options.unordered_write = immutable_db_options.unordered_write;
140
140k
  options.allow_concurrent_memtable_write =
141
140k
      immutable_db_options.allow_concurrent_memtable_write;
142
140k
  options.enable_write_thread_adaptive_yield =
143
140k
      immutable_db_options.enable_write_thread_adaptive_yield;
144
140k
  options.max_write_batch_group_size_bytes =
145
140k
      immutable_db_options.max_write_batch_group_size_bytes;
146
140k
  options.write_thread_max_yield_usec =
147
140k
      immutable_db_options.write_thread_max_yield_usec;
148
140k
  options.write_thread_slow_yield_usec =
149
140k
      immutable_db_options.write_thread_slow_yield_usec;
150
140k
  options.skip_stats_update_on_db_open =
151
140k
      immutable_db_options.skip_stats_update_on_db_open;
152
140k
  options.skip_checking_sst_file_sizes_on_db_open =
153
140k
      immutable_db_options.skip_checking_sst_file_sizes_on_db_open;
154
140k
  options.wal_recovery_mode = immutable_db_options.wal_recovery_mode;
155
140k
  options.allow_2pc = immutable_db_options.allow_2pc;
156
140k
  options.row_cache = immutable_db_options.row_cache;
157
140k
  options.wal_filter = immutable_db_options.wal_filter;
158
140k
  options.dump_malloc_stats = immutable_db_options.dump_malloc_stats;
159
140k
  options.avoid_flush_during_recovery =
160
140k
      immutable_db_options.avoid_flush_during_recovery;
161
140k
  options.avoid_flush_during_shutdown =
162
140k
      mutable_db_options.avoid_flush_during_shutdown;
163
140k
  options.allow_ingest_behind = immutable_db_options.allow_ingest_behind;
164
140k
  options.two_write_queues = immutable_db_options.two_write_queues;
165
140k
  options.manual_wal_flush = immutable_db_options.manual_wal_flush;
166
140k
  options.wal_compression = immutable_db_options.wal_compression;
167
140k
  options.background_close_inactive_wals =
168
140k
      immutable_db_options.background_close_inactive_wals;
169
140k
  options.atomic_flush = immutable_db_options.atomic_flush;
170
140k
  options.avoid_unnecessary_blocking_io =
171
140k
      immutable_db_options.avoid_unnecessary_blocking_io;
172
140k
  options.write_dbid_to_manifest = immutable_db_options.write_dbid_to_manifest;
173
140k
  options.write_identity_file = immutable_db_options.write_identity_file;
174
140k
  options.prefix_seek_opt_in_only =
175
140k
      immutable_db_options.prefix_seek_opt_in_only;
176
140k
  options.log_readahead_size = immutable_db_options.log_readahead_size;
177
140k
  options.file_checksum_gen_factory =
178
140k
      immutable_db_options.file_checksum_gen_factory;
179
140k
  options.best_efforts_recovery = immutable_db_options.best_efforts_recovery;
180
140k
  options.max_bgerror_resume_count =
181
140k
      immutable_db_options.max_bgerror_resume_count;
182
140k
  options.bgerror_resume_retry_interval =
183
140k
      immutable_db_options.bgerror_resume_retry_interval;
184
140k
  options.db_host_id = immutable_db_options.db_host_id;
185
140k
  options.allow_data_in_errors = immutable_db_options.allow_data_in_errors;
186
140k
  options.checksum_handoff_file_types =
187
140k
      immutable_db_options.checksum_handoff_file_types;
188
140k
  options.lowest_used_cache_tier = immutable_db_options.lowest_used_cache_tier;
189
140k
  options.enforce_single_del_contracts =
190
140k
      immutable_db_options.enforce_single_del_contracts;
191
140k
  options.daily_offpeak_time_utc = mutable_db_options.daily_offpeak_time_utc;
192
140k
  options.follower_refresh_catchup_period_ms =
193
140k
      immutable_db_options.follower_refresh_catchup_period_ms;
194
140k
  options.follower_catchup_retry_count =
195
140k
      immutable_db_options.follower_catchup_retry_count;
196
140k
  options.follower_catchup_retry_wait_ms =
197
140k
      immutable_db_options.follower_catchup_retry_wait_ms;
198
140k
  options.metadata_write_temperature =
199
140k
      immutable_db_options.metadata_write_temperature;
200
140k
  options.wal_write_temperature = immutable_db_options.wal_write_temperature;
201
140k
  options.compaction_service = immutable_db_options.compaction_service;
202
140k
  options.calculate_sst_write_lifetime_hint_set =
203
140k
      immutable_db_options.calculate_sst_write_lifetime_hint_set;
204
140k
}
205
206
ColumnFamilyOptions BuildColumnFamilyOptions(
207
    const ColumnFamilyOptions& options,
208
92.3k
    const MutableCFOptions& mutable_cf_options) {
209
92.3k
  ColumnFamilyOptions cf_opts(options);
210
92.3k
  UpdateColumnFamilyOptions(mutable_cf_options, &cf_opts);
211
  // TODO(yhchiang): find some way to handle the following derived options
212
  // * max_file_size
213
92.3k
  return cf_opts;
214
92.3k
}
215
216
void UpdateColumnFamilyOptions(const MutableCFOptions& moptions,
217
147k
                               ColumnFamilyOptions* cf_opts) {
218
  // Memtable related options
219
147k
  cf_opts->write_buffer_size = moptions.write_buffer_size;
220
147k
  cf_opts->max_write_buffer_number = moptions.max_write_buffer_number;
221
147k
  cf_opts->arena_block_size = moptions.arena_block_size;
222
147k
  cf_opts->memtable_prefix_bloom_size_ratio =
223
147k
      moptions.memtable_prefix_bloom_size_ratio;
224
147k
  cf_opts->memtable_whole_key_filtering = moptions.memtable_whole_key_filtering;
225
147k
  cf_opts->memtable_huge_page_size = moptions.memtable_huge_page_size;
226
147k
  cf_opts->max_successive_merges = moptions.max_successive_merges;
227
147k
  cf_opts->strict_max_successive_merges = moptions.strict_max_successive_merges;
228
147k
  cf_opts->inplace_update_num_locks = moptions.inplace_update_num_locks;
229
147k
  cf_opts->prefix_extractor = moptions.prefix_extractor;
230
147k
  cf_opts->experimental_mempurge_threshold =
231
147k
      moptions.experimental_mempurge_threshold;
232
147k
  cf_opts->memtable_protection_bytes_per_key =
233
147k
      moptions.memtable_protection_bytes_per_key;
234
147k
  cf_opts->block_protection_bytes_per_key =
235
147k
      moptions.block_protection_bytes_per_key;
236
147k
  cf_opts->paranoid_memory_checks = moptions.paranoid_memory_checks;
237
147k
  cf_opts->memtable_veirfy_per_key_checksum_on_seek =
238
147k
      moptions.memtable_veirfy_per_key_checksum_on_seek;
239
147k
  cf_opts->bottommost_file_compaction_delay =
240
147k
      moptions.bottommost_file_compaction_delay;
241
242
  // Compaction related options
243
147k
  cf_opts->disable_auto_compactions = moptions.disable_auto_compactions;
244
147k
  cf_opts->table_factory = moptions.table_factory;
245
147k
  cf_opts->soft_pending_compaction_bytes_limit =
246
147k
      moptions.soft_pending_compaction_bytes_limit;
247
147k
  cf_opts->hard_pending_compaction_bytes_limit =
248
147k
      moptions.hard_pending_compaction_bytes_limit;
249
147k
  cf_opts->level0_file_num_compaction_trigger =
250
147k
      moptions.level0_file_num_compaction_trigger;
251
147k
  cf_opts->level0_slowdown_writes_trigger =
252
147k
      moptions.level0_slowdown_writes_trigger;
253
147k
  cf_opts->level0_stop_writes_trigger = moptions.level0_stop_writes_trigger;
254
147k
  cf_opts->max_compaction_bytes = moptions.max_compaction_bytes;
255
147k
  cf_opts->target_file_size_base = moptions.target_file_size_base;
256
147k
  cf_opts->target_file_size_multiplier = moptions.target_file_size_multiplier;
257
147k
  cf_opts->target_file_size_is_upper_bound =
258
147k
      moptions.target_file_size_is_upper_bound;
259
147k
  cf_opts->max_bytes_for_level_base = moptions.max_bytes_for_level_base;
260
147k
  cf_opts->max_bytes_for_level_multiplier =
261
147k
      moptions.max_bytes_for_level_multiplier;
262
147k
  cf_opts->ttl = moptions.ttl;
263
147k
  cf_opts->periodic_compaction_seconds = moptions.periodic_compaction_seconds;
264
147k
  cf_opts->preclude_last_level_data_seconds =
265
147k
      moptions.preclude_last_level_data_seconds;
266
147k
  cf_opts->preserve_internal_time_seconds =
267
147k
      moptions.preserve_internal_time_seconds;
268
269
147k
  cf_opts->max_bytes_for_level_multiplier_additional.clear();
270
1.03M
  for (auto value : moptions.max_bytes_for_level_multiplier_additional) {
271
1.03M
    cf_opts->max_bytes_for_level_multiplier_additional.emplace_back(value);
272
1.03M
  }
273
274
147k
  cf_opts->compaction_options_fifo = moptions.compaction_options_fifo;
275
147k
  cf_opts->compaction_options_universal = moptions.compaction_options_universal;
276
277
147k
  cf_opts->verify_output_flags = moptions.verify_output_flags;
278
279
  // Blob file related options
280
147k
  cf_opts->enable_blob_files = moptions.enable_blob_files;
281
147k
  cf_opts->min_blob_size = moptions.min_blob_size;
282
147k
  cf_opts->blob_file_size = moptions.blob_file_size;
283
147k
  cf_opts->blob_compression_type = moptions.blob_compression_type;
284
147k
  cf_opts->enable_blob_garbage_collection =
285
147k
      moptions.enable_blob_garbage_collection;
286
147k
  cf_opts->blob_garbage_collection_age_cutoff =
287
147k
      moptions.blob_garbage_collection_age_cutoff;
288
147k
  cf_opts->blob_garbage_collection_force_threshold =
289
147k
      moptions.blob_garbage_collection_force_threshold;
290
147k
  cf_opts->blob_compaction_readahead_size =
291
147k
      moptions.blob_compaction_readahead_size;
292
147k
  cf_opts->blob_file_starting_level = moptions.blob_file_starting_level;
293
147k
  cf_opts->prepopulate_blob_cache = moptions.prepopulate_blob_cache;
294
295
  // Misc options
296
147k
  cf_opts->max_sequential_skip_in_iterations =
297
147k
      moptions.max_sequential_skip_in_iterations;
298
147k
  cf_opts->paranoid_file_checks = moptions.paranoid_file_checks;
299
147k
  cf_opts->report_bg_io_stats = moptions.report_bg_io_stats;
300
147k
  cf_opts->compression = moptions.compression;
301
147k
  cf_opts->compression_opts = moptions.compression_opts;
302
147k
  cf_opts->bottommost_compression = moptions.bottommost_compression;
303
147k
  cf_opts->bottommost_compression_opts = moptions.bottommost_compression_opts;
304
147k
  cf_opts->compression_manager = moptions.compression_manager;
305
147k
  cf_opts->sample_for_compression = moptions.sample_for_compression;
306
147k
  cf_opts->compression_per_level = moptions.compression_per_level;
307
147k
  cf_opts->last_level_temperature = moptions.last_level_temperature;
308
147k
  cf_opts->default_write_temperature = moptions.default_write_temperature;
309
147k
  cf_opts->memtable_max_range_deletions = moptions.memtable_max_range_deletions;
310
147k
  cf_opts->uncache_aggressiveness = moptions.uncache_aggressiveness;
311
147k
  cf_opts->memtable_op_scan_flush_trigger =
312
147k
      moptions.memtable_op_scan_flush_trigger;
313
147k
  cf_opts->memtable_avg_op_scan_flush_trigger =
314
147k
      moptions.memtable_avg_op_scan_flush_trigger;
315
147k
}
316
317
void UpdateColumnFamilyOptions(const ImmutableCFOptions& ioptions,
318
55.0k
                               ColumnFamilyOptions* cf_opts) {
319
55.0k
  cf_opts->compaction_style = ioptions.compaction_style;
320
55.0k
  cf_opts->compaction_pri = ioptions.compaction_pri;
321
55.0k
  cf_opts->comparator = ioptions.user_comparator;
322
55.0k
  cf_opts->merge_operator = ioptions.merge_operator;
323
55.0k
  cf_opts->compaction_filter = ioptions.compaction_filter;
324
55.0k
  cf_opts->compaction_filter_factory = ioptions.compaction_filter_factory;
325
55.0k
  cf_opts->min_write_buffer_number_to_merge =
326
55.0k
      ioptions.min_write_buffer_number_to_merge;
327
55.0k
  cf_opts->max_write_buffer_size_to_maintain =
328
55.0k
      ioptions.max_write_buffer_size_to_maintain;
329
55.0k
  cf_opts->inplace_update_support = ioptions.inplace_update_support;
330
55.0k
  cf_opts->inplace_callback = ioptions.inplace_callback;
331
55.0k
  cf_opts->memtable_factory = ioptions.memtable_factory;
332
55.0k
  cf_opts->table_properties_collector_factories =
333
55.0k
      ioptions.table_properties_collector_factories;
334
55.0k
  cf_opts->bloom_locality = ioptions.bloom_locality;
335
55.0k
  cf_opts->level_compaction_dynamic_level_bytes =
336
55.0k
      ioptions.level_compaction_dynamic_level_bytes;
337
55.0k
  cf_opts->num_levels = ioptions.num_levels;
338
55.0k
  cf_opts->optimize_filters_for_hits = ioptions.optimize_filters_for_hits;
339
55.0k
  cf_opts->force_consistency_checks = ioptions.force_consistency_checks;
340
55.0k
  cf_opts->disallow_memtable_writes = ioptions.disallow_memtable_writes;
341
55.0k
  cf_opts->memtable_insert_with_hint_prefix_extractor =
342
55.0k
      ioptions.memtable_insert_with_hint_prefix_extractor;
343
55.0k
  cf_opts->cf_paths = ioptions.cf_paths;
344
55.0k
  cf_opts->compaction_thread_limiter = ioptions.compaction_thread_limiter;
345
55.0k
  cf_opts->sst_partitioner_factory = ioptions.sst_partitioner_factory;
346
55.0k
  cf_opts->blob_cache = ioptions.blob_cache;
347
55.0k
  cf_opts->persist_user_defined_timestamps =
348
55.0k
      ioptions.persist_user_defined_timestamps;
349
55.0k
  cf_opts->default_temperature = ioptions.default_temperature;
350
55.0k
  cf_opts->cf_allow_ingest_behind = ioptions.cf_allow_ingest_behind;
351
352
  // TODO(yhchiang): find some way to handle the following derived options
353
  // * max_file_size
354
55.0k
}
355
356
std::map<CompactionStyle, std::string>
357
    OptionsHelper::compaction_style_to_string = {
358
        {kCompactionStyleLevel, "kCompactionStyleLevel"},
359
        {kCompactionStyleUniversal, "kCompactionStyleUniversal"},
360
        {kCompactionStyleFIFO, "kCompactionStyleFIFO"},
361
        {kCompactionStyleNone, "kCompactionStyleNone"}};
362
363
std::map<CompactionPri, std::string> OptionsHelper::compaction_pri_to_string = {
364
    {kByCompensatedSize, "kByCompensatedSize"},
365
    {kOldestLargestSeqFirst, "kOldestLargestSeqFirst"},
366
    {kOldestSmallestSeqFirst, "kOldestSmallestSeqFirst"},
367
    {kMinOverlappingRatio, "kMinOverlappingRatio"},
368
    {kRoundRobin, "kRoundRobin"}};
369
370
std::map<CompactionStopStyle, std::string>
371
    OptionsHelper::compaction_stop_style_to_string = {
372
        {kCompactionStopStyleSimilarSize, "kCompactionStopStyleSimilarSize"},
373
        {kCompactionStopStyleTotalSize, "kCompactionStopStyleTotalSize"}};
374
375
std::map<Temperature, std::string> OptionsHelper::temperature_to_string = {
376
    {Temperature::kUnknown, "kUnknown"}, {Temperature::kHot, "kHot"},
377
    {Temperature::kWarm, "kWarm"},       {Temperature::kCool, "kCool"},
378
    {Temperature::kCold, "kCold"},       {Temperature::kIce, "kIce"}};
379
380
std::unordered_map<std::string, ChecksumType>
381
    OptionsHelper::checksum_type_string_map = {{"kNoChecksum", kNoChecksum},
382
                                               {"kCRC32c", kCRC32c},
383
                                               {"kxxHash", kxxHash},
384
                                               {"kxxHash64", kxxHash64},
385
                                               {"kXXH3", kXXH3}};
386
387
std::unordered_map<std::string, CompressionType>
388
    OptionsHelper::compression_type_string_map = {
389
        {"kNoCompression", kNoCompression},
390
        {"kSnappyCompression", kSnappyCompression},
391
        {"kZlibCompression", kZlibCompression},
392
        {"kBZip2Compression", kBZip2Compression},
393
        {"kLZ4Compression", kLZ4Compression},
394
        {"kLZ4HCCompression", kLZ4HCCompression},
395
        {"kXpressCompression", kXpressCompression},
396
        {"kZSTD", kZSTD},
397
        {"kCustomCompression80", kCustomCompression80},
398
        {"kCustomCompression81", kCustomCompression81},
399
        {"kCustomCompression82", kCustomCompression82},
400
        {"kCustomCompression83", kCustomCompression83},
401
        {"kCustomCompression84", kCustomCompression84},
402
        {"kCustomCompression85", kCustomCompression85},
403
        {"kCustomCompression86", kCustomCompression86},
404
        {"kCustomCompression87", kCustomCompression87},
405
        {"kCustomCompression88", kCustomCompression88},
406
        {"kCustomCompression89", kCustomCompression89},
407
        {"kCustomCompression8A", kCustomCompression8A},
408
        {"kCustomCompression8B", kCustomCompression8B},
409
        {"kCustomCompression8C", kCustomCompression8C},
410
        {"kCustomCompression8D", kCustomCompression8D},
411
        {"kCustomCompression8E", kCustomCompression8E},
412
        {"kCustomCompression8F", kCustomCompression8F},
413
        {"kCustomCompression90", kCustomCompression90},
414
        {"kCustomCompression91", kCustomCompression91},
415
        {"kCustomCompression92", kCustomCompression92},
416
        {"kCustomCompression93", kCustomCompression93},
417
        {"kCustomCompression94", kCustomCompression94},
418
        {"kCustomCompression95", kCustomCompression95},
419
        {"kCustomCompression96", kCustomCompression96},
420
        {"kCustomCompression97", kCustomCompression97},
421
        {"kCustomCompression98", kCustomCompression98},
422
        {"kCustomCompression99", kCustomCompression99},
423
        {"kCustomCompression9A", kCustomCompression9A},
424
        {"kCustomCompression9B", kCustomCompression9B},
425
        {"kCustomCompression9C", kCustomCompression9C},
426
        {"kCustomCompression9D", kCustomCompression9D},
427
        {"kCustomCompression9E", kCustomCompression9E},
428
        {"kCustomCompression9F", kCustomCompression9F},
429
        {"kCustomCompressionA0", kCustomCompressionA0},
430
        {"kCustomCompressionA1", kCustomCompressionA1},
431
        {"kCustomCompressionA2", kCustomCompressionA2},
432
        {"kCustomCompressionA3", kCustomCompressionA3},
433
        {"kCustomCompressionA4", kCustomCompressionA4},
434
        {"kCustomCompressionA5", kCustomCompressionA5},
435
        {"kCustomCompressionA6", kCustomCompressionA6},
436
        {"kCustomCompressionA7", kCustomCompressionA7},
437
        {"kCustomCompressionA8", kCustomCompressionA8},
438
        {"kCustomCompressionA9", kCustomCompressionA9},
439
        {"kCustomCompressionAA", kCustomCompressionAA},
440
        {"kCustomCompressionAB", kCustomCompressionAB},
441
        {"kCustomCompressionAC", kCustomCompressionAC},
442
        {"kCustomCompressionAD", kCustomCompressionAD},
443
        {"kCustomCompressionAE", kCustomCompressionAE},
444
        {"kCustomCompressionAF", kCustomCompressionAF},
445
        {"kCustomCompressionB0", kCustomCompressionB0},
446
        {"kCustomCompressionB1", kCustomCompressionB1},
447
        {"kCustomCompressionB2", kCustomCompressionB2},
448
        {"kCustomCompressionB3", kCustomCompressionB3},
449
        {"kCustomCompressionB4", kCustomCompressionB4},
450
        {"kCustomCompressionB5", kCustomCompressionB5},
451
        {"kCustomCompressionB6", kCustomCompressionB6},
452
        {"kCustomCompressionB7", kCustomCompressionB7},
453
        {"kCustomCompressionB8", kCustomCompressionB8},
454
        {"kCustomCompressionB9", kCustomCompressionB9},
455
        {"kCustomCompressionBA", kCustomCompressionBA},
456
        {"kCustomCompressionBB", kCustomCompressionBB},
457
        {"kCustomCompressionBC", kCustomCompressionBC},
458
        {"kCustomCompressionBD", kCustomCompressionBD},
459
        {"kCustomCompressionBE", kCustomCompressionBE},
460
        {"kCustomCompressionBF", kCustomCompressionBF},
461
        {"kCustomCompressionC0", kCustomCompressionC0},
462
        {"kCustomCompressionC1", kCustomCompressionC1},
463
        {"kCustomCompressionC2", kCustomCompressionC2},
464
        {"kCustomCompressionC3", kCustomCompressionC3},
465
        {"kCustomCompressionC4", kCustomCompressionC4},
466
        {"kCustomCompressionC5", kCustomCompressionC5},
467
        {"kCustomCompressionC6", kCustomCompressionC6},
468
        {"kCustomCompressionC7", kCustomCompressionC7},
469
        {"kCustomCompressionC8", kCustomCompressionC8},
470
        {"kCustomCompressionC9", kCustomCompressionC9},
471
        {"kCustomCompressionCA", kCustomCompressionCA},
472
        {"kCustomCompressionCB", kCustomCompressionCB},
473
        {"kCustomCompressionCC", kCustomCompressionCC},
474
        {"kCustomCompressionCD", kCustomCompressionCD},
475
        {"kCustomCompressionCE", kCustomCompressionCE},
476
        {"kCustomCompressionCF", kCustomCompressionCF},
477
        {"kCustomCompressionD0", kCustomCompressionD0},
478
        {"kCustomCompressionD1", kCustomCompressionD1},
479
        {"kCustomCompressionD2", kCustomCompressionD2},
480
        {"kCustomCompressionD3", kCustomCompressionD3},
481
        {"kCustomCompressionD4", kCustomCompressionD4},
482
        {"kCustomCompressionD5", kCustomCompressionD5},
483
        {"kCustomCompressionD6", kCustomCompressionD6},
484
        {"kCustomCompressionD7", kCustomCompressionD7},
485
        {"kCustomCompressionD8", kCustomCompressionD8},
486
        {"kCustomCompressionD9", kCustomCompressionD9},
487
        {"kCustomCompressionDA", kCustomCompressionDA},
488
        {"kCustomCompressionDB", kCustomCompressionDB},
489
        {"kCustomCompressionDC", kCustomCompressionDC},
490
        {"kCustomCompressionDD", kCustomCompressionDD},
491
        {"kCustomCompressionDE", kCustomCompressionDE},
492
        {"kCustomCompressionDF", kCustomCompressionDF},
493
        {"kCustomCompressionE0", kCustomCompressionE0},
494
        {"kCustomCompressionE1", kCustomCompressionE1},
495
        {"kCustomCompressionE2", kCustomCompressionE2},
496
        {"kCustomCompressionE3", kCustomCompressionE3},
497
        {"kCustomCompressionE4", kCustomCompressionE4},
498
        {"kCustomCompressionE5", kCustomCompressionE5},
499
        {"kCustomCompressionE6", kCustomCompressionE6},
500
        {"kCustomCompressionE7", kCustomCompressionE7},
501
        {"kCustomCompressionE8", kCustomCompressionE8},
502
        {"kCustomCompressionE9", kCustomCompressionE9},
503
        {"kCustomCompressionEA", kCustomCompressionEA},
504
        {"kCustomCompressionEB", kCustomCompressionEB},
505
        {"kCustomCompressionEC", kCustomCompressionEC},
506
        {"kCustomCompressionED", kCustomCompressionED},
507
        {"kCustomCompressionEE", kCustomCompressionEE},
508
        {"kCustomCompressionEF", kCustomCompressionEF},
509
        {"kCustomCompressionF0", kCustomCompressionF0},
510
        {"kCustomCompressionF1", kCustomCompressionF1},
511
        {"kCustomCompressionF2", kCustomCompressionF2},
512
        {"kCustomCompressionF3", kCustomCompressionF3},
513
        {"kCustomCompressionF4", kCustomCompressionF4},
514
        {"kCustomCompressionF5", kCustomCompressionF5},
515
        {"kCustomCompressionF6", kCustomCompressionF6},
516
        {"kCustomCompressionF7", kCustomCompressionF7},
517
        {"kCustomCompressionF8", kCustomCompressionF8},
518
        {"kCustomCompressionF9", kCustomCompressionF9},
519
        {"kCustomCompressionFA", kCustomCompressionFA},
520
        {"kCustomCompressionFB", kCustomCompressionFB},
521
        {"kCustomCompressionFC", kCustomCompressionFC},
522
        {"kCustomCompressionFD", kCustomCompressionFD},
523
        {"kCustomCompressionFE", kCustomCompressionFE},
524
        {"kDisableCompressionOption", kDisableCompressionOption}};
525
526
0
const std::vector<CompressionType>& GetSupportedCompressions() {
527
0
  static std::vector<CompressionType> supported_compressions = []() {
528
    // std::set internally to deduplicate potential name aliases
529
0
    std::set<CompressionType> comp_set;
530
0
    for (const auto& comp_to_name :
531
0
         OptionsHelper::compression_type_string_map) {
532
0
      CompressionType t = comp_to_name.second;
533
0
      if (t != kDisableCompressionOption && CompressionTypeSupported(t)) {
534
0
        comp_set.insert(t);
535
0
      }
536
0
    }
537
0
    return std::vector<CompressionType>(comp_set.begin(), comp_set.end());
538
0
  }();
539
0
  return supported_compressions;
540
0
}
541
542
0
const std::vector<CompressionType>& GetSupportedDictCompressions() {
543
0
  static std::vector<CompressionType> supported_dict_compressions = []() {
544
0
    std::set<CompressionType> comp_set;
545
0
    for (const auto& comp_to_name :
546
0
         OptionsHelper::compression_type_string_map) {
547
0
      CompressionType t = comp_to_name.second;
548
0
      if (t != kDisableCompressionOption && DictCompressionTypeSupported(t)) {
549
0
        comp_set.insert(t);
550
0
      }
551
0
    }
552
0
    return std::vector<CompressionType>(comp_set.begin(), comp_set.end());
553
0
  }();
554
0
  return supported_dict_compressions;
555
0
}
556
557
0
const std::vector<ChecksumType>& GetSupportedChecksums() {
558
0
  static std::vector<ChecksumType> supported_checksums = []() {
559
0
    std::set<ChecksumType> checksum_types;
560
0
    for (const auto& e : OptionsHelper::checksum_type_string_map) {
561
0
      checksum_types.insert(e.second);
562
0
    }
563
0
    return std::vector<ChecksumType>(checksum_types.begin(),
564
0
                                     checksum_types.end());
565
0
  }();
566
0
  return supported_checksums;
567
0
}
568
569
static bool ParseOptionHelper(void* opt_address, const OptionType& opt_type,
570
10.7M
                              const std::string& value) {
571
10.7M
  switch (opt_type) {
572
3.97M
    case OptionType::kBoolean:
573
3.97M
      *static_cast<bool*>(opt_address) = ParseBoolean("", value);
574
3.97M
      break;
575
1.94M
    case OptionType::kInt:
576
1.94M
      *static_cast<int*>(opt_address) = ParseInt(value);
577
1.94M
      break;
578
0
    case OptionType::kInt32T:
579
0
      *static_cast<int32_t*>(opt_address) = ParseInt32(value);
580
0
      break;
581
55.0k
    case OptionType::kInt64T:
582
55.0k
      PutUnaligned(static_cast<int64_t*>(opt_address), ParseInt64(value));
583
55.0k
      break;
584
294k
    case OptionType::kUInt:
585
294k
      *static_cast<unsigned int*>(opt_address) = ParseUint32(value);
586
294k
      break;
587
55.0k
    case OptionType::kUInt8T:
588
55.0k
      *static_cast<uint8_t*>(opt_address) = ParseUint8(value);
589
55.0k
      break;
590
752k
    case OptionType::kUInt32T:
591
752k
      *static_cast<uint32_t*>(opt_address) = ParseUint32(value);
592
752k
      break;
593
1.71M
    case OptionType::kUInt64T:
594
1.71M
      PutUnaligned(static_cast<uint64_t*>(opt_address), ParseUint64(value));
595
1.71M
      break;
596
923k
    case OptionType::kSizeT:
597
923k
      PutUnaligned(static_cast<size_t*>(opt_address), ParseSizeT(value));
598
923k
      break;
599
0
    case OptionType::kAtomicInt:
600
0
      static_cast<std::atomic<int>*>(opt_address)
601
0
          ->store(ParseInt(value), std::memory_order_release);
602
0
      break;
603
37.3k
    case OptionType::kString:
604
37.3k
      *static_cast<std::string*>(opt_address) = value;
605
37.3k
      break;
606
330k
    case OptionType::kDouble:
607
330k
      *static_cast<double*>(opt_address) = ParseDouble(value);
608
330k
      break;
609
55.0k
    case OptionType::kCompactionStyle:
610
55.0k
      return ParseEnum<CompactionStyle>(
611
55.0k
          compaction_style_string_map, value,
612
55.0k
          static_cast<CompactionStyle*>(opt_address));
613
55.0k
    case OptionType::kCompactionPri:
614
55.0k
      return ParseEnum<CompactionPri>(compaction_pri_string_map, value,
615
55.0k
                                      static_cast<CompactionPri*>(opt_address));
616
202k
    case OptionType::kCompressionType:
617
202k
      return ParseEnum<CompressionType>(
618
202k
          compression_type_string_map, value,
619
202k
          static_cast<CompressionType*>(opt_address));
620
55.0k
    case OptionType::kChecksumType:
621
55.0k
      return ParseEnum<ChecksumType>(checksum_type_string_map, value,
622
55.0k
                                     static_cast<ChecksumType*>(opt_address));
623
0
    case OptionType::kEncodingType:
624
0
      return ParseEnum<EncodingType>(encoding_type_string_map, value,
625
0
                                     static_cast<EncodingType*>(opt_address));
626
55.0k
    case OptionType::kCompactionStopStyle:
627
55.0k
      return ParseEnum<CompactionStopStyle>(
628
55.0k
          compaction_stop_style_string_map, value,
629
55.0k
          static_cast<CompactionStopStyle*>(opt_address));
630
0
    case OptionType::kEncodedString: {
631
0
      std::string* output_addr = static_cast<std::string*>(opt_address);
632
0
      (Slice(value)).DecodeHex(output_addr);
633
0
      break;
634
0
    }
635
239k
    case OptionType::kTemperature: {
636
239k
      return ParseEnum<Temperature>(temperature_string_map, value,
637
239k
                                    static_cast<Temperature*>(opt_address));
638
0
    }
639
0
    default:
640
0
      return false;
641
10.7M
  }
642
10.0M
  return true;
643
10.7M
}
644
645
bool SerializeSingleOptionHelper(const void* opt_address,
646
                                 const OptionType opt_type,
647
23.4M
                                 std::string* value) {
648
23.4M
  assert(value);
649
23.4M
  switch (opt_type) {
650
8.77M
    case OptionType::kBoolean:
651
8.77M
      *value = *(static_cast<const bool*>(opt_address)) ? "true" : "false";
652
8.77M
      break;
653
4.06M
    case OptionType::kInt:
654
4.06M
      *value = std::to_string(*(static_cast<const int*>(opt_address)));
655
4.06M
      break;
656
0
    case OptionType::kInt32T:
657
0
      *value = std::to_string(*(static_cast<const int32_t*>(opt_address)));
658
0
      break;
659
110k
    case OptionType::kInt64T: {
660
110k
      int64_t v;
661
110k
      GetUnaligned(static_cast<const int64_t*>(opt_address), &v);
662
110k
      *value = std::to_string(v);
663
110k
    } break;
664
589k
    case OptionType::kUInt:
665
589k
      *value = std::to_string(*(static_cast<const unsigned int*>(opt_address)));
666
589k
      break;
667
110k
    case OptionType::kUInt8T:
668
110k
      *value = std::to_string(*(static_cast<const uint8_t*>(opt_address)));
669
110k
      break;
670
1.72M
    case OptionType::kUInt32T:
671
1.72M
      *value = std::to_string(*(static_cast<const uint32_t*>(opt_address)));
672
1.72M
      break;
673
3.54M
    case OptionType::kUInt64T: {
674
3.54M
      uint64_t v;
675
3.54M
      GetUnaligned(static_cast<const uint64_t*>(opt_address), &v);
676
3.54M
      *value = std::to_string(v);
677
3.54M
    } break;
678
2.12M
    case OptionType::kSizeT: {
679
2.12M
      size_t v;
680
2.12M
      GetUnaligned(static_cast<const size_t*>(opt_address), &v);
681
2.12M
      *value = std::to_string(v);
682
2.12M
    } break;
683
715k
    case OptionType::kDouble:
684
715k
      *value = std::to_string(*(static_cast<const double*>(opt_address)));
685
715k
      break;
686
0
    case OptionType::kAtomicInt:
687
0
      *value = std::to_string(static_cast<const std::atomic<int>*>(opt_address)
688
0
                                  ->load(std::memory_order_acquire));
689
0
      break;
690
298k
    case OptionType::kString:
691
298k
      *value =
692
298k
          EscapeOptionString(*(static_cast<const std::string*>(opt_address)));
693
298k
      break;
694
110k
    case OptionType::kCompactionStyle:
695
110k
      return SerializeEnum<CompactionStyle>(
696
110k
          compaction_style_string_map,
697
110k
          *(static_cast<const CompactionStyle*>(opt_address)), value);
698
110k
    case OptionType::kCompactionPri:
699
110k
      return SerializeEnum<CompactionPri>(
700
110k
          compaction_pri_string_map,
701
110k
          *(static_cast<const CompactionPri*>(opt_address)), value);
702
404k
    case OptionType::kCompressionType:
703
404k
      return SerializeEnum<CompressionType>(
704
404k
          compression_type_string_map,
705
404k
          *(static_cast<const CompressionType*>(opt_address)), value);
706
165k
    case OptionType::kChecksumType:
707
165k
      return SerializeEnum<ChecksumType>(
708
165k
          checksum_type_string_map,
709
165k
          *static_cast<const ChecksumType*>(opt_address), value);
710
0
    case OptionType::kEncodingType:
711
0
      return SerializeEnum<EncodingType>(
712
0
          encoding_type_string_map,
713
0
          *static_cast<const EncodingType*>(opt_address), value);
714
110k
    case OptionType::kCompactionStopStyle:
715
110k
      return SerializeEnum<CompactionStopStyle>(
716
110k
          compaction_stop_style_string_map,
717
110k
          *static_cast<const CompactionStopStyle*>(opt_address), value);
718
0
    case OptionType::kEncodedString: {
719
0
      const auto* ptr = static_cast<const std::string*>(opt_address);
720
0
      *value = (Slice(*ptr)).ToString(true);
721
0
      break;
722
0
    }
723
479k
    case OptionType::kTemperature: {
724
479k
      return SerializeEnum<Temperature>(
725
479k
          temperature_string_map, *static_cast<const Temperature*>(opt_address),
726
479k
          value);
727
0
    }
728
0
    default:
729
0
      return false;
730
23.4M
  }
731
22.0M
  return true;
732
23.4M
}
733
734
template <typename T>
735
Status ConfigureFromMap(
736
    const ConfigOptions& config_options,
737
    const std::unordered_map<std::string, std::string>& opt_map,
738
92.3k
    const std::string& option_name, Configurable* config, T* new_opts) {
739
92.3k
  Status s = config->ConfigureFromMap(config_options, opt_map);
740
92.3k
  if (s.ok()) {
741
92.3k
    *new_opts = *(config->GetOptions<T>(option_name));
742
92.3k
  }
743
92.3k
  return s;
744
92.3k
}
rocksdb::Status rocksdb::ConfigureFromMap<rocksdb::ColumnFamilyOptions>(rocksdb::ConfigOptions const&, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, rocksdb::Configurable*, rocksdb::ColumnFamilyOptions*)
Line
Count
Source
738
55.0k
    const std::string& option_name, Configurable* config, T* new_opts) {
739
55.0k
  Status s = config->ConfigureFromMap(config_options, opt_map);
740
55.0k
  if (s.ok()) {
741
55.0k
    *new_opts = *(config->GetOptions<T>(option_name));
742
55.0k
  }
743
55.0k
  return s;
744
55.0k
}
rocksdb::Status rocksdb::ConfigureFromMap<rocksdb::DBOptions>(rocksdb::ConfigOptions const&, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, rocksdb::Configurable*, rocksdb::DBOptions*)
Line
Count
Source
738
37.3k
    const std::string& option_name, Configurable* config, T* new_opts) {
739
37.3k
  Status s = config->ConfigureFromMap(config_options, opt_map);
740
37.3k
  if (s.ok()) {
741
37.3k
    *new_opts = *(config->GetOptions<T>(option_name));
742
37.3k
  }
743
37.3k
  return s;
744
37.3k
}
745
746
Status StringToMap(const std::string& opts_str,
747
385k
                   std::unordered_map<std::string, std::string>* opts_map) {
748
385k
  assert(opts_map);
749
  // Example:
750
  //   opts_str = "write_buffer_size=1024;max_write_buffer_number=2;"
751
  //              "nested_opt={opt1=1;opt2=2};max_bytes_for_level_base=100"
752
385k
  size_t pos = 0;
753
385k
  std::string opts = trim(opts_str);
754
  // If the input string starts and ends with "{...}", strip off the brackets
755
660k
  while (opts.size() > 2 && opts[0] == '{' && opts[opts.size() - 1] == '}') {
756
275k
    opts = trim(opts.substr(1, opts.size() - 2));
757
275k
  }
758
759
2.64M
  while (pos < opts.size()) {
760
2.25M
    size_t eq_pos = opts.find_first_of("={};", pos);
761
2.25M
    if (eq_pos == std::string::npos) {
762
0
      return Status::InvalidArgument("Mismatched key value pair, '=' expected");
763
2.25M
    } else if (opts[eq_pos] != '=') {
764
0
      return Status::InvalidArgument("Unexpected char in key");
765
0
    }
766
767
2.25M
    std::string key = trim(opts.substr(pos, eq_pos - pos));
768
2.25M
    if (key.empty()) {
769
0
      return Status::InvalidArgument("Empty key found");
770
0
    }
771
772
2.25M
    std::string value;
773
2.25M
    Status s = OptionTypeInfo::NextToken(opts, ';', eq_pos + 1, &pos, &value);
774
2.25M
    if (!s.ok()) {
775
0
      return s;
776
2.25M
    } else {
777
2.25M
      (*opts_map)[key] = value;
778
2.25M
      if (pos == std::string::npos) {
779
0
        break;
780
2.25M
      } else {
781
2.25M
        pos++;
782
2.25M
      }
783
2.25M
    }
784
2.25M
  }
785
786
385k
  return Status::OK();
787
385k
}
788
789
Status GetStringFromDBOptions(std::string* opt_string,
790
                              const DBOptions& db_options,
791
0
                              const std::string& delimiter) {
792
0
  ConfigOptions config_options(db_options);
793
0
  config_options.delimiter = delimiter;
794
0
  return GetStringFromDBOptions(config_options, db_options, opt_string);
795
0
}
796
797
Status GetStringFromDBOptions(const ConfigOptions& config_options,
798
                              const DBOptions& db_options,
799
37.3k
                              std::string* opt_string) {
800
37.3k
  assert(opt_string);
801
37.3k
  opt_string->clear();
802
37.3k
  auto config = DBOptionsAsConfigurable(db_options);
803
37.3k
  return config->GetOptionString(config_options, opt_string);
804
37.3k
}
805
806
Status GetStringFromColumnFamilyOptions(std::string* opt_string,
807
                                        const ColumnFamilyOptions& cf_options,
808
0
                                        const std::string& delimiter) {
809
0
  ConfigOptions config_options;
810
0
  config_options.delimiter = delimiter;
811
0
  return GetStringFromColumnFamilyOptions(config_options, cf_options,
812
0
                                          opt_string);
813
0
}
814
815
Status GetStringFromColumnFamilyOptions(const ConfigOptions& config_options,
816
                                        const ColumnFamilyOptions& cf_options,
817
55.0k
                                        std::string* opt_string) {
818
55.0k
  const auto config = CFOptionsAsConfigurable(cf_options);
819
55.0k
  return config->GetOptionString(config_options, opt_string);
820
55.0k
}
821
822
Status GetStringFromCompressionType(std::string* compression_str,
823
0
                                    CompressionType compression_type) {
824
0
  bool ok = SerializeEnum<CompressionType>(compression_type_string_map,
825
0
                                           compression_type, compression_str);
826
0
  if (ok) {
827
0
    return Status::OK();
828
0
  } else {
829
0
    return Status::InvalidArgument("Invalid compression types");
830
0
  }
831
0
}
832
833
Status GetColumnFamilyOptionsFromMap(
834
    const ConfigOptions& config_options,
835
    const ColumnFamilyOptions& base_options,
836
    const std::unordered_map<std::string, std::string>& opts_map,
837
55.0k
    ColumnFamilyOptions* new_options) {
838
55.0k
  assert(new_options);
839
840
55.0k
  *new_options = base_options;
841
842
55.0k
  const auto config = CFOptionsAsConfigurable(base_options);
843
55.0k
  Status s = ConfigureFromMap<ColumnFamilyOptions>(
844
55.0k
      config_options, opts_map, OptionsHelper::kCFOptionsName, config.get(),
845
55.0k
      new_options);
846
  // Translate any errors (NotFound, NotSupported, to InvalidArgument
847
55.0k
  if (s.ok() || s.IsInvalidArgument()) {
848
55.0k
    return s;
849
55.0k
  } else {
850
0
    return Status::InvalidArgument(s.getState());
851
0
  }
852
55.0k
}
853
854
Status GetColumnFamilyOptionsFromString(const ConfigOptions& config_options,
855
                                        const ColumnFamilyOptions& base_options,
856
                                        const std::string& opts_str,
857
0
                                        ColumnFamilyOptions* new_options) {
858
0
  std::unordered_map<std::string, std::string> opts_map;
859
0
  Status s = StringToMap(opts_str, &opts_map);
860
0
  if (!s.ok()) {
861
0
    *new_options = base_options;
862
0
    return s;
863
0
  }
864
0
  return GetColumnFamilyOptionsFromMap(config_options, base_options, opts_map,
865
0
                                       new_options);
866
0
}
867
868
Status GetDBOptionsFromMap(
869
    const ConfigOptions& config_options, const DBOptions& base_options,
870
    const std::unordered_map<std::string, std::string>& opts_map,
871
37.3k
    DBOptions* new_options) {
872
37.3k
  assert(new_options);
873
37.3k
  *new_options = base_options;
874
37.3k
  auto config = DBOptionsAsConfigurable(base_options);
875
37.3k
  Status s = ConfigureFromMap<DBOptions>(config_options, opts_map,
876
37.3k
                                         OptionsHelper::kDBOptionsName,
877
37.3k
                                         config.get(), new_options);
878
  // Translate any errors (NotFound, NotSupported, to InvalidArgument
879
37.3k
  if (s.ok() || s.IsInvalidArgument()) {
880
37.3k
    return s;
881
37.3k
  } else {
882
0
    return Status::InvalidArgument(s.getState());
883
0
  }
884
37.3k
}
885
886
Status GetDBOptionsFromString(const ConfigOptions& config_options,
887
                              const DBOptions& base_options,
888
                              const std::string& opts_str,
889
0
                              DBOptions* new_options) {
890
0
  std::unordered_map<std::string, std::string> opts_map;
891
0
  Status s = StringToMap(opts_str, &opts_map);
892
0
  if (!s.ok()) {
893
0
    *new_options = base_options;
894
0
    return s;
895
0
  }
896
0
  return GetDBOptionsFromMap(config_options, base_options, opts_map,
897
0
                             new_options);
898
0
}
899
900
Status GetOptionsFromString(const Options& base_options,
901
0
                            const std::string& opts_str, Options* new_options) {
902
0
  ConfigOptions config_options(base_options);
903
0
  config_options.input_strings_escaped = false;
904
0
  config_options.ignore_unknown_options = false;
905
906
0
  return GetOptionsFromString(config_options, base_options, opts_str,
907
0
                              new_options);
908
0
}
909
910
Status GetOptionsFromString(const ConfigOptions& config_options,
911
                            const Options& base_options,
912
0
                            const std::string& opts_str, Options* new_options) {
913
0
  ColumnFamilyOptions new_cf_options;
914
0
  std::unordered_map<std::string, std::string> unused_opts;
915
0
  std::unordered_map<std::string, std::string> opts_map;
916
917
0
  assert(new_options);
918
0
  *new_options = base_options;
919
0
  Status s = StringToMap(opts_str, &opts_map);
920
0
  if (!s.ok()) {
921
0
    return s;
922
0
  }
923
0
  auto config = DBOptionsAsConfigurable(base_options);
924
0
  s = config->ConfigureFromMap(config_options, opts_map, &unused_opts);
925
926
0
  if (s.ok()) {
927
0
    DBOptions* new_db_options =
928
0
        config->GetOptions<DBOptions>(OptionsHelper::kDBOptionsName);
929
0
    if (!unused_opts.empty()) {
930
0
      s = GetColumnFamilyOptionsFromMap(config_options, base_options,
931
0
                                        unused_opts, &new_cf_options);
932
0
      if (s.ok()) {
933
0
        *new_options = Options(*new_db_options, new_cf_options);
934
0
      }
935
0
    } else {
936
0
      *new_options = Options(*new_db_options, base_options);
937
0
    }
938
0
  }
939
  // Translate any errors (NotFound, NotSupported, to InvalidArgument
940
0
  if (s.ok() || s.IsInvalidArgument()) {
941
0
    return s;
942
0
  } else {
943
0
    return Status::InvalidArgument(s.getState());
944
0
  }
945
0
}
946
947
std::unordered_map<std::string, EncodingType>
948
    OptionsHelper::encoding_type_string_map = {{"kPlain", kPlain},
949
                                               {"kPrefix", kPrefix}};
950
951
std::unordered_map<std::string, CompactionStyle>
952
    OptionsHelper::compaction_style_string_map = {
953
        {"kCompactionStyleLevel", kCompactionStyleLevel},
954
        {"kCompactionStyleUniversal", kCompactionStyleUniversal},
955
        {"kCompactionStyleFIFO", kCompactionStyleFIFO},
956
        {"kCompactionStyleNone", kCompactionStyleNone}};
957
958
std::unordered_map<std::string, CompactionPri>
959
    OptionsHelper::compaction_pri_string_map = {
960
        {"kByCompensatedSize", kByCompensatedSize},
961
        {"kOldestLargestSeqFirst", kOldestLargestSeqFirst},
962
        {"kOldestSmallestSeqFirst", kOldestSmallestSeqFirst},
963
        {"kMinOverlappingRatio", kMinOverlappingRatio},
964
        {"kRoundRobin", kRoundRobin}};
965
966
std::unordered_map<std::string, CompactionStopStyle>
967
    OptionsHelper::compaction_stop_style_string_map = {
968
        {"kCompactionStopStyleSimilarSize", kCompactionStopStyleSimilarSize},
969
        {"kCompactionStopStyleTotalSize", kCompactionStopStyleTotalSize}};
970
971
std::unordered_map<std::string, Temperature>
972
    OptionsHelper::temperature_string_map = {
973
        {"kUnknown", Temperature::kUnknown}, {"kHot", Temperature::kHot},
974
        {"kWarm", Temperature::kWarm},       {"kCool", Temperature::kCool},
975
        {"kCold", Temperature::kCold},       {"kIce", Temperature::kIce}};
976
977
std::unordered_map<std::string, PrepopulateBlobCache>
978
    OptionsHelper::prepopulate_blob_cache_string_map = {
979
        {"kDisable", PrepopulateBlobCache::kDisable},
980
        {"kFlushOnly", PrepopulateBlobCache::kFlushOnly}};
981
982
Status OptionTypeInfo::NextToken(const std::string& opts, char delimiter,
983
2.64M
                                 size_t pos, size_t* end, std::string* token) {
984
2.64M
  while (pos < opts.size() && isspace(opts[pos])) {
985
0
    ++pos;
986
0
  }
987
  // Empty value at the end
988
2.64M
  if (pos >= opts.size()) {
989
0
    *token = "";
990
0
    *end = std::string::npos;
991
0
    return Status::OK();
992
2.64M
  } else if (opts[pos] == '{') {
993
0
    int count = 1;
994
0
    size_t brace_pos = pos + 1;
995
0
    while (brace_pos < opts.size()) {
996
0
      if (opts[brace_pos] == '{') {
997
0
        ++count;
998
0
      } else if (opts[brace_pos] == '}') {
999
0
        --count;
1000
0
        if (count == 0) {
1001
0
          break;
1002
0
        }
1003
0
      }
1004
0
      ++brace_pos;
1005
0
    }
1006
    // found the matching closing brace
1007
0
    if (count == 0) {
1008
0
      *token = trim(opts.substr(pos + 1, brace_pos - pos - 1));
1009
      // skip all whitespace and move to the next delimiter
1010
      // brace_pos points to the next position after the matching '}'
1011
0
      pos = brace_pos + 1;
1012
0
      while (pos < opts.size() && isspace(opts[pos])) {
1013
0
        ++pos;
1014
0
      }
1015
0
      if (pos < opts.size() && opts[pos] != delimiter) {
1016
0
        return Status::InvalidArgument("Unexpected chars after nested options");
1017
0
      }
1018
0
      *end = pos;
1019
0
    } else {
1020
0
      return Status::InvalidArgument(
1021
0
          "Mismatched curly braces for nested options");
1022
0
    }
1023
2.64M
  } else {
1024
2.64M
    *end = opts.find(delimiter, pos);
1025
2.64M
    if (*end == std::string::npos) {
1026
      // It either ends with a trailing semi-colon or the last key-value pair
1027
55.0k
      *token = trim(opts.substr(pos));
1028
2.58M
    } else {
1029
2.58M
      *token = trim(opts.substr(pos, *end - pos));
1030
2.58M
    }
1031
2.64M
  }
1032
2.64M
  return Status::OK();
1033
2.64M
}
1034
1035
Status OptionTypeInfo::Parse(const ConfigOptions& config_options,
1036
                             const std::string& opt_name,
1037
12.5M
                             const std::string& value, void* opt_ptr) const {
1038
12.5M
  if (IsDeprecated()) {
1039
0
    return Status::OK();
1040
0
  }
1041
12.5M
  try {
1042
12.5M
    const std::string& opt_value = config_options.input_strings_escaped
1043
12.5M
                                       ? UnescapeOptionString(value)
1044
12.5M
                                       : value;
1045
1046
12.5M
    if (opt_ptr == nullptr) {
1047
0
      return Status::NotFound("Nullptr option", opt_name);
1048
12.5M
    } else if (parse_func_ != nullptr) {
1049
1.83M
      ConfigOptions copy = config_options;
1050
1.83M
      copy.invoke_prepare_options = false;
1051
1.83M
      void* opt_addr = GetOffset(opt_ptr);
1052
1.83M
      return parse_func_(copy, opt_name, opt_value, opt_addr);
1053
10.7M
    } else if (ParseOptionHelper(GetOffset(opt_ptr), type_, opt_value)) {
1054
10.7M
      return Status::OK();
1055
10.7M
    } else if (IsConfigurable()) {
1056
      // The option is <config>.<name>
1057
0
      Configurable* config = AsRawPointer<Configurable>(opt_ptr);
1058
0
      if (opt_value.empty()) {
1059
0
        return Status::OK();
1060
0
      } else if (config == nullptr) {
1061
0
        return Status::NotFound("Could not find configurable: ", opt_name);
1062
0
      } else {
1063
0
        ConfigOptions copy = config_options;
1064
0
        copy.ignore_unknown_options = false;
1065
0
        copy.invoke_prepare_options = false;
1066
0
        if (opt_value.find('=') != std::string::npos) {
1067
0
          return config->ConfigureFromString(copy, opt_value);
1068
0
        } else {
1069
0
          return config->ConfigureOption(copy, opt_name, opt_value);
1070
0
        }
1071
0
      }
1072
0
    } else if (IsByName()) {
1073
0
      return Status::NotSupported("Deserializing the option " + opt_name +
1074
0
                                  " is not supported");
1075
0
    } else {
1076
0
      return Status::InvalidArgument("Error parsing:", opt_name);
1077
0
    }
1078
12.5M
  } catch (std::exception& e) {
1079
0
    return Status::InvalidArgument("Error parsing " + opt_name + ":" +
1080
0
                                   std::string(e.what()));
1081
0
  }
1082
12.5M
}
1083
1084
Status OptionTypeInfo::ParseType(
1085
    const ConfigOptions& config_options, const std::string& opts_str,
1086
    const std::unordered_map<std::string, OptionTypeInfo>& type_map,
1087
275k
    void* opt_addr, std::unordered_map<std::string, std::string>* unused) {
1088
275k
  std::unordered_map<std::string, std::string> opts_map;
1089
275k
  Status status = StringToMap(opts_str, &opts_map);
1090
275k
  if (!status.ok()) {
1091
0
    return status;
1092
275k
  } else {
1093
275k
    return ParseType(config_options, opts_map, type_map, opt_addr, unused);
1094
275k
  }
1095
275k
}
1096
1097
Status OptionTypeInfo::ParseType(
1098
    const ConfigOptions& config_options,
1099
    const std::unordered_map<std::string, std::string>& opts_map,
1100
    const std::unordered_map<std::string, OptionTypeInfo>& type_map,
1101
275k
    void* opt_addr, std::unordered_map<std::string, std::string>* unused) {
1102
2.25M
  for (const auto& opts_iter : opts_map) {
1103
2.25M
    std::string opt_name;
1104
2.25M
    const auto* opt_info = Find(opts_iter.first, type_map, &opt_name);
1105
2.25M
    if (opt_info != nullptr) {
1106
2.25M
      Status status =
1107
2.25M
          opt_info->Parse(config_options, opt_name, opts_iter.second, opt_addr);
1108
2.25M
      if (!status.ok()) {
1109
0
        return status;
1110
0
      }
1111
2.25M
    } else if (unused != nullptr) {
1112
0
      (*unused)[opts_iter.first] = opts_iter.second;
1113
0
    } else if (!config_options.ignore_unknown_options) {
1114
0
      return Status::NotFound("Unrecognized option", opts_iter.first);
1115
0
    }
1116
2.25M
  }
1117
275k
  return Status::OK();
1118
275k
}
1119
1120
Status OptionTypeInfo::ParseStruct(
1121
    const ConfigOptions& config_options, const std::string& struct_name,
1122
    const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
1123
275k
    const std::string& opt_name, const std::string& opt_value, void* opt_addr) {
1124
275k
  assert(struct_map);
1125
275k
  Status status;
1126
275k
  if (opt_name == struct_name || EndsWith(opt_name, "." + struct_name)) {
1127
    // This option represents the entire struct
1128
275k
    std::unordered_map<std::string, std::string> unused;
1129
275k
    status =
1130
275k
        ParseType(config_options, opt_value, *struct_map, opt_addr, &unused);
1131
275k
    if (status.ok() && !unused.empty() &&
1132
0
        !config_options.ignore_unknown_options) {
1133
0
      status = Status::InvalidArgument(
1134
0
          "Unrecognized option", struct_name + "." + unused.begin()->first);
1135
0
    }
1136
275k
  } else if (StartsWith(opt_name, struct_name + ".")) {
1137
    // This option represents a nested field in the struct (e.g, struct.field)
1138
0
    std::string elem_name;
1139
0
    const auto opt_info =
1140
0
        Find(opt_name.substr(struct_name.size() + 1), *struct_map, &elem_name);
1141
0
    if (opt_info != nullptr) {
1142
0
      status = opt_info->Parse(config_options, elem_name, opt_value, opt_addr);
1143
0
    } else if (!config_options.ignore_unknown_options) {
1144
0
      status = Status::InvalidArgument("Unrecognized option", opt_name);
1145
0
    }
1146
0
  } else {
1147
    // This option represents a field in the struct (e.g. field)
1148
0
    std::string elem_name;
1149
0
    const auto opt_info = Find(opt_name, *struct_map, &elem_name);
1150
0
    if (opt_info != nullptr) {
1151
0
      status = opt_info->Parse(config_options, elem_name, opt_value, opt_addr);
1152
0
    } else if (!config_options.ignore_unknown_options) {
1153
0
      status = Status::InvalidArgument("Unrecognized option",
1154
0
                                       struct_name + "." + opt_name);
1155
0
    }
1156
0
  }
1157
275k
  return status;
1158
275k
}
1159
1160
Status OptionTypeInfo::Serialize(const ConfigOptions& config_options,
1161
                                 const std::string& opt_name,
1162
                                 const void* const opt_ptr,
1163
27.9M
                                 std::string* opt_value) const {
1164
  // If the option is no longer used in rocksdb and marked as deprecated,
1165
  // we skip it in the serialization.
1166
27.9M
  if (opt_ptr == nullptr || IsDeprecated()) {
1167
0
    return Status::OK();
1168
27.9M
  } else if (IsEnabled(OptionTypeFlags::kDontSerialize)) {
1169
0
    return Status::NotSupported("Cannot serialize option: ", opt_name);
1170
27.9M
  } else if (serialize_func_ != nullptr) {
1171
2.88M
    const void* opt_addr = GetOffset(opt_ptr);
1172
2.88M
    return serialize_func_(config_options, opt_name, opt_addr, opt_value);
1173
25.0M
  } else if (IsCustomizable()) {
1174
1.63M
    const Customizable* custom = AsRawPointer<Customizable>(opt_ptr);
1175
1.63M
    opt_value->clear();
1176
1.63M
    if (custom == nullptr) {
1177
      // We do not have a custom object to serialize.
1178
      // If the option is not mutable and we are doing only mutable options,
1179
      // we return an empty string (which will cause the option not to be
1180
      // printed). Otherwise, we return the "nullptr" string, which will result
1181
      // in "option=nullptr" being printed.
1182
1.24M
      if (IsMutable() || !config_options.mutable_options_only) {
1183
1.24M
        *opt_value = kNullptrString;
1184
1.24M
      } else {
1185
0
        *opt_value = "";
1186
0
      }
1187
1.24M
    } else if (IsEnabled(OptionTypeFlags::kStringNameOnly) &&
1188
110k
               !config_options.IsDetailed()) {
1189
55.0k
      if (!config_options.mutable_options_only || IsMutable()) {
1190
55.0k
        *opt_value = custom->GetId();
1191
55.0k
      }
1192
330k
    } else {
1193
330k
      ConfigOptions embedded = config_options;
1194
330k
      embedded.delimiter = ";";
1195
      // If this option is mutable, everything inside it should be considered
1196
      // mutable
1197
330k
      if (IsMutable()) {
1198
55.0k
        embedded.mutable_options_only = false;
1199
55.0k
      }
1200
330k
      std::string value = custom->ToString(embedded);
1201
330k
      if (!embedded.mutable_options_only ||
1202
330k
          value.find('=') != std::string::npos) {
1203
330k
        *opt_value = value;
1204
330k
      } else {
1205
0
        *opt_value = "";
1206
0
      }
1207
330k
    }
1208
1.63M
    return Status::OK();
1209
23.4M
  } else if (IsConfigurable()) {
1210
0
    const Configurable* config = AsRawPointer<Configurable>(opt_ptr);
1211
0
    if (config != nullptr) {
1212
0
      ConfigOptions embedded = config_options;
1213
0
      embedded.delimiter = ";";
1214
0
      *opt_value = config->ToString(embedded);
1215
0
    }
1216
0
    return Status::OK();
1217
23.4M
  } else if (config_options.mutable_options_only && !IsMutable()) {
1218
0
    return Status::OK();
1219
23.4M
  } else if (SerializeSingleOptionHelper(GetOffset(opt_ptr), type_,
1220
23.4M
                                         opt_value)) {
1221
23.4M
    return Status::OK();
1222
23.4M
  } else {
1223
0
    return Status::InvalidArgument("Cannot serialize option: ", opt_name);
1224
0
  }
1225
27.9M
}
1226
1227
Status OptionTypeInfo::SerializeType(
1228
    const ConfigOptions& config_options,
1229
    const std::unordered_map<std::string, OptionTypeInfo>& type_map,
1230
605k
    const void* opt_addr, std::string* result) {
1231
605k
  Status status;
1232
4.78M
  for (const auto& iter : type_map) {
1233
4.78M
    std::string single;
1234
4.78M
    const auto& opt_info = iter.second;
1235
4.78M
    if (opt_info.ShouldSerialize()) {
1236
4.67M
      status =
1237
4.67M
          opt_info.Serialize(config_options, iter.first, opt_addr, &single);
1238
4.67M
      if (!status.ok()) {
1239
0
        return status;
1240
4.67M
      } else {
1241
4.67M
        result->append(iter.first + "=" + single + config_options.delimiter);
1242
4.67M
      }
1243
4.67M
    }
1244
4.78M
  }
1245
605k
  return status;
1246
605k
}
1247
1248
Status OptionTypeInfo::SerializeStruct(
1249
    const ConfigOptions& config_options, const std::string& struct_name,
1250
    const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
1251
605k
    const std::string& opt_name, const void* opt_addr, std::string* value) {
1252
605k
  assert(struct_map);
1253
605k
  Status status;
1254
605k
  if (EndsWith(opt_name, struct_name)) {
1255
    // We are going to write the struct as "{ prop1=value1; prop2=value2;}.
1256
    // Set the delimiter to ";" so that the everything will be on one line.
1257
605k
    ConfigOptions embedded = config_options;
1258
605k
    embedded.delimiter = ";";
1259
1260
    // This option represents the entire struct
1261
605k
    std::string result;
1262
605k
    status = SerializeType(embedded, *struct_map, opt_addr, &result);
1263
605k
    if (!status.ok()) {
1264
0
      return status;
1265
605k
    } else {
1266
605k
      *value = "{" + result + "}";
1267
605k
    }
1268
605k
  } else if (StartsWith(opt_name, struct_name + ".")) {
1269
    // This option represents a nested field in the struct (e.g, struct.field)
1270
0
    std::string elem_name;
1271
0
    const auto opt_info =
1272
0
        Find(opt_name.substr(struct_name.size() + 1), *struct_map, &elem_name);
1273
0
    if (opt_info != nullptr) {
1274
0
      status = opt_info->Serialize(config_options, elem_name, opt_addr, value);
1275
0
    } else {
1276
0
      status = Status::InvalidArgument("Unrecognized option", opt_name);
1277
0
    }
1278
0
  } else {
1279
    // This option represents a field in the struct (e.g. field)
1280
0
    std::string elem_name;
1281
0
    const auto opt_info = Find(opt_name, *struct_map, &elem_name);
1282
0
    if (opt_info == nullptr) {
1283
0
      status = Status::InvalidArgument("Unrecognized option", opt_name);
1284
0
    } else if (opt_info->ShouldSerialize()) {
1285
0
      status = opt_info->Serialize(config_options, opt_name + "." + elem_name,
1286
0
                                   opt_addr, value);
1287
0
    }
1288
0
  }
1289
605k
  return status;
1290
605k
}
1291
1292
template <typename T>
1293
6.69M
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
6.69M
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
6.69M
}
bool rocksdb::IsOptionEqual<bool>(void const*, void const*)
Line
Count
Source
1293
3.64M
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
3.64M
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
3.64M
}
bool rocksdb::IsOptionEqual<int>(void const*, void const*)
Line
Count
Source
1293
1.39M
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
1.39M
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
1.39M
}
bool rocksdb::IsOptionEqual<unsigned int>(void const*, void const*)
Line
Count
Source
1293
882k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
882k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
882k
}
bool rocksdb::IsOptionEqual<unsigned char>(void const*, void const*)
Line
Count
Source
1293
55.0k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
55.0k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
55.0k
}
Unexecuted instantiation: bool rocksdb::IsOptionEqual<std::__1::atomic<int> >(void const*, void const*)
bool rocksdb::IsOptionEqual<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(void const*, void const*)
Line
Count
Source
1293
112k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
112k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
112k
}
bool rocksdb::IsOptionEqual<rocksdb::CompactionStyle>(void const*, void const*)
Line
Count
Source
1293
55.0k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
55.0k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
55.0k
}
bool rocksdb::IsOptionEqual<rocksdb::CompactionStopStyle>(void const*, void const*)
Line
Count
Source
1293
55.0k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
55.0k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
55.0k
}
bool rocksdb::IsOptionEqual<rocksdb::CompactionPri>(void const*, void const*)
Line
Count
Source
1293
55.0k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
55.0k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
55.0k
}
bool rocksdb::IsOptionEqual<rocksdb::CompressionType>(void const*, void const*)
Line
Count
Source
1293
202k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
202k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
202k
}
bool rocksdb::IsOptionEqual<rocksdb::ChecksumType>(void const*, void const*)
Line
Count
Source
1293
55.0k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
55.0k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
55.0k
}
Unexecuted instantiation: bool rocksdb::IsOptionEqual<rocksdb::EncodingType>(void const*, void const*)
bool rocksdb::IsOptionEqual<rocksdb::Temperature>(void const*, void const*)
Line
Count
Source
1293
184k
bool IsOptionEqual(const void* offset1, const void* offset2) {
1294
184k
  return (*static_cast<const T*>(offset1) == *static_cast<const T*>(offset2));
1295
184k
}
1296
1297
330k
static bool AreEqualDoubles(const double a, const double b) {
1298
330k
  return (fabs(a - b) < 0.00001);
1299
330k
}
1300
1301
static bool AreOptionsEqual(OptionType type, const void* this_offset,
1302
10.3M
                            const void* that_offset) {
1303
10.3M
  switch (type) {
1304
3.64M
    case OptionType::kBoolean:
1305
3.64M
      return IsOptionEqual<bool>(this_offset, that_offset);
1306
1.39M
    case OptionType::kInt:
1307
1.39M
      return IsOptionEqual<int>(this_offset, that_offset);
1308
294k
    case OptionType::kUInt:
1309
294k
      return IsOptionEqual<unsigned int>(this_offset, that_offset);
1310
0
    case OptionType::kInt32T:
1311
0
      return IsOptionEqual<int32_t>(this_offset, that_offset);
1312
55.0k
    case OptionType::kInt64T: {
1313
55.0k
      int64_t v1, v2;
1314
55.0k
      GetUnaligned(static_cast<const int64_t*>(this_offset), &v1);
1315
55.0k
      GetUnaligned(static_cast<const int64_t*>(that_offset), &v2);
1316
55.0k
      return (v1 == v2);
1317
0
    }
1318
55.0k
    case OptionType::kUInt8T:
1319
55.0k
      return IsOptionEqual<uint8_t>(this_offset, that_offset);
1320
587k
    case OptionType::kUInt32T:
1321
587k
      return IsOptionEqual<uint32_t>(this_offset, that_offset);
1322
1.60M
    case OptionType::kUInt64T: {
1323
1.60M
      uint64_t v1, v2;
1324
1.60M
      GetUnaligned(static_cast<const uint64_t*>(this_offset), &v1);
1325
1.60M
      GetUnaligned(static_cast<const uint64_t*>(that_offset), &v2);
1326
1.60M
      return (v1 == v2);
1327
0
    }
1328
978k
    case OptionType::kSizeT: {
1329
978k
      size_t v1, v2;
1330
978k
      GetUnaligned(static_cast<const size_t*>(this_offset), &v1);
1331
978k
      GetUnaligned(static_cast<const size_t*>(that_offset), &v2);
1332
978k
      return (v1 == v2);
1333
0
    }
1334
0
    case OptionType::kAtomicInt:
1335
0
      return IsOptionEqual<std::atomic<int>>(this_offset, that_offset);
1336
112k
    case OptionType::kString:
1337
112k
      return IsOptionEqual<std::string>(this_offset, that_offset);
1338
330k
    case OptionType::kDouble:
1339
330k
      return AreEqualDoubles(*static_cast<const double*>(this_offset),
1340
330k
                             *static_cast<const double*>(that_offset));
1341
55.0k
    case OptionType::kCompactionStyle:
1342
55.0k
      return IsOptionEqual<CompactionStyle>(this_offset, that_offset);
1343
55.0k
    case OptionType::kCompactionStopStyle:
1344
55.0k
      return IsOptionEqual<CompactionStopStyle>(this_offset, that_offset);
1345
55.0k
    case OptionType::kCompactionPri:
1346
55.0k
      return IsOptionEqual<CompactionPri>(this_offset, that_offset);
1347
202k
    case OptionType::kCompressionType:
1348
202k
      return IsOptionEqual<CompressionType>(this_offset, that_offset);
1349
55.0k
    case OptionType::kChecksumType:
1350
55.0k
      return IsOptionEqual<ChecksumType>(this_offset, that_offset);
1351
0
    case OptionType::kEncodingType:
1352
0
      return IsOptionEqual<EncodingType>(this_offset, that_offset);
1353
0
    case OptionType::kEncodedString:
1354
0
      return IsOptionEqual<std::string>(this_offset, that_offset);
1355
184k
    case OptionType::kTemperature:
1356
184k
      return IsOptionEqual<Temperature>(this_offset, that_offset);
1357
697k
    default:
1358
697k
      return false;
1359
10.3M
  }  // End switch
1360
10.3M
}
1361
1362
bool OptionTypeInfo::AreEqual(const ConfigOptions& config_options,
1363
                              const std::string& opt_name,
1364
                              const void* const this_ptr,
1365
                              const void* const that_ptr,
1366
11.4M
                              std::string* mismatch) const {
1367
11.4M
  auto level = GetSanityLevel();
1368
11.4M
  if (!config_options.IsCheckEnabled(level)) {
1369
55.0k
    return true;  // If the sanity level is not being checked, skip it
1370
55.0k
  }
1371
11.3M
  if (this_ptr == nullptr || that_ptr == nullptr) {
1372
0
    if (this_ptr == that_ptr) {
1373
0
      return true;
1374
0
    }
1375
11.3M
  } else if (equals_func_ != nullptr) {
1376
992k
    const void* this_addr = GetOffset(this_ptr);
1377
992k
    const void* that_addr = GetOffset(that_ptr);
1378
992k
    if (equals_func_(config_options, opt_name, this_addr, that_addr,
1379
992k
                     mismatch)) {
1380
992k
      return true;
1381
992k
    }
1382
10.3M
  } else {
1383
10.3M
    const void* this_addr = GetOffset(this_ptr);
1384
10.3M
    const void* that_addr = GetOffset(that_ptr);
1385
10.3M
    if (AreOptionsEqual(type_, this_addr, that_addr)) {
1386
9.66M
      return true;
1387
9.66M
    } else if (IsConfigurable()) {
1388
697k
      const auto* this_config = AsRawPointer<Configurable>(this_ptr);
1389
697k
      const auto* that_config = AsRawPointer<Configurable>(that_ptr);
1390
697k
      if (this_config == that_config) {
1391
587k
        return true;
1392
587k
      } else if (this_config != nullptr && that_config != nullptr) {
1393
110k
        std::string bad_name;
1394
110k
        bool matches;
1395
110k
        if (level < config_options.sanity_level) {
1396
55.0k
          ConfigOptions copy = config_options;
1397
55.0k
          copy.sanity_level = level;
1398
55.0k
          matches = this_config->AreEquivalent(copy, that_config, &bad_name);
1399
55.0k
        } else {
1400
55.0k
          matches = this_config->AreEquivalent(config_options, that_config,
1401
55.0k
                                               &bad_name);
1402
55.0k
        }
1403
110k
        if (!matches) {
1404
0
          *mismatch = opt_name + "." + bad_name;
1405
0
        }
1406
110k
        return matches;
1407
110k
      }
1408
697k
    }
1409
10.3M
  }
1410
0
  if (mismatch->empty()) {
1411
0
    *mismatch = opt_name;
1412
0
  }
1413
0
  return false;
1414
11.3M
}
1415
1416
bool OptionTypeInfo::TypesAreEqual(
1417
    const ConfigOptions& config_options,
1418
    const std::unordered_map<std::string, OptionTypeInfo>& type_map,
1419
165k
    const void* this_addr, const void* that_addr, std::string* mismatch) {
1420
1.10M
  for (const auto& iter : type_map) {
1421
1.10M
    const auto& opt_info = iter.second;
1422
1.10M
    if (!opt_info.AreEqual(config_options, iter.first, this_addr, that_addr,
1423
1.10M
                           mismatch)) {
1424
0
      return false;
1425
0
    }
1426
1.10M
  }
1427
165k
  return true;
1428
165k
}
1429
1430
bool OptionTypeInfo::StructsAreEqual(
1431
    const ConfigOptions& config_options, const std::string& struct_name,
1432
    const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
1433
    const std::string& opt_name, const void* this_addr, const void* that_addr,
1434
165k
    std::string* mismatch) {
1435
165k
  assert(struct_map);
1436
165k
  bool matches = true;
1437
165k
  std::string result;
1438
165k
  if (EndsWith(opt_name, struct_name)) {
1439
    // This option represents the entire struct
1440
165k
    matches = TypesAreEqual(config_options, *struct_map, this_addr, that_addr,
1441
165k
                            &result);
1442
165k
    if (!matches) {
1443
0
      *mismatch = struct_name + "." + result;
1444
0
      return false;
1445
0
    }
1446
165k
  } else if (StartsWith(opt_name, struct_name + ".")) {
1447
    // This option represents a nested field in the struct (e.g, struct.field)
1448
0
    std::string elem_name;
1449
0
    const auto opt_info =
1450
0
        Find(opt_name.substr(struct_name.size() + 1), *struct_map, &elem_name);
1451
0
    assert(opt_info);
1452
0
    if (opt_info == nullptr) {
1453
0
      *mismatch = opt_name;
1454
0
      matches = false;
1455
0
    } else if (!opt_info->AreEqual(config_options, elem_name, this_addr,
1456
0
                                   that_addr, &result)) {
1457
0
      matches = false;
1458
0
      *mismatch = struct_name + "." + result;
1459
0
    }
1460
0
  } else {
1461
    // This option represents a field in the struct (e.g. field)
1462
0
    std::string elem_name;
1463
0
    const auto opt_info = Find(opt_name, *struct_map, &elem_name);
1464
0
    assert(opt_info);
1465
0
    if (opt_info == nullptr) {
1466
0
      *mismatch = struct_name + "." + opt_name;
1467
0
      matches = false;
1468
0
    } else if (!opt_info->AreEqual(config_options, elem_name, this_addr,
1469
0
                                   that_addr, &result)) {
1470
0
      matches = false;
1471
0
      *mismatch = struct_name + "." + result;
1472
0
    }
1473
0
  }
1474
165k
  return matches;
1475
165k
}
1476
1477
bool MatchesOptionsTypeFromMap(
1478
    const ConfigOptions& config_options,
1479
    const std::unordered_map<std::string, OptionTypeInfo>& type_map,
1480
    const void* const this_ptr, const void* const that_ptr,
1481
0
    std::string* mismatch) {
1482
0
  for (auto& pair : type_map) {
1483
    // We skip checking deprecated variables as they might
1484
    // contain random values since they might not be initialized
1485
0
    if (config_options.IsCheckEnabled(pair.second.GetSanityLevel())) {
1486
0
      if (!pair.second.AreEqual(config_options, pair.first, this_ptr, that_ptr,
1487
0
                                mismatch) &&
1488
0
          !pair.second.AreEqualByName(config_options, pair.first, this_ptr,
1489
0
                                      that_ptr)) {
1490
0
        return false;
1491
0
      }
1492
0
    }
1493
0
  }
1494
0
  return true;
1495
0
}
1496
1497
bool OptionTypeInfo::AreEqualByName(const ConfigOptions& config_options,
1498
                                    const std::string& opt_name,
1499
                                    const void* const this_ptr,
1500
0
                                    const void* const that_ptr) const {
1501
0
  if (IsByName()) {
1502
0
    std::string that_value;
1503
0
    if (Serialize(config_options, opt_name, that_ptr, &that_value).ok()) {
1504
0
      return AreEqualByName(config_options, opt_name, this_ptr, that_value);
1505
0
    }
1506
0
  }
1507
0
  return false;
1508
0
}
1509
1510
bool OptionTypeInfo::AreEqualByName(const ConfigOptions& config_options,
1511
                                    const std::string& opt_name,
1512
                                    const void* const opt_ptr,
1513
0
                                    const std::string& that_value) const {
1514
0
  std::string this_value;
1515
0
  if (!IsByName()) {
1516
0
    return false;
1517
0
  } else if (!Serialize(config_options, opt_name, opt_ptr, &this_value).ok()) {
1518
0
    return false;
1519
0
  } else if (IsEnabled(OptionVerificationType::kByNameAllowFromNull)) {
1520
0
    if (that_value == kNullptrString) {
1521
0
      return true;
1522
0
    }
1523
0
  } else if (IsEnabled(OptionVerificationType::kByNameAllowNull)) {
1524
0
    if (that_value == kNullptrString) {
1525
0
      return true;
1526
0
    }
1527
0
  }
1528
0
  return (this_value == that_value);
1529
0
}
1530
1531
Status OptionTypeInfo::Prepare(const ConfigOptions& config_options,
1532
644k
                               const std::string& name, void* opt_ptr) const {
1533
644k
  if (ShouldPrepare()) {
1534
644k
    if (prepare_func_ != nullptr) {
1535
37.3k
      void* opt_addr = GetOffset(opt_ptr);
1536
37.3k
      return prepare_func_(config_options, name, opt_addr);
1537
607k
    } else if (IsConfigurable()) {
1538
607k
      Configurable* config = AsRawPointer<Configurable>(opt_ptr);
1539
607k
      if (config != nullptr) {
1540
110k
        return config->PrepareOptions(config_options);
1541
497k
      } else if (!CanBeNull()) {
1542
0
        return Status::NotFound("Missing configurable object", name);
1543
0
      }
1544
607k
    }
1545
644k
  }
1546
497k
  return Status::OK();
1547
644k
}
1548
1549
Status OptionTypeInfo::Validate(const DBOptions& db_opts,
1550
                                const ColumnFamilyOptions& cf_opts,
1551
                                const std::string& name,
1552
485k
                                const void* opt_ptr) const {
1553
485k
  if (ShouldValidate()) {
1554
485k
    if (validate_func_ != nullptr) {
1555
28.5k
      const void* opt_addr = GetOffset(opt_ptr);
1556
28.5k
      return validate_func_(db_opts, cf_opts, name, opt_addr);
1557
456k
    } else if (IsConfigurable()) {
1558
456k
      const Configurable* config = AsRawPointer<Configurable>(opt_ptr);
1559
456k
      if (config != nullptr) {
1560
114k
        return config->ValidateOptions(db_opts, cf_opts);
1561
342k
      } else if (!CanBeNull()) {
1562
0
        return Status::NotFound("Missing configurable object", name);
1563
0
      }
1564
456k
    }
1565
485k
  }
1566
342k
  return Status::OK();
1567
485k
}
1568
1569
const OptionTypeInfo* OptionTypeInfo::Find(
1570
    const std::string& opt_name,
1571
    const std::unordered_map<std::string, OptionTypeInfo>& opt_map,
1572
19.5M
    std::string* elem_name) {
1573
19.5M
  const auto iter = opt_map.find(opt_name);  // Look up the value in the map
1574
19.5M
  if (iter != opt_map.end()) {               // Found the option in the map
1575
12.2M
    *elem_name = opt_name;                   // Return the name
1576
12.2M
    return &(iter->second);  // Return the contents of the iterator
1577
12.2M
  } else {
1578
7.39M
    auto idx = opt_name.find('.');              // Look for a separator
1579
7.39M
    if (idx > 0 && idx != std::string::npos) {  // We found a separator
1580
0
      auto siter =
1581
0
          opt_map.find(opt_name.substr(0, idx));  // Look for the short name
1582
0
      if (siter != opt_map.end()) {               // We found the short name
1583
0
        if (siter->second.IsStruct() ||           // If the object is a struct
1584
0
            siter->second.IsConfigurable()) {     // or a Configurable
1585
0
          *elem_name = opt_name.substr(idx + 1);  // Return the rest
1586
0
          return &(siter->second);  // Return the contents of the iterator
1587
0
        }
1588
0
      }
1589
0
    }
1590
7.39M
  }
1591
7.39M
  return nullptr;
1592
19.5M
}
1593
1594
}  // namespace ROCKSDB_NAMESPACE