]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
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 | ||
6 | #include "rocksdb/configurable.h" | |
7 | ||
8 | #include "logging/logging.h" | |
9 | #include "options/configurable_helper.h" | |
10 | #include "options/options_helper.h" | |
11 | #include "rocksdb/customizable.h" | |
12 | #include "rocksdb/status.h" | |
13 | #include "rocksdb/utilities/object_registry.h" | |
14 | #include "rocksdb/utilities/options_type.h" | |
15 | #include "util/coding.h" | |
16 | #include "util/string_util.h" | |
17 | ||
18 | namespace ROCKSDB_NAMESPACE { | |
19 | ||
20 | void ConfigurableHelper::RegisterOptions( | |
21 | Configurable& configurable, const std::string& name, void* opt_ptr, | |
22 | const std::unordered_map<std::string, OptionTypeInfo>* type_map) { | |
23 | Configurable::RegisteredOptions opts; | |
24 | opts.name = name; | |
25 | #ifndef ROCKSDB_LITE | |
26 | opts.type_map = type_map; | |
27 | #else | |
28 | (void)type_map; | |
29 | #endif // ROCKSDB_LITE | |
30 | opts.opt_ptr = opt_ptr; | |
31 | configurable.options_.emplace_back(opts); | |
32 | } | |
33 | ||
34 | //************************************************************************* | |
35 | // | |
36 | // Methods for Initializing and Validating Configurable Objects | |
37 | // | |
38 | //************************************************************************* | |
39 | ||
40 | Status Configurable::PrepareOptions(const ConfigOptions& opts) { | |
41 | Status status = Status::OK(); | |
42 | #ifndef ROCKSDB_LITE | |
43 | for (auto opt_iter : options_) { | |
44 | for (auto map_iter : *(opt_iter.type_map)) { | |
45 | auto& opt_info = map_iter.second; | |
46 | if (!opt_info.IsDeprecated() && !opt_info.IsAlias() && | |
47 | opt_info.IsConfigurable()) { | |
48 | if (!opt_info.IsEnabled(OptionTypeFlags::kDontPrepare)) { | |
49 | Configurable* config = | |
50 | opt_info.AsRawPointer<Configurable>(opt_iter.opt_ptr); | |
51 | if (config != nullptr) { | |
52 | status = config->PrepareOptions(opts); | |
53 | if (!status.ok()) { | |
54 | return status; | |
55 | } | |
56 | } | |
57 | } | |
58 | } | |
59 | } | |
60 | } | |
61 | #else | |
62 | (void)opts; | |
63 | #endif // ROCKSDB_LITE | |
64 | if (status.ok()) { | |
65 | prepared_ = true; | |
66 | } | |
67 | return status; | |
68 | } | |
69 | ||
70 | Status Configurable::ValidateOptions(const DBOptions& db_opts, | |
71 | const ColumnFamilyOptions& cf_opts) const { | |
72 | Status status; | |
73 | #ifndef ROCKSDB_LITE | |
74 | for (auto opt_iter : options_) { | |
75 | for (auto map_iter : *(opt_iter.type_map)) { | |
76 | auto& opt_info = map_iter.second; | |
77 | if (!opt_info.IsDeprecated() && !opt_info.IsAlias()) { | |
78 | if (opt_info.IsConfigurable()) { | |
79 | const Configurable* config = | |
80 | opt_info.AsRawPointer<Configurable>(opt_iter.opt_ptr); | |
81 | if (config != nullptr) { | |
82 | status = config->ValidateOptions(db_opts, cf_opts); | |
83 | } else if (!opt_info.CanBeNull()) { | |
84 | status = | |
85 | Status::NotFound("Missing configurable object", map_iter.first); | |
86 | } | |
87 | if (!status.ok()) { | |
88 | return status; | |
89 | } | |
90 | } | |
91 | } | |
92 | } | |
93 | } | |
94 | #else | |
95 | (void)db_opts; | |
96 | (void)cf_opts; | |
97 | #endif // ROCKSDB_LITE | |
98 | return status; | |
99 | } | |
100 | ||
101 | /*********************************************************************************/ | |
102 | /* */ | |
103 | /* Methods for Retrieving Options from Configurables */ | |
104 | /* */ | |
105 | /*********************************************************************************/ | |
106 | ||
107 | const void* Configurable::GetOptionsPtr(const std::string& name) const { | |
108 | for (auto o : options_) { | |
109 | if (o.name == name) { | |
110 | return o.opt_ptr; | |
111 | } | |
112 | } | |
113 | return nullptr; | |
114 | } | |
115 | ||
116 | std::string Configurable::GetOptionName(const std::string& opt_name) const { | |
117 | return opt_name; | |
118 | } | |
119 | ||
120 | #ifndef ROCKSDB_LITE | |
121 | const OptionTypeInfo* ConfigurableHelper::FindOption( | |
122 | const std::vector<Configurable::RegisteredOptions>& options, | |
123 | const std::string& short_name, std::string* opt_name, void** opt_ptr) { | |
124 | for (auto iter : options) { | |
125 | const auto opt_info = | |
126 | OptionTypeInfo::Find(short_name, *(iter.type_map), opt_name); | |
127 | if (opt_info != nullptr) { | |
128 | *opt_ptr = iter.opt_ptr; | |
129 | return opt_info; | |
130 | } | |
131 | } | |
132 | return nullptr; | |
133 | } | |
134 | #endif // ROCKSDB_LITE | |
135 | ||
136 | //************************************************************************* | |
137 | // | |
138 | // Methods for Configuring Options from Strings/Name-Value Pairs/Maps | |
139 | // | |
140 | //************************************************************************* | |
141 | ||
142 | Status Configurable::ConfigureFromMap( | |
143 | const ConfigOptions& config_options, | |
144 | const std::unordered_map<std::string, std::string>& opts_map) { | |
145 | Status s = ConfigureFromMap(config_options, opts_map, nullptr); | |
146 | return s; | |
147 | } | |
148 | ||
149 | Status Configurable::ConfigureFromMap( | |
150 | const ConfigOptions& config_options, | |
151 | const std::unordered_map<std::string, std::string>& opts_map, | |
152 | std::unordered_map<std::string, std::string>* unused) { | |
153 | return ConfigureOptions(config_options, opts_map, unused); | |
154 | } | |
155 | ||
156 | Status Configurable::ConfigureOptions( | |
157 | const ConfigOptions& config_options, | |
158 | const std::unordered_map<std::string, std::string>& opts_map, | |
159 | std::unordered_map<std::string, std::string>* unused) { | |
160 | std::string curr_opts; | |
161 | #ifndef ROCKSDB_LITE | |
162 | if (!config_options.ignore_unknown_options) { | |
163 | // If we are not ignoring unused, get the defaults in case we need to reset | |
164 | GetOptionString(config_options, &curr_opts).PermitUncheckedError(); | |
165 | } | |
166 | #endif // ROCKSDB_LITE | |
167 | Status s = ConfigurableHelper::ConfigureOptions(config_options, *this, | |
168 | opts_map, unused); | |
169 | if (config_options.invoke_prepare_options && s.ok()) { | |
170 | s = PrepareOptions(config_options); | |
171 | } | |
172 | #ifndef ROCKSDB_LITE | |
173 | if (!s.ok() && !curr_opts.empty()) { | |
174 | ConfigOptions reset = config_options; | |
175 | reset.ignore_unknown_options = true; | |
176 | reset.invoke_prepare_options = true; | |
177 | // There are some options to reset from this current error | |
178 | ConfigureFromString(reset, curr_opts).PermitUncheckedError(); | |
179 | } | |
180 | #endif // ROCKSDB_LITE | |
181 | return s; | |
182 | } | |
183 | ||
184 | Status Configurable::ParseStringOptions(const ConfigOptions& /*config_options*/, | |
185 | const std::string& /*opts_str*/) { | |
186 | return Status::OK(); | |
187 | } | |
188 | ||
189 | Status Configurable::ConfigureFromString(const ConfigOptions& config_options, | |
190 | const std::string& opts_str) { | |
191 | Status s; | |
192 | if (!opts_str.empty()) { | |
193 | #ifndef ROCKSDB_LITE | |
194 | if (opts_str.find(';') != std::string::npos || | |
195 | opts_str.find('=') != std::string::npos) { | |
196 | std::unordered_map<std::string, std::string> opt_map; | |
197 | s = StringToMap(opts_str, &opt_map); | |
198 | if (s.ok()) { | |
199 | s = ConfigureFromMap(config_options, opt_map, nullptr); | |
200 | } | |
201 | } else { | |
202 | #endif // ROCKSDB_LITE | |
203 | s = ParseStringOptions(config_options, opts_str); | |
204 | if (s.ok() && config_options.invoke_prepare_options) { | |
205 | s = PrepareOptions(config_options); | |
206 | } | |
207 | #ifndef ROCKSDB_LITE | |
208 | } | |
209 | #endif // ROCKSDB_LITE | |
210 | } else if (config_options.invoke_prepare_options) { | |
211 | s = PrepareOptions(config_options); | |
212 | } else { | |
213 | s = Status::OK(); | |
214 | } | |
215 | return s; | |
216 | } | |
217 | ||
218 | #ifndef ROCKSDB_LITE | |
219 | /** | |
220 | * Sets the value of the named property to the input value, returning OK on | |
221 | * succcess. | |
222 | */ | |
223 | Status Configurable::ConfigureOption(const ConfigOptions& config_options, | |
224 | const std::string& name, | |
225 | const std::string& value) { | |
226 | const std::string& opt_name = GetOptionName(name); | |
227 | return ConfigurableHelper::ConfigureSingleOption(config_options, *this, | |
228 | opt_name, value); | |
229 | } | |
230 | ||
231 | /** | |
232 | * Looks for the named option amongst the options for this type and sets | |
233 | * the value for it to be the input value. | |
234 | * If the name was found, found_option will be set to true and the resulting | |
235 | * status should be returned. | |
236 | */ | |
237 | ||
238 | Status Configurable::ParseOption(const ConfigOptions& config_options, | |
239 | const OptionTypeInfo& opt_info, | |
240 | const std::string& opt_name, | |
241 | const std::string& opt_value, void* opt_ptr) { | |
242 | if (opt_info.IsMutable() || opt_info.IsConfigurable()) { | |
243 | return opt_info.Parse(config_options, opt_name, opt_value, opt_ptr); | |
244 | } else if (prepared_) { | |
245 | return Status::InvalidArgument("Option not changeable: " + opt_name); | |
246 | } else { | |
247 | return opt_info.Parse(config_options, opt_name, opt_value, opt_ptr); | |
248 | } | |
249 | } | |
250 | ||
251 | #endif // ROCKSDB_LITE | |
252 | ||
253 | Status ConfigurableHelper::ConfigureOptions( | |
254 | const ConfigOptions& config_options, Configurable& configurable, | |
255 | const std::unordered_map<std::string, std::string>& opts_map, | |
256 | std::unordered_map<std::string, std::string>* unused) { | |
257 | std::unordered_map<std::string, std::string> remaining = opts_map; | |
258 | Status s = Status::OK(); | |
259 | if (!opts_map.empty()) { | |
260 | #ifndef ROCKSDB_LITE | |
261 | for (const auto& iter : configurable.options_) { | |
262 | s = ConfigureSomeOptions(config_options, configurable, *(iter.type_map), | |
263 | &remaining, iter.opt_ptr); | |
264 | if (remaining.empty()) { // Are there more options left? | |
265 | break; | |
266 | } else if (!s.ok()) { | |
267 | break; | |
268 | } | |
269 | } | |
270 | #else | |
271 | (void)configurable; | |
272 | if (!config_options.ignore_unknown_options) { | |
273 | s = Status::NotSupported("ConfigureFromMap not supported in LITE mode"); | |
274 | } | |
275 | #endif // ROCKSDB_LITE | |
276 | } | |
277 | if (unused != nullptr && !remaining.empty()) { | |
278 | unused->insert(remaining.begin(), remaining.end()); | |
279 | } | |
280 | if (config_options.ignore_unknown_options) { | |
281 | s = Status::OK(); | |
282 | } else if (s.ok() && unused == nullptr && !remaining.empty()) { | |
283 | s = Status::NotFound("Could not find option: ", remaining.begin()->first); | |
284 | } | |
285 | return s; | |
286 | } | |
287 | ||
288 | #ifndef ROCKSDB_LITE | |
289 | /** | |
290 | * Updates the object with the named-value property values, returning OK on | |
291 | * succcess. Any properties that were found are removed from the options list; | |
292 | * upon return only options that were not found in this opt_map remain. | |
293 | ||
294 | * Returns: | |
295 | * - OK if ignore_unknown_options is set | |
296 | * - InvalidArgument, if any option was invalid | |
297 | * - NotSupported, if any option is unsupported and ignore_unsupported_options | |
298 | is OFF | |
299 | * - OK, if no option was invalid or not supported (or ignored) | |
300 | */ | |
301 | Status ConfigurableHelper::ConfigureSomeOptions( | |
302 | const ConfigOptions& config_options, Configurable& configurable, | |
303 | const std::unordered_map<std::string, OptionTypeInfo>& type_map, | |
304 | std::unordered_map<std::string, std::string>* options, void* opt_ptr) { | |
305 | Status result = Status::OK(); // The last non-OK result (if any) | |
306 | Status notsup = Status::OK(); // The last NotSupported result (if any) | |
307 | std::string elem_name; | |
308 | int found = 1; | |
309 | std::unordered_set<std::string> unsupported; | |
310 | // While there are unused properties and we processed at least one, | |
311 | // go through the remaining unused properties and attempt to configure them. | |
312 | while (found > 0 && !options->empty()) { | |
313 | found = 0; | |
314 | notsup = Status::OK(); | |
315 | for (auto it = options->begin(); it != options->end();) { | |
316 | const std::string& opt_name = configurable.GetOptionName(it->first); | |
317 | const std::string& opt_value = it->second; | |
318 | const auto opt_info = | |
319 | OptionTypeInfo::Find(opt_name, type_map, &elem_name); | |
320 | if (opt_info == nullptr) { // Did not find the option. Skip it | |
321 | ++it; | |
322 | } else { | |
323 | Status s = ConfigureOption(config_options, configurable, *opt_info, | |
324 | opt_name, elem_name, opt_value, opt_ptr); | |
325 | if (s.IsNotFound()) { | |
326 | ++it; | |
327 | } else if (s.IsNotSupported()) { | |
328 | notsup = s; | |
329 | unsupported.insert(it->first); | |
330 | ++it; // Skip it for now | |
331 | } else { | |
332 | found++; | |
333 | it = options->erase(it); | |
334 | if (!s.ok()) { | |
335 | result = s; | |
336 | } | |
337 | } | |
338 | } | |
339 | } // End for all remaining options | |
340 | } // End while found one or options remain | |
341 | ||
342 | // Now that we have been through the list, remove any unsupported | |
343 | for (auto u : unsupported) { | |
344 | auto it = options->find(u); | |
345 | if (it != options->end()) { | |
346 | options->erase(it); | |
347 | } | |
348 | } | |
349 | if (config_options.ignore_unknown_options) { | |
350 | if (!result.ok()) result.PermitUncheckedError(); | |
351 | if (!notsup.ok()) notsup.PermitUncheckedError(); | |
352 | return Status::OK(); | |
353 | } else if (!result.ok()) { | |
354 | if (!notsup.ok()) notsup.PermitUncheckedError(); | |
355 | return result; | |
356 | } else if (config_options.ignore_unsupported_options) { | |
357 | if (!notsup.ok()) notsup.PermitUncheckedError(); | |
358 | return Status::OK(); | |
359 | } else { | |
360 | return notsup; | |
361 | } | |
362 | } | |
363 | ||
364 | Status ConfigurableHelper::ConfigureSingleOption( | |
365 | const ConfigOptions& config_options, Configurable& configurable, | |
366 | const std::string& name, const std::string& value) { | |
367 | std::string opt_name; | |
368 | void* opt_ptr = nullptr; | |
369 | const auto opt_info = | |
370 | FindOption(configurable.options_, name, &opt_name, &opt_ptr); | |
371 | if (opt_info == nullptr) { | |
372 | return Status::NotFound("Could not find option: ", name); | |
373 | } else { | |
374 | return ConfigureOption(config_options, configurable, *opt_info, name, | |
375 | opt_name, value, opt_ptr); | |
376 | } | |
377 | } | |
378 | ||
379 | Status ConfigurableHelper::ConfigureOption( | |
380 | const ConfigOptions& config_options, Configurable& configurable, | |
381 | const OptionTypeInfo& opt_info, const std::string& opt_name, | |
382 | const std::string& name, const std::string& value, void* opt_ptr) { | |
383 | if (opt_name == name) { | |
384 | return configurable.ParseOption(config_options, opt_info, opt_name, value, | |
385 | opt_ptr); | |
386 | } else if (opt_info.IsCustomizable() && | |
387 | EndsWith(opt_name, ConfigurableHelper::kIdPropSuffix)) { | |
388 | return configurable.ParseOption(config_options, opt_info, name, value, | |
389 | opt_ptr); | |
390 | ||
391 | } else if (opt_info.IsCustomizable()) { | |
392 | Customizable* custom = opt_info.AsRawPointer<Customizable>(opt_ptr); | |
393 | if (value.empty()) { | |
394 | return Status::OK(); | |
395 | } else if (custom == nullptr || !StartsWith(name, custom->GetId() + ".")) { | |
396 | return configurable.ParseOption(config_options, opt_info, name, value, | |
397 | opt_ptr); | |
398 | } else if (value.find("=") != std::string::npos) { | |
399 | return custom->ConfigureFromString(config_options, value); | |
400 | } else { | |
401 | return custom->ConfigureOption(config_options, name, value); | |
402 | } | |
403 | } else if (opt_info.IsStruct() || opt_info.IsConfigurable()) { | |
404 | return configurable.ParseOption(config_options, opt_info, name, value, | |
405 | opt_ptr); | |
406 | } else { | |
407 | return Status::NotFound("Could not find option: ", name); | |
408 | } | |
409 | } | |
410 | #endif // ROCKSDB_LITE | |
411 | ||
412 | Status ConfigurableHelper::ConfigureNewObject( | |
413 | const ConfigOptions& config_options_in, Configurable* object, | |
414 | const std::string& id, const std::string& base_opts, | |
415 | const std::unordered_map<std::string, std::string>& opts) { | |
416 | if (object != nullptr) { | |
417 | ConfigOptions config_options = config_options_in; | |
418 | config_options.invoke_prepare_options = false; | |
419 | if (!base_opts.empty()) { | |
420 | #ifndef ROCKSDB_LITE | |
421 | // Don't run prepare options on the base, as we would do that on the | |
422 | // overlay opts instead | |
423 | Status status = object->ConfigureFromString(config_options, base_opts); | |
424 | if (!status.ok()) { | |
425 | return status; | |
426 | } | |
427 | #endif // ROCKSDB_LITE | |
428 | } | |
429 | if (!opts.empty()) { | |
430 | return object->ConfigureFromMap(config_options, opts); | |
431 | } | |
432 | } else if (!opts.empty()) { // No object but no map. This is OK | |
433 | return Status::InvalidArgument("Cannot configure null object ", id); | |
434 | } | |
435 | return Status::OK(); | |
436 | } | |
437 | ||
438 | //******************************************************************************* | |
439 | // | |
440 | // Methods for Converting Options into strings | |
441 | // | |
442 | //******************************************************************************* | |
443 | ||
444 | Status Configurable::GetOptionString(const ConfigOptions& config_options, | |
445 | std::string* result) const { | |
446 | assert(result); | |
447 | result->clear(); | |
448 | #ifndef ROCKSDB_LITE | |
449 | return ConfigurableHelper::SerializeOptions(config_options, *this, "", | |
450 | result); | |
451 | #else | |
452 | (void)config_options; | |
453 | return Status::NotSupported("GetOptionString not supported in LITE mode"); | |
454 | #endif // ROCKSDB_LITE | |
455 | } | |
456 | ||
457 | #ifndef ROCKSDB_LITE | |
458 | std::string Configurable::ToString(const ConfigOptions& config_options, | |
459 | const std::string& prefix) const { | |
460 | std::string result = SerializeOptions(config_options, prefix); | |
461 | if (result.empty() || result.find('=') == std::string::npos) { | |
462 | return result; | |
463 | } else { | |
464 | return "{" + result + "}"; | |
465 | } | |
466 | } | |
467 | ||
468 | std::string Configurable::SerializeOptions(const ConfigOptions& config_options, | |
469 | const std::string& header) const { | |
470 | std::string result; | |
471 | Status s = ConfigurableHelper::SerializeOptions(config_options, *this, header, | |
472 | &result); | |
473 | assert(s.ok()); | |
474 | return result; | |
475 | } | |
476 | ||
477 | Status Configurable::GetOption(const ConfigOptions& config_options, | |
478 | const std::string& name, | |
479 | std::string* value) const { | |
480 | return ConfigurableHelper::GetOption(config_options, *this, | |
481 | GetOptionName(name), value); | |
482 | } | |
483 | ||
484 | Status ConfigurableHelper::GetOption(const ConfigOptions& config_options, | |
485 | const Configurable& configurable, | |
486 | const std::string& short_name, | |
487 | std::string* value) { | |
488 | // Look for option directly | |
489 | assert(value); | |
490 | value->clear(); | |
491 | ||
492 | std::string opt_name; | |
493 | void* opt_ptr = nullptr; | |
494 | const auto opt_info = | |
495 | FindOption(configurable.options_, short_name, &opt_name, &opt_ptr); | |
496 | if (opt_info != nullptr) { | |
497 | ConfigOptions embedded = config_options; | |
498 | embedded.delimiter = ";"; | |
499 | if (short_name == opt_name) { | |
500 | return opt_info->Serialize(embedded, opt_name, opt_ptr, value); | |
501 | } else if (opt_info->IsStruct()) { | |
502 | return opt_info->Serialize(embedded, opt_name, opt_ptr, value); | |
503 | } else if (opt_info->IsConfigurable()) { | |
504 | auto const* config = opt_info->AsRawPointer<Configurable>(opt_ptr); | |
505 | if (config != nullptr) { | |
506 | return config->GetOption(embedded, opt_name, value); | |
507 | } | |
508 | } | |
509 | } | |
510 | return Status::NotFound("Cannot find option: ", short_name); | |
511 | } | |
512 | ||
513 | Status ConfigurableHelper::SerializeOptions(const ConfigOptions& config_options, | |
514 | const Configurable& configurable, | |
515 | const std::string& prefix, | |
516 | std::string* result) { | |
517 | assert(result); | |
518 | for (auto const& opt_iter : configurable.options_) { | |
519 | for (const auto& map_iter : *(opt_iter.type_map)) { | |
520 | const auto& opt_name = map_iter.first; | |
521 | const auto& opt_info = map_iter.second; | |
522 | if (opt_info.ShouldSerialize()) { | |
523 | std::string value; | |
524 | Status s = opt_info.Serialize(config_options, prefix + opt_name, | |
525 | opt_iter.opt_ptr, &value); | |
526 | if (!s.ok()) { | |
527 | return s; | |
528 | } else if (!value.empty()) { | |
529 | // <prefix><opt_name>=<value><delimiter> | |
530 | result->append(prefix + opt_name + "=" + value + | |
531 | config_options.delimiter); | |
532 | } | |
533 | } | |
534 | } | |
535 | } | |
536 | return Status::OK(); | |
537 | } | |
538 | #endif // ROCKSDB_LITE | |
539 | ||
540 | //******************************************************************************** | |
541 | // | |
542 | // Methods for listing the options from Configurables | |
543 | // | |
544 | //******************************************************************************** | |
545 | #ifndef ROCKSDB_LITE | |
546 | Status Configurable::GetOptionNames( | |
547 | const ConfigOptions& config_options, | |
548 | std::unordered_set<std::string>* result) const { | |
549 | assert(result); | |
550 | return ConfigurableHelper::ListOptions(config_options, *this, "", result); | |
551 | } | |
552 | ||
553 | Status ConfigurableHelper::ListOptions( | |
554 | const ConfigOptions& /*config_options*/, const Configurable& configurable, | |
555 | const std::string& prefix, std::unordered_set<std::string>* result) { | |
556 | Status status; | |
557 | for (auto const& opt_iter : configurable.options_) { | |
558 | for (const auto& map_iter : *(opt_iter.type_map)) { | |
559 | const auto& opt_name = map_iter.first; | |
560 | const auto& opt_info = map_iter.second; | |
561 | // If the option is no longer used in rocksdb and marked as deprecated, | |
562 | // we skip it in the serialization. | |
563 | if (!opt_info.IsDeprecated() && !opt_info.IsAlias()) { | |
564 | result->emplace(prefix + opt_name); | |
565 | } | |
566 | } | |
567 | } | |
568 | return status; | |
569 | } | |
570 | #endif // ROCKSDB_LITE | |
571 | ||
572 | //******************************************************************************* | |
573 | // | |
574 | // Methods for Comparing Configurables | |
575 | // | |
576 | //******************************************************************************* | |
577 | ||
578 | bool Configurable::AreEquivalent(const ConfigOptions& config_options, | |
579 | const Configurable* other, | |
580 | std::string* name) const { | |
581 | assert(name); | |
582 | name->clear(); | |
583 | if (this == other || config_options.IsCheckDisabled()) { | |
584 | return true; | |
585 | } else if (other != nullptr) { | |
586 | #ifndef ROCKSDB_LITE | |
587 | return ConfigurableHelper::AreEquivalent(config_options, *this, *other, | |
588 | name); | |
589 | #else | |
590 | return true; | |
591 | #endif // ROCKSDB_LITE | |
592 | } else { | |
593 | return false; | |
594 | } | |
595 | } | |
596 | ||
597 | #ifndef ROCKSDB_LITE | |
598 | bool Configurable::OptionsAreEqual(const ConfigOptions& config_options, | |
599 | const OptionTypeInfo& opt_info, | |
600 | const std::string& opt_name, | |
601 | const void* const this_ptr, | |
602 | const void* const that_ptr, | |
603 | std::string* mismatch) const { | |
604 | if (opt_info.AreEqual(config_options, opt_name, this_ptr, that_ptr, | |
605 | mismatch)) { | |
606 | return true; | |
607 | } else if (opt_info.AreEqualByName(config_options, opt_name, this_ptr, | |
608 | that_ptr)) { | |
609 | *mismatch = ""; | |
610 | return true; | |
611 | } else { | |
612 | return false; | |
613 | } | |
614 | } | |
615 | ||
616 | bool ConfigurableHelper::AreEquivalent(const ConfigOptions& config_options, | |
617 | const Configurable& this_one, | |
618 | const Configurable& that_one, | |
619 | std::string* mismatch) { | |
620 | assert(mismatch != nullptr); | |
621 | for (auto const& o : this_one.options_) { | |
622 | const auto this_offset = this_one.GetOptionsPtr(o.name); | |
623 | const auto that_offset = that_one.GetOptionsPtr(o.name); | |
624 | if (this_offset != that_offset) { | |
625 | if (this_offset == nullptr || that_offset == nullptr) { | |
626 | return false; | |
627 | } else { | |
628 | for (const auto& map_iter : *(o.type_map)) { | |
629 | if (config_options.IsCheckEnabled(map_iter.second.GetSanityLevel()) && | |
630 | !this_one.OptionsAreEqual(config_options, map_iter.second, | |
631 | map_iter.first, this_offset, | |
632 | that_offset, mismatch)) { | |
633 | return false; | |
634 | } | |
635 | } | |
636 | } | |
637 | } | |
638 | } | |
639 | return true; | |
640 | } | |
641 | #endif // ROCKSDB_LITE | |
642 | ||
643 | Status ConfigurableHelper::GetOptionsMap( | |
644 | const std::string& value, std::string* id, | |
645 | std::unordered_map<std::string, std::string>* props) { | |
646 | return GetOptionsMap(value, "", id, props); | |
647 | } | |
648 | ||
649 | Status ConfigurableHelper::GetOptionsMap( | |
650 | const std::string& value, const std::string& default_id, std::string* id, | |
651 | std::unordered_map<std::string, std::string>* props) { | |
652 | assert(id); | |
653 | assert(props); | |
654 | Status status; | |
655 | if (value.empty() || value == kNullptrString) { | |
656 | *id = default_id; | |
657 | } else if (value.find('=') == std::string::npos) { | |
658 | *id = value; | |
659 | #ifndef ROCKSDB_LITE | |
660 | } else { | |
661 | status = StringToMap(value, props); | |
662 | if (status.ok()) { | |
663 | auto iter = props->find(ConfigurableHelper::kIdPropName); | |
664 | if (iter != props->end()) { | |
665 | *id = iter->second; | |
666 | props->erase(iter); | |
667 | } else if (default_id.empty()) { // Should this be an error?? | |
668 | status = Status::InvalidArgument("Name property is missing"); | |
669 | } else { | |
670 | *id = default_id; | |
671 | } | |
672 | } | |
673 | #else | |
674 | } else { | |
675 | *id = value; | |
676 | props->clear(); | |
677 | #endif | |
678 | } | |
679 | return status; | |
680 | } | |
681 | } // namespace ROCKSDB_NAMESPACE |