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