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 #pragma once
7 
8 #include <map>
9 #include <stdexcept>
10 #include <string>
11 #include <vector>
12 
13 #include "rocksdb/configurable.h"
14 #include "rocksdb/convenience.h"
15 
16 namespace ROCKSDB_NAMESPACE {
17 // Helper class defining static methods for supporting the Configurable
18 // class.  The purpose of this class is to keep the Configurable class
19 // as tight as possible and provide methods for doing the actual work
20 // of configuring the objects.
21 class ConfigurableHelper {
22  public:
23   // Configures the input Configurable object based on the parameters.
24   // On successful completion, the Configurable is updated with the settings
25   // from the opt_map.
26   //
27   // The acceptable values of the name/value pairs are documented with the
28   // specific class/instance.
29   //
30   // @param config_options Controls how the arguments are processed.
31   // @param opt_map Name/value pairs of the options to update
32   // @param unused If specified, this value will return the name/value
33   //      pairs from opt_map that were NotFound for this object.
34   // @return OK If all values in the map were successfully updated
35   // @return NotFound If any of the names in the opt_map were not valid
36   //      for this object.  If unused is specified, it will contain the
37   //      collection of NotFound entries
38   // @return NotSupported  If any of the names are valid but the object does
39   //       not know how to convert the value.  This can happen if, for example,
40   //       there is some nested Configurable that cannot be created.
41   // @return InvalidArgument If any of the values cannot be successfully
42   //       parsed.  This can also be returned if PrepareOptions encounters an
43   //       error.
44   static Status ConfigureOptions(
45       const ConfigOptions& config_options, Configurable& configurable,
46       const std::unordered_map<std::string, std::string>& options,
47       std::unordered_map<std::string, std::string>* unused);
48 
49 #ifndef ROCKSDB_LITE
50   // Internal method to configure a set of options for this object.
51   // Classes may override this value to change its behavior.
52   // @param config_options Controls how the options are being configured
53   // @param type_name The name that was registered for this set of options
54   // @param type_map The map of options for this name
55   // @param opt_ptr Pointer to the object being configured for this option set.
56   // @param options The option name/values being updated.  On return, any
57   //    option that was found is removed from the list.
58   // @return OK If all of the options were successfully updated.
59   // @return InvalidArgument If an option was found but the value could not
60   //       be updated.
61   // @return NotFound If an option name was not found in type_mape
62   // @return NotSupported If the option was found but no rule for converting
63   //       the value could be found.
64   static Status ConfigureSomeOptions(
65       const ConfigOptions& config_options, Configurable& configurable,
66       const std::unordered_map<std::string, OptionTypeInfo>& type_map,
67       std::unordered_map<std::string, std::string>* options, void* opt_ptr);
68 
69   // Configures a single option in the input Configurable.
70   // This method will look through the set of option names for this
71   // Configurable searching for one with the input name.  If such an option
72   // is found, it will be configured via the input value.
73   //
74   // @param config_options Controls how the option is being configured
75   // @param configurable The object to configure
76   // @param name For options with sub-options (like Structs or
77   // Configurables),
78   //      this value may be the name of the sub-field of the option being
79   //      updated. For example, if the option is
80   //      "compaction_options_fifo.allow_compaction", then field name would be
81   //      "allow_compaction".  For most options, field_name and opt_name will be
82   //      equivalent.
83   // @param value The new value for this option.
84   // @param See ConfigureOptions for the possible return values
85   static Status ConfigureSingleOption(const ConfigOptions& config_options,
86                                       Configurable& configurable,
87                                       const std::string& name,
88                                       const std::string& value);
89 
90   // Configures the option referenced by opt_info for this configurable
91   // This method configures the option based on opt_info for the input
92   // configurable.
93   // @param config_options Controls how the option is being configured
94   // @param configurable The object to configure
95   // @param opt_name The full option name
96   // @param name For options with sub-options (like Structs or
97   // Configurables),
98   //      this value may be the name of the sub-field of the option being
99   //      updated. For example, if the option is
100   //      "compaction_options_fifo.allow_compaction", then field name would be
101   //      "allow_compaction".  For most options, field_name and opt_name will be
102   //      equivalent.
103   // @param value The new value for this option.
104   // @param See ConfigureOptions for the possible return values
105   static Status ConfigureOption(const ConfigOptions& config_options,
106                                 Configurable& configurable,
107                                 const OptionTypeInfo& opt_info,
108                                 const std::string& opt_name,
109                                 const std::string& name,
110                                 const std::string& value, void* opt_ptr);
111 
112   // Returns the value of the option associated with the input name
113   // This method is the functional inverse of ConfigureOption
114   // @param config_options Controls how the value is returned
115   // @param configurable The object from which to get the option.
116   // @param name The name of the option to return a value for.
117   // @param value The returned value associated with the named option.
118   //              Note that value will be only the serialized version
119   //              of the option and not "name=value"
120   // @return OK If the named field was successfully updated to value.
121   // @return NotFound If the name is not valid for this object.
122   // @param InvalidArgument If the name is valid for this object but
123   //      its value cannot be serialized.
124   static Status GetOption(const ConfigOptions& config_options,
125                           const Configurable& configurable,
126                           const std::string& name, std::string* value);
127 
128   // Serializes the input Configurable into the output result.
129   // This is the inverse of ConfigureOptions
130   // @param config_options Controls how serialization happens.
131   // @param configurable The object to serialize
132   // @param prefix A prefix to add to the each option as it is serialized.
133   // @param result The string representation of the configurable.
134   // @return OK If the options for this object wer successfully serialized.
135   // @return InvalidArgument If one or more of the options could not be
136   // serialized.
137   static Status SerializeOptions(const ConfigOptions& config_options,
138                                  const Configurable& configurable,
139                                  const std::string& prefix,
140                                  std::string* result);
141 
142   // Internal method to list the option names for this object.
143   // Classes may override this value to change its behavior.
144   // @see ListOptions for more details
145   static Status ListOptions(const ConfigOptions& config_options,
146                             const Configurable& configurable,
147                             const std::string& prefix,
148                             std::unordered_set<std::string>* result);
149 
150   // Checks to see if the two configurables are equivalent to one other.
151   // This method assumes that the two objects are of the same class.
152   // @param config_options Controls how the options are compared.
153   // @param this_one The object to compare to.
154   // @param that_one The other object being compared.
155   // @param mismatch If the objects do not match, this parameter contains
156   //      the name of the option that triggered the match failure.
157   // @param True if the objects match, false otherwise.
158   static bool AreEquivalent(const ConfigOptions& config_options,
159                             const Configurable& this_one,
160                             const Configurable& that_one,
161                             std::string* mismatch);
162 
163  private:
164   // Looks for the option specified by name in the RegisteredOptions.
165   // This method traverses the types in the input options vector.  If an entry
166   // matching name is found, that entry, opt_name, and pointer are returned.
167   // @param options  The vector of options to search through
168   // @param name     The name of the option to search for in the OptionType map
169   // @param opt_name If the name was found, this value is set to the option name
170   //                 associated with the input name/type.
171   // @param opt_ptr  If the name was found, this value is set to the option
172   // pointer
173   //                 in the RegisteredOptions vector associated with this entry
174   // @return         A pointer to the OptionTypeInfo from the options if found,
175   //                 nullptr if the name was not found in the input options
176   static const OptionTypeInfo* FindOption(
177       const std::vector<Configurable::RegisteredOptions>& options,
178       const std::string& name, std::string* opt_name, void** opt_ptr);
179 
180   static Status ConfigureCustomizableOption(
181       const ConfigOptions& config_options, Configurable& configurable,
182       const OptionTypeInfo& opt_info, const std::string& opt_name,
183       const std::string& name, const std::string& value, void* opt_ptr);
184 #endif  // ROCKSDB_LITE
185 };
186 
187 }  // namespace ROCKSDB_NAMESPACE
188