]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/include/rocksdb/utilities/options_type.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / include / rocksdb / utilities / options_type.h
CommitLineData
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).
1e59de90
TL
5//
6// The OptionTypeInfo and related classes provide a framework for
7// configuring and validating RocksDB classes via the Options framework.
8// This file is part of the public API to allow developers who wish to
9// write their own extensions and plugins to take use the Options
10// framework in their custom implementations.
11//
12// See https://github.com/facebook/rocksdb/wiki/RocksDB-Configurable-Objects
13// for more information on how to develop and use custom extensions
20effc67
TL
14
15#pragma once
16
17#include <functional>
18#include <memory>
19#include <unordered_map>
20
21#include "rocksdb/convenience.h"
22#include "rocksdb/rocksdb_namespace.h"
23#include "rocksdb/status.h"
24
25namespace ROCKSDB_NAMESPACE {
26class OptionTypeInfo;
1e59de90
TL
27struct ColumnFamilyOptions;
28struct DBOptions;
20effc67
TL
29
30// The underlying "class/type" of the option.
31// This enum is used to determine how the option should
32// be converted to/from strings and compared.
33enum class OptionType {
34 kBoolean,
35 kInt,
36 kInt32T,
37 kInt64T,
38 kUInt,
1e59de90 39 kUInt8T,
20effc67
TL
40 kUInt32T,
41 kUInt64T,
42 kSizeT,
43 kString,
44 kDouble,
45 kCompactionStyle,
46 kCompactionPri,
20effc67 47 kCompressionType,
20effc67 48 kCompactionStopStyle,
20effc67
TL
49 kChecksumType,
50 kEncodingType,
51 kEnv,
52 kEnum,
53 kStruct,
54 kVector,
55 kConfigurable,
56 kCustomizable,
1e59de90
TL
57 kEncodedString,
58 kTemperature,
59 kArray,
20effc67
TL
60 kUnknown,
61};
62
63enum class OptionVerificationType {
64 kNormal,
65 kByName, // The option is pointer typed so we can only verify
66 // based on it's name.
67 kByNameAllowNull, // Same as kByName, but it also allows the case
68 // where one of them is a nullptr.
69 kByNameAllowFromNull, // Same as kByName, but it also allows the case
70 // where the old option is nullptr.
71 kDeprecated, // The option is no longer used in rocksdb. The RocksDB
72 // OptionsParser will still accept this option if it
73 // happen to exists in some Options file. However,
74 // the parser will not include it in serialization
75 // and verification processes.
76 kAlias, // This option represents is a name/shortcut for
77 // another option and should not be written or verified
78 // independently
79};
80
81// A set of modifier flags used to alter how an option is evaluated or
82// processed. These flags can be combined together (e.g. kMutable | kShared).
83// The kCompare flags can be used to control if/when options are compared.
84// If kCompareNever is set, two related options would never be compared (always
85// equal) If kCompareExact is set, the options will only be compared if the
86// sanity mode
87// is exact
88// kMutable means the option can be changed after it is prepared
89// kShared means the option is contained in a std::shared_ptr
90// kUnique means the option is contained in a std::uniqued_ptr
91// kRawPointer means the option is a raw pointer value.
92// kAllowNull means that an option is allowed to be null for verification
93// purposes.
94// kDontSerialize means this option should not be serialized and included in
95// the string representation.
96// kDontPrepare means do not call PrepareOptions for this pointer value.
97enum class OptionTypeFlags : uint32_t {
98 kNone = 0x00, // No flags
99 kCompareDefault = 0x0,
100 kCompareNever = ConfigOptions::kSanityLevelNone,
101 kCompareLoose = ConfigOptions::kSanityLevelLooselyCompatible,
102 kCompareExact = ConfigOptions::kSanityLevelExactMatch,
103
104 kMutable = 0x0100, // Option is mutable
105 kRawPointer = 0x0200, // The option is stored as a raw pointer
106 kShared = 0x0400, // The option is stored as a shared_ptr
107 kUnique = 0x0800, // The option is stored as a unique_ptr
108 kAllowNull = 0x1000, // The option can be null
109 kDontSerialize = 0x2000, // Don't serialize the option
110 kDontPrepare = 0x4000, // Don't prepare or sanitize this option
111 kStringNameOnly = 0x8000, // The option serializes to a name only
112};
113
1e59de90
TL
114inline OptionTypeFlags operator|(const OptionTypeFlags& a,
115 const OptionTypeFlags& b) {
20effc67
TL
116 return static_cast<OptionTypeFlags>(static_cast<uint32_t>(a) |
117 static_cast<uint32_t>(b));
118}
119
1e59de90
TL
120inline OptionTypeFlags operator&(const OptionTypeFlags& a,
121 const OptionTypeFlags& b) {
20effc67
TL
122 return static_cast<OptionTypeFlags>(static_cast<uint32_t>(a) &
123 static_cast<uint32_t>(b));
124}
125
126// Converts an string into its enumerated value.
127// @param type_map Mapping between strings and enum values
128// @param type The string representation of the enum
129// @param value Returns the enum value represented by the string
130// @return true if the string was found in the enum map, false otherwise.
131template <typename T>
132bool ParseEnum(const std::unordered_map<std::string, T>& type_map,
133 const std::string& type, T* value) {
134 auto iter = type_map.find(type);
135 if (iter != type_map.end()) {
136 *value = iter->second;
137 return true;
138 }
139 return false;
140}
141
142// Converts an enum into its string representation.
143// @param type_map Mapping between strings and enum values
144// @param type The enum
145// @param value Returned as the string representation of the enum
146// @return true if the enum was found in the enum map, false otherwise.
147template <typename T>
148bool SerializeEnum(const std::unordered_map<std::string, T>& type_map,
149 const T& type, std::string* value) {
150 for (const auto& pair : type_map) {
151 if (pair.second == type) {
152 *value = pair.first;
153 return true;
154 }
155 }
156 return false;
157}
158
1e59de90
TL
159template <typename T, size_t kSize>
160Status ParseArray(const ConfigOptions& config_options,
161 const OptionTypeInfo& elem_info, char separator,
162 const std::string& name, const std::string& value,
163 std::array<T, kSize>* result);
164
165template <typename T, size_t kSize>
166Status SerializeArray(const ConfigOptions& config_options,
167 const OptionTypeInfo& elem_info, char separator,
168 const std::string& name, const std::array<T, kSize>& vec,
169 std::string* value);
170
171template <typename T, size_t kSize>
172bool ArraysAreEqual(const ConfigOptions& config_options,
173 const OptionTypeInfo& elem_info, const std::string& name,
174 const std::array<T, kSize>& array1,
175 const std::array<T, kSize>& array2, std::string* mismatch);
176
20effc67
TL
177template <typename T>
178Status ParseVector(const ConfigOptions& config_options,
179 const OptionTypeInfo& elem_info, char separator,
180 const std::string& name, const std::string& value,
181 std::vector<T>* result);
182
183template <typename T>
184Status SerializeVector(const ConfigOptions& config_options,
185 const OptionTypeInfo& elem_info, char separator,
186 const std::string& name, const std::vector<T>& vec,
187 std::string* value);
188template <typename T>
189bool VectorsAreEqual(const ConfigOptions& config_options,
190 const OptionTypeInfo& elem_info, const std::string& name,
191 const std::vector<T>& vec1, const std::vector<T>& vec2,
192 std::string* mismatch);
193
194// Function for converting a option string value into its underlying
195// representation in "addr"
196// On success, Status::OK is returned and addr is set to the parsed form
197// On failure, a non-OK status is returned
198// @param opts The ConfigOptions controlling how the value is parsed
199// @param name The name of the options being parsed
200// @param value The string representation of the option
201// @param addr Pointer to the object
202using ParseFunc = std::function<Status(
203 const ConfigOptions& /*opts*/, const std::string& /*name*/,
1e59de90 204 const std::string& /*value*/, void* /*addr*/)>;
20effc67
TL
205
206// Function for converting an option "addr" into its string representation.
207// On success, Status::OK is returned and value is the serialized form.
208// On failure, a non-OK status is returned
209// @param opts The ConfigOptions controlling how the values are serialized
210// @param name The name of the options being serialized
211// @param addr Pointer to the value being serialized
212// @param value The result of the serialization.
213using SerializeFunc = std::function<Status(
214 const ConfigOptions& /*opts*/, const std::string& /*name*/,
1e59de90 215 const void* /*addr*/, std::string* /*value*/)>;
20effc67
TL
216
217// Function for comparing two option values
218// If they are not equal, updates "mismatch" with the name of the bad option
219// @param opts The ConfigOptions controlling how the values are compared
220// @param name The name of the options being compared
221// @param addr1 The first address to compare
222// @param addr2 The address to compare to
223// @param mismatch If the values are not equal, the name of the option that
224// first differs
225using EqualsFunc = std::function<bool(
226 const ConfigOptions& /*opts*/, const std::string& /*name*/,
1e59de90
TL
227 const void* /*addr1*/, const void* /*addr2*/, std::string* mismatch)>;
228
229// Function for preparing/initializing an option.
230using PrepareFunc =
231 std::function<Status(const ConfigOptions& /*opts*/,
232 const std::string& /*name*/, void* /*addr*/)>;
233
234// Function for validating an option.
235using ValidateFunc = std::function<Status(
236 const DBOptions& /*db_opts*/, const ColumnFamilyOptions& /*cf_opts*/,
237 const std::string& /*name*/, const void* /*addr*/)>;
20effc67
TL
238
239// A struct for storing constant option information such as option name,
240// option type, and offset.
241class OptionTypeInfo {
242 public:
243 // A simple "normal", non-mutable Type "type" at offset
244 OptionTypeInfo(int offset, OptionType type)
245 : offset_(offset),
246 parse_func_(nullptr),
247 serialize_func_(nullptr),
248 equals_func_(nullptr),
249 type_(type),
250 verification_(OptionVerificationType::kNormal),
251 flags_(OptionTypeFlags::kNone) {}
252
253 OptionTypeInfo(int offset, OptionType type,
254 OptionVerificationType verification, OptionTypeFlags flags)
255 : offset_(offset),
256 parse_func_(nullptr),
257 serialize_func_(nullptr),
258 equals_func_(nullptr),
259 type_(type),
260 verification_(verification),
261 flags_(flags) {}
262
263 OptionTypeInfo(int offset, OptionType type,
264 OptionVerificationType verification, OptionTypeFlags flags,
265 const ParseFunc& parse_func)
266 : offset_(offset),
267 parse_func_(parse_func),
268 serialize_func_(nullptr),
269 equals_func_(nullptr),
270 type_(type),
271 verification_(verification),
272 flags_(flags) {}
273
274 OptionTypeInfo(int offset, OptionType type,
275 OptionVerificationType verification, OptionTypeFlags flags,
276 const ParseFunc& parse_func,
277 const SerializeFunc& serialize_func,
278 const EqualsFunc& equals_func)
279 : offset_(offset),
280 parse_func_(parse_func),
281 serialize_func_(serialize_func),
282 equals_func_(equals_func),
283 type_(type),
284 verification_(verification),
285 flags_(flags) {}
286
287 // Creates an OptionTypeInfo for an enum type. Enums use an additional
288 // map to convert the enums to/from their string representation.
289 // To create an OptionTypeInfo that is an Enum, one should:
290 // - Create a static map of string values to the corresponding enum value
291 // - Call this method passing the static map in as a parameter.
292 // Note that it is not necessary to add a new OptionType or make any
1e59de90 293 // other changes -- the returned object handles parsing, serialization, and
20effc67
TL
294 // comparisons.
295 //
296 // @param offset The offset in the option object for this enum
297 // @param map The string to enum mapping for this enum
298 template <typename T>
299 static OptionTypeInfo Enum(
1e59de90
TL
300 int offset, const std::unordered_map<std::string, T>* const map,
301 OptionTypeFlags flags = OptionTypeFlags::kNone) {
302 OptionTypeInfo info(offset, OptionType::kEnum,
303 OptionVerificationType::kNormal, flags);
304 info.SetParseFunc(
20effc67
TL
305 // Uses the map argument to convert the input string into
306 // its corresponding enum value. If value is found in the map,
307 // addr is updated to the corresponding map entry.
308 // @return OK if the value is found in the map
309 // @return InvalidArgument if the value is not found in the map
310 [map](const ConfigOptions&, const std::string& name,
1e59de90 311 const std::string& value, void* addr) {
20effc67
TL
312 if (map == nullptr) {
313 return Status::NotSupported("No enum mapping ", name);
1e59de90 314 } else if (ParseEnum<T>(*map, value, static_cast<T*>(addr))) {
20effc67
TL
315 return Status::OK();
316 } else {
317 return Status::InvalidArgument("No mapping for enum ", name);
318 }
1e59de90
TL
319 });
320 info.SetSerializeFunc(
20effc67
TL
321 // Uses the map argument to convert the input enum into
322 // its corresponding string value. If enum value is found in the map,
323 // value is updated to the corresponding string value in the map.
324 // @return OK if the enum is found in the map
325 // @return InvalidArgument if the enum is not found in the map
1e59de90 326 [map](const ConfigOptions&, const std::string& name, const void* addr,
20effc67
TL
327 std::string* value) {
328 if (map == nullptr) {
329 return Status::NotSupported("No enum mapping ", name);
1e59de90 330 } else if (SerializeEnum<T>(*map, (*static_cast<const T*>(addr)),
20effc67
TL
331 value)) {
332 return Status::OK();
333 } else {
334 return Status::InvalidArgument("No mapping for enum ", name);
335 }
1e59de90
TL
336 });
337 info.SetEqualsFunc(
20effc67
TL
338 // Casts addr1 and addr2 to the enum type and returns true if
339 // they are equal, false otherwise.
1e59de90
TL
340 [](const ConfigOptions&, const std::string&, const void* addr1,
341 const void* addr2, std::string*) {
342 return (*static_cast<const T*>(addr1) ==
343 *static_cast<const T*>(addr2));
20effc67 344 });
1e59de90 345 return info;
20effc67
TL
346 } // End OptionTypeInfo::Enum
347
348 // Creates an OptionTypeInfo for a Struct type. Structs have a
349 // map of string-OptionTypeInfo associated with them that describes how
350 // to process the object for parsing, serializing, and matching.
351 // Structs also have a struct_name, which is the name of the object
352 // as registered in the parent map.
353 // When processing a struct, the option name can be specified as:
354 // - <struct_name> Meaning to process the entire struct.
355 // - <struct_name.field> Meaning to process the single field
356 // - <field> Process the single fields
357 // The CompactionOptionsFIFO, CompactionOptionsUniversal, and LRUCacheOptions
358 // are all examples of Struct options.
359 //
360 // To create an OptionTypeInfo that is a Struct, one should:
361 // - Create a static map of string-OptionTypeInfo corresponding to the
362 // properties of the object that can be set via the options.
363 // - Call this method passing the name and map in as parameters.
364 // Note that it is not necessary to add a new OptionType or make any
365 // other changes -- the returned object handles parsing, serialization, and
366 // comparisons.
367 //
368 // @param offset The offset in the option object for this enum
369 // @param map The string to enum mapping for this enum
370 static OptionTypeInfo Struct(
371 const std::string& struct_name,
372 const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
373 int offset, OptionVerificationType verification, OptionTypeFlags flags) {
1e59de90
TL
374 OptionTypeInfo info(offset, OptionType::kStruct, verification, flags);
375 info.SetParseFunc(
20effc67
TL
376 // Parses the struct and updates the fields at addr
377 [struct_name, struct_map](const ConfigOptions& opts,
378 const std::string& name,
1e59de90 379 const std::string& value, void* addr) {
20effc67 380 return ParseStruct(opts, struct_name, struct_map, name, value, addr);
1e59de90
TL
381 });
382 info.SetSerializeFunc(
20effc67
TL
383 // Serializes the struct options into value
384 [struct_name, struct_map](const ConfigOptions& opts,
1e59de90 385 const std::string& name, const void* addr,
20effc67
TL
386 std::string* value) {
387 return SerializeStruct(opts, struct_name, struct_map, name, addr,
388 value);
1e59de90
TL
389 });
390 info.SetEqualsFunc(
20effc67
TL
391 // Compares the struct fields of addr1 and addr2 for equality
392 [struct_name, struct_map](const ConfigOptions& opts,
1e59de90
TL
393 const std::string& name, const void* addr1,
394 const void* addr2, std::string* mismatch) {
20effc67
TL
395 return StructsAreEqual(opts, struct_name, struct_map, name, addr1,
396 addr2, mismatch);
397 });
1e59de90 398 return info;
20effc67
TL
399 }
400 static OptionTypeInfo Struct(
401 const std::string& struct_name,
402 const std::unordered_map<std::string, OptionTypeInfo>* struct_map,
403 int offset, OptionVerificationType verification, OptionTypeFlags flags,
404 const ParseFunc& parse_func) {
1e59de90
TL
405 OptionTypeInfo info(
406 Struct(struct_name, struct_map, offset, verification, flags));
407 return info.SetParseFunc(parse_func);
408 }
409
410 template <typename T, size_t kSize>
411 static OptionTypeInfo Array(int _offset, OptionVerificationType _verification,
412 OptionTypeFlags _flags,
413 const OptionTypeInfo& elem_info,
414 char separator = ':') {
415 OptionTypeInfo info(_offset, OptionType::kArray, _verification, _flags);
416 info.SetParseFunc([elem_info, separator](
417 const ConfigOptions& opts, const std::string& name,
418 const std::string& value, void* addr) {
419 auto result = static_cast<std::array<T, kSize>*>(addr);
420 return ParseArray<T, kSize>(opts, elem_info, separator, name, value,
421 result);
422 });
423 info.SetSerializeFunc([elem_info, separator](const ConfigOptions& opts,
424 const std::string& name,
425 const void* addr,
426 std::string* value) {
427 const auto& array = *(static_cast<const std::array<T, kSize>*>(addr));
428 return SerializeArray<T, kSize>(opts, elem_info, separator, name, array,
429 value);
430 });
431 info.SetEqualsFunc([elem_info](const ConfigOptions& opts,
432 const std::string& name, const void* addr1,
433 const void* addr2, std::string* mismatch) {
434 const auto& array1 = *(static_cast<const std::array<T, kSize>*>(addr1));
435 const auto& array2 = *(static_cast<const std::array<T, kSize>*>(addr2));
436 return ArraysAreEqual<T, kSize>(opts, elem_info, name, array1, array2,
437 mismatch);
438 });
439 return info;
20effc67
TL
440 }
441
442 template <typename T>
443 static OptionTypeInfo Vector(int _offset,
444 OptionVerificationType _verification,
445 OptionTypeFlags _flags,
446 const OptionTypeInfo& elem_info,
447 char separator = ':') {
1e59de90
TL
448 OptionTypeInfo info(_offset, OptionType::kVector, _verification, _flags);
449 info.SetParseFunc([elem_info, separator](
450 const ConfigOptions& opts, const std::string& name,
451 const std::string& value, void* addr) {
452 auto result = static_cast<std::vector<T>*>(addr);
453 return ParseVector<T>(opts, elem_info, separator, name, value, result);
454 });
455 info.SetSerializeFunc([elem_info, separator](const ConfigOptions& opts,
456 const std::string& name,
457 const void* addr,
458 std::string* value) {
459 const auto& vec = *(static_cast<const std::vector<T>*>(addr));
460 return SerializeVector<T>(opts, elem_info, separator, name, vec, value);
461 });
462 info.SetEqualsFunc([elem_info](const ConfigOptions& opts,
463 const std::string& name, const void* addr1,
464 const void* addr2, std::string* mismatch) {
465 const auto& vec1 = *(static_cast<const std::vector<T>*>(addr1));
466 const auto& vec2 = *(static_cast<const std::vector<T>*>(addr2));
467 return VectorsAreEqual<T>(opts, elem_info, name, vec1, vec2, mismatch);
468 });
469 return info;
20effc67
TL
470 }
471
472 // Create a new std::shared_ptr<Customizable> OptionTypeInfo
473 // This function will call the T::CreateFromString method to create a new
474 // std::shared_ptr<T> object.
475 //
476 // @param offset The offset for the Customizable from the base pointer
477 // @param ovt How to verify this option
478 // @param flags, Extra flags specifying the behavior of this option
479 // @param _sfunc Optional function for serializing this option
480 // @param _efunc Optional function for comparing this option
481 template <typename T>
482 static OptionTypeInfo AsCustomSharedPtr(int offset,
483 OptionVerificationType ovt,
484 OptionTypeFlags flags) {
1e59de90
TL
485 OptionTypeInfo info(offset, OptionType::kCustomizable, ovt,
486 flags | OptionTypeFlags::kShared);
487 return info.SetParseFunc([](const ConfigOptions& opts,
488 const std::string& name,
489 const std::string& value, void* addr) {
490 auto* shared = static_cast<std::shared_ptr<T>*>(addr);
491 if (name == kIdPropName() && value.empty()) {
492 shared->reset();
493 return Status::OK();
494 } else {
495 return T::CreateFromString(opts, value, shared);
496 }
497 });
20effc67
TL
498 }
499
500 template <typename T>
501 static OptionTypeInfo AsCustomSharedPtr(int offset,
502 OptionVerificationType ovt,
503 OptionTypeFlags flags,
504 const SerializeFunc& serialize_func,
505 const EqualsFunc& equals_func) {
1e59de90
TL
506 OptionTypeInfo info(AsCustomSharedPtr<T>(offset, ovt, flags));
507 info.SetSerializeFunc(serialize_func);
508 info.SetEqualsFunc(equals_func);
509 return info;
20effc67
TL
510 }
511
512 // Create a new std::unique_ptr<Customizable> OptionTypeInfo
513 // This function will call the T::CreateFromString method to create a new
514 // std::unique_ptr<T> object.
515 //
516 // @param offset The offset for the Customizable from the base pointer
517 // @param ovt How to verify this option
518 // @param flags, Extra flags specifying the behavior of this option
519 // @param _sfunc Optional function for serializing this option
520 // @param _efunc Optional function for comparing this option
521 template <typename T>
522 static OptionTypeInfo AsCustomUniquePtr(int offset,
523 OptionVerificationType ovt,
524 OptionTypeFlags flags) {
1e59de90
TL
525 OptionTypeInfo info(offset, OptionType::kCustomizable, ovt,
526 flags | OptionTypeFlags::kUnique);
527 return info.SetParseFunc([](const ConfigOptions& opts,
528 const std::string& name,
529 const std::string& value, void* addr) {
530 auto* unique = static_cast<std::unique_ptr<T>*>(addr);
531 if (name == kIdPropName() && value.empty()) {
532 unique->reset();
533 return Status::OK();
534 } else {
535 return T::CreateFromString(opts, value, unique);
536 }
537 });
20effc67
TL
538 }
539
540 template <typename T>
541 static OptionTypeInfo AsCustomUniquePtr(int offset,
542 OptionVerificationType ovt,
543 OptionTypeFlags flags,
544 const SerializeFunc& serialize_func,
545 const EqualsFunc& equals_func) {
1e59de90
TL
546 OptionTypeInfo info(AsCustomUniquePtr<T>(offset, ovt, flags));
547 info.SetSerializeFunc(serialize_func);
548 info.SetEqualsFunc(equals_func);
549 return info;
20effc67
TL
550 }
551
552 // Create a new Customizable* OptionTypeInfo
553 // This function will call the T::CreateFromString method to create a new
554 // T object.
555 //
556 // @param _offset The offset for the Customizable from the base pointer
557 // @param ovt How to verify this option
558 // @param flags, Extra flags specifying the behavior of this option
559 // @param _sfunc Optional function for serializing this option
560 // @param _efunc Optional function for comparing this option
561 template <typename T>
562 static OptionTypeInfo AsCustomRawPtr(int offset, OptionVerificationType ovt,
563 OptionTypeFlags flags) {
1e59de90
TL
564 OptionTypeInfo info(offset, OptionType::kCustomizable, ovt,
565 flags | OptionTypeFlags::kRawPointer);
566 return info.SetParseFunc([](const ConfigOptions& opts,
567 const std::string& name,
568 const std::string& value, void* addr) {
569 auto** pointer = static_cast<T**>(addr);
570 if (name == kIdPropName() && value.empty()) {
571 *pointer = nullptr;
572 return Status::OK();
573 } else {
574 return T::CreateFromString(opts, value, pointer);
575 }
576 });
20effc67
TL
577 }
578
579 template <typename T>
580 static OptionTypeInfo AsCustomRawPtr(int offset, OptionVerificationType ovt,
581 OptionTypeFlags flags,
582 const SerializeFunc& serialize_func,
583 const EqualsFunc& equals_func) {
1e59de90
TL
584 OptionTypeInfo info(AsCustomRawPtr<T>(offset, ovt, flags));
585 info.SetSerializeFunc(serialize_func);
586 info.SetEqualsFunc(equals_func);
587 return info;
588 }
589
590 OptionTypeInfo& SetParseFunc(const ParseFunc& f) {
591 parse_func_ = f;
592 return *this;
593 }
594
595 OptionTypeInfo& SetSerializeFunc(const SerializeFunc& f) {
596 serialize_func_ = f;
597 return *this;
598 }
599 OptionTypeInfo& SetEqualsFunc(const EqualsFunc& f) {
600 equals_func_ = f;
601 return *this;
602 }
603
604 OptionTypeInfo& SetPrepareFunc(const PrepareFunc& f) {
605 prepare_func_ = f;
606 return *this;
607 }
608
609 OptionTypeInfo& SetValidateFunc(const ValidateFunc& f) {
610 validate_func_ = f;
611 return *this;
20effc67
TL
612 }
613
614 bool IsEnabled(OptionTypeFlags otf) const { return (flags_ & otf) == otf; }
615
1e59de90
TL
616 bool IsEditable(const ConfigOptions& opts) const {
617 if (opts.mutable_options_only) {
618 return IsMutable();
619 } else {
620 return true;
621 }
622 }
20effc67
TL
623 bool IsMutable() const { return IsEnabled(OptionTypeFlags::kMutable); }
624
625 bool IsDeprecated() const {
626 return IsEnabled(OptionVerificationType::kDeprecated);
627 }
628
629 // Returns true if the option is marked as an Alias.
630 // Aliases are valid options that are parsed but are not converted to strings
631 // or compared.
632 bool IsAlias() const { return IsEnabled(OptionVerificationType::kAlias); }
633
634 bool IsEnabled(OptionVerificationType ovf) const {
635 return verification_ == ovf;
636 }
637
638 // Returns the sanity level for comparing the option.
639 // If the options should not be compared, returns None
640 // If the option has a compare flag, returns it.
641 // Otherwise, returns "exact"
642 ConfigOptions::SanityLevel GetSanityLevel() const {
643 if (IsDeprecated() || IsAlias()) {
644 return ConfigOptions::SanityLevel::kSanityLevelNone;
645 } else {
646 auto match = (flags_ & OptionTypeFlags::kCompareExact);
647 if (match == OptionTypeFlags::kCompareDefault) {
648 return ConfigOptions::SanityLevel::kSanityLevelExactMatch;
649 } else {
650 return (ConfigOptions::SanityLevel)match;
651 }
652 }
653 }
654
655 // Returns true if the option should be serialized.
656 // Options should be serialized if the are not deprecated, aliases,
657 // or marked as "Don't Serialize".
658 bool ShouldSerialize() const {
659 if (IsDeprecated() || IsAlias()) {
660 return false;
661 } else if (IsEnabled(OptionTypeFlags::kDontSerialize)) {
662 return false;
663 } else {
664 return true;
665 }
666 }
667
1e59de90
TL
668 bool ShouldPrepare() const {
669 if (IsDeprecated() || IsAlias()) {
670 return false;
671 } else if (IsEnabled(OptionTypeFlags::kDontPrepare)) {
672 return false;
673 } else {
674 return (prepare_func_ != nullptr || IsConfigurable());
675 }
676 }
677
678 bool ShouldValidate() const {
679 if (IsDeprecated() || IsAlias()) {
680 return false;
681 } else {
682 return (validate_func_ != nullptr || IsConfigurable());
683 }
684 }
685
20effc67
TL
686 // Returns true if the option is allowed to be null.
687 // Options can be null if the verification type is allow from null
688 // or if the flags specify allow null.
689 bool CanBeNull() const {
690 return (IsEnabled(OptionTypeFlags::kAllowNull) ||
1e59de90 691 IsEnabled(OptionVerificationType::kByNameAllowNull) ||
20effc67
TL
692 IsEnabled(OptionVerificationType::kByNameAllowFromNull));
693 }
694
695 bool IsSharedPtr() const { return IsEnabled(OptionTypeFlags::kShared); }
696
697 bool IsUniquePtr() const { return IsEnabled(OptionTypeFlags::kUnique); }
698
699 bool IsRawPtr() const { return IsEnabled(OptionTypeFlags::kRawPointer); }
700
701 bool IsByName() const {
702 return (verification_ == OptionVerificationType::kByName ||
703 verification_ == OptionVerificationType::kByNameAllowNull ||
704 verification_ == OptionVerificationType::kByNameAllowFromNull);
705 }
706
707 bool IsStruct() const { return (type_ == OptionType::kStruct); }
708
709 bool IsConfigurable() const {
710 return (type_ == OptionType::kConfigurable ||
711 type_ == OptionType::kCustomizable);
712 }
713
714 bool IsCustomizable() const { return (type_ == OptionType::kCustomizable); }
715
1e59de90
TL
716 inline const void* GetOffset(const void* base) const {
717 return static_cast<const char*>(base) + offset_;
718 }
719
720 inline void* GetOffset(void* base) const {
721 return static_cast<char*>(base) + offset_;
722 }
723
724 template <typename T>
725 const T* GetOffsetAs(const void* base) const {
726 const void* addr = GetOffset(base);
727 return static_cast<const T*>(addr);
728 }
729
730 template <typename T>
731 T* GetOffsetAs(void* base) const {
732 void* addr = GetOffset(base);
733 return static_cast<T*>(addr);
734 }
735
20effc67
TL
736 // Returns the underlying pointer for the type at base_addr
737 // The value returned is the underlying "raw" pointer, offset from base.
738 template <typename T>
739 const T* AsRawPointer(const void* const base_addr) const {
740 if (base_addr == nullptr) {
741 return nullptr;
742 }
20effc67 743 if (IsUniquePtr()) {
1e59de90 744 const auto ptr = GetOffsetAs<std::unique_ptr<T>>(base_addr);
20effc67
TL
745 return ptr->get();
746 } else if (IsSharedPtr()) {
1e59de90 747 const auto ptr = GetOffsetAs<std::shared_ptr<T>>(base_addr);
20effc67
TL
748 return ptr->get();
749 } else if (IsRawPtr()) {
1e59de90 750 const T* const* ptr = GetOffsetAs<T* const>(base_addr);
20effc67
TL
751 return *ptr;
752 } else {
1e59de90 753 return GetOffsetAs<T>(base_addr);
20effc67
TL
754 }
755 }
756
757 // Returns the underlying pointer for the type at base_addr
758 // The value returned is the underlying "raw" pointer, offset from base.
759 template <typename T>
760 T* AsRawPointer(void* base_addr) const {
761 if (base_addr == nullptr) {
762 return nullptr;
763 }
20effc67 764 if (IsUniquePtr()) {
1e59de90 765 auto ptr = GetOffsetAs<std::unique_ptr<T>>(base_addr);
20effc67
TL
766 return ptr->get();
767 } else if (IsSharedPtr()) {
1e59de90 768 auto ptr = GetOffsetAs<std::shared_ptr<T>>(base_addr);
20effc67
TL
769 return ptr->get();
770 } else if (IsRawPtr()) {
1e59de90 771 auto ptr = GetOffsetAs<T*>(base_addr);
20effc67
TL
772 return *ptr;
773 } else {
1e59de90 774 return GetOffsetAs<T>(base_addr);
20effc67
TL
775 }
776 }
777
778 // Parses the option in "opt_value" according to the rules of this class
779 // and updates the value at "opt_ptr".
780 // On success, Status::OK() is returned. On failure:
781 // NotFound means the opt_name is not valid for this option
782 // NotSupported means we do not know how to parse the value for this option
783 // InvalidArgument means the opt_value is not valid for this option.
784 Status Parse(const ConfigOptions& config_options, const std::string& opt_name,
785 const std::string& opt_value, void* const opt_ptr) const;
786
787 // Serializes the option in "opt_addr" according to the rules of this class
788 // into the value at "opt_value".
789 Status Serialize(const ConfigOptions& config_options,
790 const std::string& opt_name, const void* const opt_ptr,
791 std::string* opt_value) const;
792
793 // Compares the "addr1" and "addr2" values according to the rules of this
794 // class and returns true if they match. On a failed match, mismatch is the
795 // name of the option that failed to match.
796 bool AreEqual(const ConfigOptions& config_options,
797 const std::string& opt_name, const void* const addr1,
798 const void* const addr2, std::string* mismatch) const;
799
800 // Used to override the match rules for "ByName" options.
801 bool AreEqualByName(const ConfigOptions& config_options,
802 const std::string& opt_name, const void* const this_ptr,
803 const void* const that_ptr) const;
804 bool AreEqualByName(const ConfigOptions& config_options,
805 const std::string& opt_name, const void* const this_ptr,
806 const std::string& that_value) const;
807
1e59de90
TL
808 Status Prepare(const ConfigOptions& config_options, const std::string& name,
809 void* opt_ptr) const;
810 Status Validate(const DBOptions& db_opts, const ColumnFamilyOptions& cf_opts,
811 const std::string& name, const void* opt_ptr) const;
812
813 // Parses the input opts_map according to the type_map for the opt_addr
814 // For each name-value pair in opts_map, find the corresponding name in
815 // type_map If the name is found:
816 // - set the corresponding value in opt_addr, returning the status on
817 // failure;
818 // If the name is not found:
819 // - If unused is specified, add the name-value to unused and continue
820 // - If ingore_unknown_options is false, return NotFound
821 // Returns OK if all options were either:
822 // - Successfully set
823 // - options were not found and ignore_unknown_options=true
824 // - options were not found and unused was specified
825 // Note that this method is much less sophisticated than the comparable
826 // Configurable::Configure methods. For example, on error, there is no
827 // attempt to return opt_addr to the initial state. Additionally, there
828 // is no effort to initialize (Configurable::PrepareOptions) the object
829 // on success. This method should typically only be used for simpler,
830 // standalone structures and not those that contain shared and embedded
831 // objects.
832 static Status ParseType(
833 const ConfigOptions& config_options, const std::string& opts_str,
834 const std::unordered_map<std::string, OptionTypeInfo>& type_map,
835 void* opt_addr,
836 std::unordered_map<std::string, std::string>* unused = nullptr);
837 static Status ParseType(
838 const ConfigOptions& config_options,
839 const std::unordered_map<std::string, std::string>& opts_map,
840 const std::unordered_map<std::string, OptionTypeInfo>& type_map,
841 void* opt_addr,
842 std::unordered_map<std::string, std::string>* unused = nullptr);
843
20effc67
TL
844 // Parses the input value according to the map for the struct at opt_addr
845 // struct_name is the name of the struct option as registered
846 // opt_name is the name of the option being evaluated. This may
847 // be the whole struct or a sub-element of it, based on struct_name and
848 // opt_name.
849 static Status ParseStruct(
850 const ConfigOptions& config_options, const std::string& struct_name,
851 const std::unordered_map<std::string, OptionTypeInfo>* map,
1e59de90
TL
852 const std::string& opt_name, const std::string& value, void* opt_addr);
853
854 // Serializes the values from opt_addr using the rules in type_map.
855 // Returns the serialized form in result.
856 // Returns OK on success or non-OK if some option could not be serialized.
857 static Status SerializeType(
858 const ConfigOptions& config_options,
859 const std::unordered_map<std::string, OptionTypeInfo>& type_map,
860 const void* opt_addr, std::string* value);
20effc67
TL
861
862 // Serializes the input addr according to the map for the struct to value.
863 // struct_name is the name of the struct option as registered
864 // opt_name is the name of the option being evaluated. This may
865 // be the whole struct or a sub-element of it
866 static Status SerializeStruct(
867 const ConfigOptions& config_options, const std::string& struct_name,
868 const std::unordered_map<std::string, OptionTypeInfo>* map,
1e59de90
TL
869 const std::string& opt_name, const void* opt_addr, std::string* value);
870
871 // Compares the values in this_addr and that_addr using the rules in type_map.
872 // If the values are equal, returns true
873 // If the values are not equal, returns false and sets mismatch to the name
874 // of the first value that did not match.
875 static bool TypesAreEqual(
876 const ConfigOptions& config_options,
877 const std::unordered_map<std::string, OptionTypeInfo>& map,
878 const void* this_addr, const void* that_addr, std::string* mismatch);
20effc67
TL
879
880 // Compares the input offsets according to the map for the struct and returns
881 // true if they are equivalent, false otherwise.
882 // struct_name is the name of the struct option as registered
883 // opt_name is the name of the option being evaluated. This may
884 // be the whole struct or a sub-element of it
885 static bool StructsAreEqual(
886 const ConfigOptions& config_options, const std::string& struct_name,
887 const std::unordered_map<std::string, OptionTypeInfo>* map,
1e59de90
TL
888 const std::string& opt_name, const void* this_offset,
889 const void* that_offset, std::string* mismatch);
20effc67
TL
890
891 // Finds the entry for the opt_name in the opt_map, returning
892 // nullptr if not found.
893 // If found, elem_name will be the name of option to find.
894 // This may be opt_name, or a substring of opt_name.
895 // For "simple" options, opt_name will be equal to elem_name. Given the
896 // opt_name "opt", elem_name will equal "opt".
897 // For "embedded" options (like structs), elem_name may be opt_name
898 // or a field within the opt_name. For example, given the struct "struct",
899 // and opt_name of "struct.field", elem_name will be "field"
900 static const OptionTypeInfo* Find(
901 const std::string& opt_name,
902 const std::unordered_map<std::string, OptionTypeInfo>& opt_map,
903 std::string* elem_name);
904
905 // Returns the next token marked by the delimiter from "opts" after start in
906 // token and updates end to point to where that token stops. Delimiters inside
907 // of braces are ignored. Returns OK if a token is found and an error if the
908 // input opts string is mis-formatted.
909 // Given "a=AA;b=BB;" start=2 and delimiter=";", token is "AA" and end points
910 // to "b" Given "{a=A;b=B}", the token would be "a=A;b=B"
911 //
912 // @param opts The string in which to find the next token
913 // @param delimiter The delimiter between tokens
914 // @param start The position in opts to start looking for the token
1e59de90 915 // @param ed Returns the end position in opts of the token
20effc67
TL
916 // @param token Returns the token
917 // @returns OK if a token was found
918 // @return InvalidArgument if the braces mismatch
919 // (e.g. "{a={b=c;}" ) -- missing closing brace
920 // @return InvalidArgument if an expected delimiter is not found
921 // e.g. "{a=b}c=d;" -- missing delimiter before "c"
922 static Status NextToken(const std::string& opts, char delimiter, size_t start,
923 size_t* end, std::string* token);
924
1e59de90
TL
925 constexpr static const char* kIdPropName() { return "id"; }
926 constexpr static const char* kIdPropSuffix() { return ".id"; }
927
20effc67
TL
928 private:
929 int offset_;
930
931 // The optional function to convert a string to its representation
932 ParseFunc parse_func_;
933
934 // The optional function to convert a value to its string representation
935 SerializeFunc serialize_func_;
936
937 // The optional function to match two option values
938 EqualsFunc equals_func_;
939
1e59de90
TL
940 PrepareFunc prepare_func_;
941 ValidateFunc validate_func_;
20effc67
TL
942 OptionType type_;
943 OptionVerificationType verification_;
944 OptionTypeFlags flags_;
945};
946
1e59de90
TL
947// Parses the input value into elements of the result array, which has fixed
948// array size. For example, if the value=1:2:3 and elem_info parses integers,
949// the result array will be {1,2,3}. Array size is defined in the OptionTypeInfo
950// the input value has to match with that.
951// @param config_options Controls how the option value is parsed.
952// @param elem_info Controls how individual tokens in value are parsed
953// @param separator Character separating tokens in values (':' in the above
954// example)
955// @param name The name associated with this array option
956// @param value The input string to parse into tokens
957// @param result Returns the results of parsing value into its elements.
958// @return OK if the value was successfully parse
959// @return InvalidArgument if the value is improperly formed or element number
960// doesn't match array size defined in OptionTypeInfo
961// or if the token could not be parsed
962// @return NotFound If the tokenized value contains unknown options for
963// its type
964template <typename T, size_t kSize>
965Status ParseArray(const ConfigOptions& config_options,
966 const OptionTypeInfo& elem_info, char separator,
967 const std::string& name, const std::string& value,
968 std::array<T, kSize>* result) {
969 Status status;
970
971 ConfigOptions copy = config_options;
972 copy.ignore_unsupported_options = false;
973 size_t i = 0, start = 0, end = 0;
974 for (; status.ok() && i < kSize && start < value.size() &&
975 end != std::string::npos;
976 i++, start = end + 1) {
977 std::string token;
978 status = OptionTypeInfo::NextToken(value, separator, start, &end, &token);
979 if (status.ok()) {
980 status = elem_info.Parse(copy, name, token, &((*result)[i]));
981 if (config_options.ignore_unsupported_options &&
982 status.IsNotSupported()) {
983 // If we were ignoring unsupported options and this one should be
984 // ignored, ignore it by setting the status to OK
985 status = Status::OK();
986 }
987 }
988 }
989 if (!status.ok()) {
990 return status;
991 }
992 // make sure the element number matches the array size
993 if (i < kSize) {
994 return Status::InvalidArgument(
995 "Serialized value has less elements than array size", name);
996 }
997 if (start < value.size() && end != std::string::npos) {
998 return Status::InvalidArgument(
999 "Serialized value has more elements than array size", name);
1000 }
1001 return status;
1002}
1003
1004// Serializes the fixed size input array into its output value. Elements are
1005// separated by the separator character. This element will convert all of the
1006// elements in array into their serialized form, using elem_info to perform the
1007// serialization.
1008// For example, if the array contains the integers 1,2,3 and elem_info
1009// serializes the output would be 1:2:3 for separator ":".
1010// @param config_options Controls how the option value is serialized.
1011// @param elem_info Controls how individual tokens in value are serialized
1012// @param separator Character separating tokens in value (':' in the above
1013// example)
1014// @param name The name associated with this array option
1015// @param array The input array to serialize
1016// @param value The output string of serialized options
1017// @return OK if the value was successfully parse
1018// @return InvalidArgument if the value is improperly formed or if the token
1019// could not be parsed
1020// @return NotFound If the tokenized value contains unknown options for
1021// its type
1022template <typename T, size_t kSize>
1023Status SerializeArray(const ConfigOptions& config_options,
1024 const OptionTypeInfo& elem_info, char separator,
1025 const std::string& name,
1026 const std::array<T, kSize>& array, std::string* value) {
1027 std::string result;
1028 ConfigOptions embedded = config_options;
1029 embedded.delimiter = ";";
1030 int printed = 0;
1031 for (const auto& elem : array) {
1032 std::string elem_str;
1033 Status s = elem_info.Serialize(embedded, name, &elem, &elem_str);
1034 if (!s.ok()) {
1035 return s;
1036 } else if (!elem_str.empty()) {
1037 if (printed++ > 0) {
1038 result += separator;
1039 }
1040 // If the element contains embedded separators, put it inside of brackets
1041 if (elem_str.find(separator) != std::string::npos) {
1042 result += "{" + elem_str + "}";
1043 } else {
1044 result += elem_str;
1045 }
1046 }
1047 }
1048 if (result.find("=") != std::string::npos) {
1049 *value = "{" + result + "}";
1050 } else if (printed > 1 && result.at(0) == '{') {
1051 *value = "{" + result + "}";
1052 } else {
1053 *value = result;
1054 }
1055 return Status::OK();
1056}
1057
1058// Compares the input arrays array1 and array2 for equality
1059// Elements of the array are compared one by one using elem_info to perform the
1060// comparison.
1061//
1062// @param config_options Controls how the arrays are compared.
1063// @param elem_info Controls how individual elements in the arrays are compared
1064// @param name The name associated with this array option
1065// @param array1,array2 The arrays to compare.
1066// @param mismatch If the arrays are not equivalent, mismatch will point to
1067// the first element of the comparison that did not match.
1068// @return true If vec1 and vec2 are "equal", false otherwise
1069template <typename T, size_t kSize>
1070bool ArraysAreEqual(const ConfigOptions& config_options,
1071 const OptionTypeInfo& elem_info, const std::string& name,
1072 const std::array<T, kSize>& array1,
1073 const std::array<T, kSize>& array2, std::string* mismatch) {
1074 assert(array1.size() == kSize);
1075 assert(array2.size() == kSize);
1076 for (size_t i = 0; i < kSize; ++i) {
1077 if (!elem_info.AreEqual(config_options, name, &array1[i], &array2[i],
1078 mismatch)) {
1079 return false;
1080 }
1081 }
1082 return true;
1083}
1084
20effc67
TL
1085// Parses the input value into elements of the result vector. This method
1086// will break the input value into the individual tokens (based on the
1087// separator), where each of those tokens will be parsed based on the rules of
1088// elem_info. The result vector will be populated with elements based on the
1089// input tokens. For example, if the value=1:2:3:4:5 and elem_info parses
1090// integers, the result vector will contain the integers 1,2,3,4,5
1091// @param config_options Controls how the option value is parsed.
1092// @param elem_info Controls how individual tokens in value are parsed
1093// @param separator Character separating tokens in values (':' in the above
1094// example)
1095// @param name The name associated with this vector option
1096// @param value The input string to parse into tokens
1097// @param result Returns the results of parsing value into its elements.
1098// @return OK if the value was successfully parse
1099// @return InvalidArgument if the value is improperly formed or if the token
1100// could not be parsed
1101// @return NotFound If the tokenized value contains unknown options for
1102// its type
1103template <typename T>
1104Status ParseVector(const ConfigOptions& config_options,
1105 const OptionTypeInfo& elem_info, char separator,
1106 const std::string& name, const std::string& value,
1107 std::vector<T>* result) {
1108 result->clear();
1109 Status status;
1110
1111 // Turn off ignore_unknown_objects so we can tell if the returned
1112 // object is valid or not.
1113 ConfigOptions copy = config_options;
1114 copy.ignore_unsupported_options = false;
1115 for (size_t start = 0, end = 0;
1116 status.ok() && start < value.size() && end != std::string::npos;
1117 start = end + 1) {
1118 std::string token;
1119 status = OptionTypeInfo::NextToken(value, separator, start, &end, &token);
1120 if (status.ok()) {
1121 T elem;
1e59de90 1122 status = elem_info.Parse(copy, name, token, &elem);
20effc67
TL
1123 if (status.ok()) {
1124 result->emplace_back(elem);
1125 } else if (config_options.ignore_unsupported_options &&
1126 status.IsNotSupported()) {
1127 // If we were ignoring unsupported options and this one should be
1128 // ignored, ignore it by setting the status to OK
1129 status = Status::OK();
1130 }
1131 }
1132 }
1133 return status;
1134}
1135
1136// Serializes the input vector into its output value. Elements are
1137// separated by the separator character. This element will convert all of the
1138// elements in vec into their serialized form, using elem_info to perform the
1139// serialization.
1140// For example, if the vec contains the integers 1,2,3,4,5 and elem_info
1141// serializes the output would be 1:2:3:4:5 for separator ":".
1142// @param config_options Controls how the option value is serialized.
1143// @param elem_info Controls how individual tokens in value are serialized
1144// @param separator Character separating tokens in value (':' in the above
1145// example)
1146// @param name The name associated with this vector option
1147// @param vec The input vector to serialize
1148// @param value The output string of serialized options
1149// @return OK if the value was successfully parse
1150// @return InvalidArgument if the value is improperly formed or if the token
1151// could not be parsed
1152// @return NotFound If the tokenized value contains unknown options for
1153// its type
1154template <typename T>
1155Status SerializeVector(const ConfigOptions& config_options,
1156 const OptionTypeInfo& elem_info, char separator,
1157 const std::string& name, const std::vector<T>& vec,
1158 std::string* value) {
1159 std::string result;
1160 ConfigOptions embedded = config_options;
1161 embedded.delimiter = ";";
1e59de90
TL
1162 int printed = 0;
1163 for (const auto& elem : vec) {
20effc67 1164 std::string elem_str;
1e59de90 1165 Status s = elem_info.Serialize(embedded, name, &elem, &elem_str);
20effc67
TL
1166 if (!s.ok()) {
1167 return s;
1e59de90
TL
1168 } else if (!elem_str.empty()) {
1169 if (printed++ > 0) {
20effc67
TL
1170 result += separator;
1171 }
1172 // If the element contains embedded separators, put it inside of brackets
1e59de90 1173 if (elem_str.find(separator) != std::string::npos) {
20effc67
TL
1174 result += "{" + elem_str + "}";
1175 } else {
1176 result += elem_str;
1177 }
1178 }
1179 }
1180 if (result.find("=") != std::string::npos) {
1181 *value = "{" + result + "}";
1e59de90
TL
1182 } else if (printed > 1 && result.at(0) == '{') {
1183 *value = "{" + result + "}";
20effc67
TL
1184 } else {
1185 *value = result;
1186 }
1187 return Status::OK();
1188}
1189
1190// Compares the input vectors vec1 and vec2 for equality
1191// If the vectors are the same size, elements of the vectors are compared one by
1192// one using elem_info to perform the comparison.
1193//
1194// @param config_options Controls how the vectors are compared.
1195// @param elem_info Controls how individual elements in the vectors are compared
1196// @param name The name associated with this vector option
1197// @param vec1,vec2 The vectors to compare.
1198// @param mismatch If the vectors are not equivalent, mismatch will point to
1199// the first
1e59de90 1200// element of the comparison that did not match.
20effc67
TL
1201// @return true If vec1 and vec2 are "equal", false otherwise
1202template <typename T>
1203bool VectorsAreEqual(const ConfigOptions& config_options,
1204 const OptionTypeInfo& elem_info, const std::string& name,
1205 const std::vector<T>& vec1, const std::vector<T>& vec2,
1206 std::string* mismatch) {
1207 if (vec1.size() != vec2.size()) {
1208 *mismatch = name;
1209 return false;
1210 } else {
1211 for (size_t i = 0; i < vec1.size(); ++i) {
1212 if (!elem_info.AreEqual(
1213 config_options, name, reinterpret_cast<const char*>(&vec1[i]),
1214 reinterpret_cast<const char*>(&vec2[i]), mismatch)) {
1215 return false;
1216 }
1217 }
1218 return true;
1219 }
1220}
1221} // namespace ROCKSDB_NAMESPACE