MySQL 8.4.0
Source Code Documentation
config_parser.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_HARNESS_CONFIG_PARSER_INCLUDED
27#define MYSQL_HARNESS_CONFIG_PARSER_INCLUDED
28
29#include <functional>
30#include <iterator>
31#include <list>
32#include <map>
33#include <memory>
34#include <stdexcept>
35#include <string>
36#include <vector>
37
38#include "harness_export.h"
39
40namespace mysql_harness {
41
42class ConfigSection;
43class Path;
44
45/**
46 * Convenience class for handling iterator range.
47 *
48 * This is a template class that accept a pair of iterators and
49 * implement the necessary methods to be able to be used as a sequence
50 * container.
51 */
52template <class Iter>
53class Range {
54 public:
55 using value_type = typename Iter::value_type;
56 using reference = typename Iter::reference;
57 using iterator = Iter;
59 using difference_type = typename std::iterator_traits<Iter>::difference_type;
61
62 Range(Iter start, Iter finish) : begin_(start), end_(finish) {}
63
64 /** Get iterator to beginning of range. */
65 Iter begin() const { return begin_; }
66
67 /** Get iterator to end of range. */
68 Iter end() const { return end_; }
69
70 /** Check if range is empty. */
71 bool empty() const { return begin_ == end_; }
72
73 /**
74 * Get size of the range, that is, number of elements in the range.
75 *
76 * @note This call `std::distance` internally.
77 *
78 * @returns The number of elements in the range.
79 */
80 size_type size() const { return std::distance(begin_, end_); }
81
82 private:
83 Iter begin_;
84 Iter end_;
85};
86
87/**
88 * Exception thrown for syntax errors.
89 *
90 * @ingroup ConfigParser
91 * Exception thrown for errors during parsing configuration file.
92 */
93
94class syntax_error : public std::logic_error {
95 public:
96 explicit syntax_error(const std::string &msg) : std::logic_error(msg) {}
97};
98
99/**
100 * Exception thrown for section problems.
101 *
102 * @ingroup ConfigParser
103 */
104
105class bad_section : public std::runtime_error {
106 public:
107 explicit bad_section(const std::string &msg) : std::runtime_error(msg) {}
108};
109
110/**
111 * Exception thrown for option problems.
112 *
113 * @ingroup ConfigParser
114 */
115
116class bad_option : public std::runtime_error {
117 public:
118 explicit bad_option(const std::string &msg) : std::runtime_error(msg) {}
119};
120
121/**
122 * Exception thrown for option value problems.
123 *
124 * @ingroup ConfigParser
125 */
126
127class bad_option_value : public std::runtime_error {
128 public:
129 explicit bad_option_value(const std::string &msg) : std::runtime_error(msg) {}
130};
131
132/**
133 * Configuration section.
134 *
135 * @ingroup ConfigParser
136 *
137 * A named configuration file section with a zero or more
138 * configuration file options.
139 */
140
141class HARNESS_EXPORT ConfigSection {
142 public:
143 using OptionMap = std::map<std::string, std::string>;
145
146 ConfigSection(const std::string &name_arg, const std::string &key_arg,
147 const std::shared_ptr<const ConfigSection> &defaults);
148
150 const std::shared_ptr<const ConfigSection> &defaults);
152 ConfigSection(const ConfigSection &) = default;
153
154 /**
155 * Clear the options in the section.
156 *
157 * This will remove options from the configuration section.
158 */
159 void clear();
160
161 /**
162 * Update section with contents of another section.
163 *
164 * The configuration section will be updated with the contents of
165 * the other section. For any options that exist in the section, the
166 * value will be overwritten by the values in the `other`
167 * section. If the option do not exist, a new option will be created
168 * and the value set to the value of the option in the `other`
169 * section.
170 *
171 * @note The section name and key have to match for the update to be
172 * done.
173 *
174 * @exception bad_section Thrown if the section name or section key
175 * do not match.
176 *
177 * @param other Section to copy options and values from.
178 */
179 void update(const ConfigSection &other); // throws bad_section
180
181 std::string get(std::string_view option) const;
182 void set(const std::string &option,
183 const std::string &value); // throws bad_option
184 void add(const std::string &option, const std::string &value);
185 bool has(std::string_view option) const;
186
187 /**
188 * Range for options in section.
189 *
190 * Typical usage is:
191 *
192 * @code
193 * for (auto elem: section.get_options())
194 * std::cout << "Option " << elem.first
195 * << " has value " << elem.second
196 * << std::endl;
197 * @endcode
198 *
199 * @returns a range of options each consisting of a pair
200 * option-value.
201 */
203 return OptionRange(options_.begin(), options_.end());
204 }
205
206 /*
207 * Returns name of the section in which option is specified. The returned
208 * name may be the name of the section or the name of the default section.
209 *
210 * @option option The name of the option
211 * @return The name of the ConfigSection which option is specified.
212 */
213 std::string get_section_name(std::string_view option) const;
214
215 /*
216 * Returns name of the section.
217 */
218 std::string get_section_name() const;
219
220#ifndef NDEBUG
221 bool assert_default(const ConfigSection *def) const {
222 return def == defaults_.get();
223 }
224#endif
225
226 public:
227 const std::string name;
228 const std::string key;
229
230 private:
231 std::string do_replace(const std::string &value, int depth = 0) const;
232
233 const int kMaxInterpolationDepth = 10;
234
235 std::pair<OptionMap::const_iterator, bool> do_locate(
236 std::string_view option) const noexcept;
237
238 const std::shared_ptr<const ConfigSection> defaults_;
240};
241
242/**
243 * Configuration.
244 *
245 * @ingroup ConfigParser
246 *
247 * A configuration consisting of named configuration sections.
248 *
249 * There are three different constructors that are available with
250 * different kind of parameters.
251 */
252
253class HARNESS_EXPORT Config {
254 public:
255 using SectionKey = std::pair<std::string, std::string>;
257 using SectionList = std::list<ConfigSection *>;
258 using ConstSectionList = std::list<const ConfigSection *>;
259 using ConfigOverwrites = std::map<std::pair<std::string, std::string>,
260 std::map<std::string, std::string>>;
261
262 /**@{*/
263 /** Flags for construction of configurations. */
264
265 static constexpr unsigned int allow_keys = 1U;
266
267 /**@}*/
268
269 /**
270 * Default pattern to used to identify configuration files.
271 */
272 static constexpr const char *DEFAULT_PATTERN = "*.cfg";
273
274 /**
275 * Construct a configuration.
276 *
277 * @param flags flags.
278 * @param config_overwrites overwrites for selected configuration options.
279 */
280 explicit Config(unsigned int flags = 0U,
281 const ConfigOverwrites &config_overwrites = {});
282
283 /**
284 * Construct a configuration.
285 *
286 * @tparam AssocT Associate container type
287 * @arg @c parameters Associative container with parameters.
288 * @arg @c flags flags.
289 * @arg @c config_overwrites overwrites for selected configuration options.
290 * @throws bad_option on bad options
291 */
292 template <class AssocT>
293 explicit Config(const AssocT &parameters, unsigned int flags = 0U,
294 const ConfigOverwrites &config_overwrites = {})
295 : Config(flags, config_overwrites) {
296 for (auto item : parameters)
297 defaults_->set(item.first, item.second); // throws bad_option
298 apply_overwrites();
299 }
300
301 /**
302 * Construct a configuration.
303 *
304 * Construct a configuration instance by reading a configuration file
305 * and overriding the values read from a list of supplied
306 * parameters.
307 *
308 * @tparam AssocT Associate container type
309 * @tparam SeqT Sequence container type
310 * @arg @c parameters Associative container with parameters.
311 * @arg @c reserved Sequence container of reserved words.
312 * @arg @c flags flags.
313 * @arg @c config_overwrites overwrites for selected configuration options.
314 * @throws bad_option on bad options
315 */
316 template <class AssocT, class SeqT>
317 explicit Config(const AssocT &parameters, const SeqT &reserved,
318 unsigned int flags = 0U,
319 const ConfigOverwrites &config_overwrites = {})
320 : Config(parameters, flags, config_overwrites) /* throws bad_option */ {
321 for (auto word : reserved) reserved_.push_back(word);
322 }
323
324 Config(const Config &) = default;
325 Config &operator=(const Config &) = default;
326 virtual ~Config() = default;
327
328 template <class SeqT>
329 void set_reserved(const SeqT &reserved) {
330 reserved_.assign(reserved.begin(), reserved.end());
331 }
332
333 /**
334 * Read configuration file from file, directory, or input stream.
335 *
336 * If there are conflicting sections (several instance sections with
337 * identical name and key) or conflicting options (several instances
338 * of an option in the same section) in the input, an exception will
339 * be thrown.
340 *
341 * If the input is a stream, the contents of the stream will be
342 * added to the configuration, but if the input is either a file or
343 * a directory, the exisisting contents of the configuration will be
344 * removed.
345 *
346 * If a `pattern` is given, the path is assumed to be a directory
347 * and all files matching the pattern will be read into the the
348 * configuration object. The files together will be treated as if it
349 * is a single file, that is, no conflicting option values or
350 * sections are allowed and will raise an exception.
351 *
352 * @param input Input stream to read from.
353 *
354 * @exception syntax_error Raised if there is a syntax error in the
355 * configuration file and the configuration file have to be corrected.
356 *
357 * @exception bad_section Raised if there is a duplicate section
358 * (section with the same name and key) in the input stream.
359 *
360 * @exception bad_option Raised if there is a duplicate definition
361 * of an option (same option is given twice in a section).
362 */
363 void read(std::istream &input);
364
365 /** @overload */
366 void read(const Path &path);
367
368 /*
369 * @param path Path to directory or file to read from.
370 * @param pattern Glob pattern for configuration files in the directory.
371 */
372 /** @overload */
373 void read(const Path &path, const std::string &pattern);
374
375 /**
376 * Check if the configuration is empty.
377 *
378 * @return `true` if there are any sections in the configuration
379 * (not counting the default section), `false` otherwise.
380 */
381 bool empty() const;
382
383 /**
384 * Clear the configuration.
385 *
386 * This will remove all configuration information from the
387 * configuration, including the default section, but not the
388 * reserved words nor the flags set.
389 */
390 void clear();
391
392 /**
393 * Remove section from configuration
394 *
395 * @param section_key section+key to remove.
396 *
397 * @return true if section was removed, false if section did not exist
398 */
399 bool remove(const SectionKey &section_key) noexcept;
400
401 /*
402 * @param section Name of section to remove.
403 * @param key Optional key of section to remove.
404 */
405 /** @overload */
406 bool remove(const std::string &section,
407 const std::string &key = std::string()) noexcept;
408
409 /**
410 * Update configuration using another configuration.
411 *
412 * This will incorporate all the sections and options from the
413 * `other` configuration by adding sections that are missing and
414 * overwriting option values for sections that exist in the current
415 * configuration.
416 *
417 * @param other Configuration to read section, options, and values
418 * from.
419 */
420 void update(const Config &other);
421
422 /**
423 * Get a list of sections having a name.
424 *
425 * There can be several sections under the same name, but they will
426 * have different keys.
427 *
428 * @note The empty string is used to denote the keyless section.
429 *
430 * @param section Section name of sections to fetch.
431 */
432 ConstSectionList get(const std::string &section) const;
433
434 /** @overload */
435 SectionList get(const std::string &section);
436
437 ConfigSection &get_default_section() const;
438
439 /**
440 * Get a section by name and key.
441 *
442 * Get a section given a name and a key. Since there can be several
443 * sections with the same name (but different keys) this will always
444 * return a unique section.
445 *
446 * @note The empty string is used to denote the keyless section.
447 *
448 * @param section Name of section to fetch.
449 * @param key Key for section to fetch.
450 *
451 * @return Reference to section instance.
452 *
453 * @exception bad_section Thrown if the section do not exist or if a
454 * key were used but is not allowed.
455 */
456 ConfigSection &get(const std::string &section, const std::string &key);
457
458 /** @overload */
459 const ConfigSection &get(const std::string &section,
460 const std::string &key) const;
461
462 /**
463 * Add a new section to the configuration.
464 *
465 * @param section Name of section to add.
466 * @param key Optional key of section to add.
467 *
468 * @return Reference to newly constructed configuration section
469 * instance.
470 */
471 ConfigSection &add(const std::string &section,
472 const std::string &key = std::string());
473
474 bool has(const std::string &section,
475 const std::string &key = std::string()) const;
476
477 /**
478 * @return True if a section exists, no matter what the key is.
479 */
480 bool has_any(std::string_view section) const;
481
482 // all 3 below throw bad_option (std::runtime_error) on illegal option name
483 // (one that contains illegal characters) */
484 std::string get_default(std::string_view option) const;
485 bool has_default(std::string_view option) const;
486 void set_default(const std::string &option, const std::string &value);
487
488 bool is_reserved(const std::string &word) const;
489
490 std::list<Config::SectionKey> section_names() const {
491 decltype(section_names()) result;
492 for (auto &section : sections_) result.push_back(section.first);
493 return result;
494 }
495
496 /**
497 * Get a list of all sections in the configuration.
498 */
499 ConstSectionList sections() const;
500
501 bool error_on_unsupported_option{false};
502
503 protected:
504 using SectionMap = std::map<SectionKey, ConfigSection>;
505 using ReservedList = std::vector<std::string>;
506
507 /**
508 * Copy the guts of another configuration.
509 *
510 * This member function is used to copy configuration state (the
511 * "guts") but not the sections and options, including not copying
512 * the default section.
513 */
514 void copy_guts(const Config &source) noexcept;
515
516 /**
517 * Function to read single file.
518 *
519 * @throws std::runtime_error, syntax_error
520 */
521 virtual void do_read_file(const Path &path);
522
523 /**
524 * Function to read the configuration from a stream.
525 *
526 * @throws syntax_error, maybe bad_section (not sure if it can happen)
527 *
528 * @note This function is guaranteeed to be called for reading all
529 * configurations so it can be overridden to handle post- or
530 * pre-parsing actions.
531 */
532 virtual void do_read_stream(std::istream &input);
533
534 void apply_overwrites();
535
538 std::shared_ptr<ConfigSection> defaults_;
539 unsigned int flags_;
541};
542
543/**
544 * Returns true if a character given as a parameter is valid for config
545 * identifier (section, section key or option name)
546 */
547bool HARNESS_EXPORT is_valid_conf_ident_char(const char ch);
548
549} // namespace mysql_harness
550
551#endif /* MYSQL_HARNESS_CONFIG_PARSER_INCLUDED */
A helper class for handling file paths.
Definition: path.h:38
Configuration section.
Definition: config_parser.h:141
OptionRange get_options() const
Range for options in section.
Definition: config_parser.h:202
const std::shared_ptr< const ConfigSection > defaults_
Definition: config_parser.h:238
OptionMap options_
Definition: config_parser.h:239
ConfigSection & operator=(const ConfigSection &)=delete
const std::string key
Definition: config_parser.h:228
std::string get(std::string_view option) const
Definition: config_parser.cc:163
bool assert_default(const ConfigSection *def) const
Definition: config_parser.h:221
ConfigSection(const ConfigSection &)=default
std::map< std::string, std::string > OptionMap
Definition: config_parser.h:143
const std::string name
Definition: config_parser.h:227
Configuration.
Definition: config_parser.h:253
std::pair< std::string, std::string > SectionKey
Definition: config_parser.h:255
Config(const AssocT &parameters, unsigned int flags=0U, const ConfigOverwrites &config_overwrites={})
Construct a configuration.
Definition: config_parser.h:293
std::list< const ConfigSection * > ConstSectionList
Definition: config_parser.h:258
std::map< std::pair< std::string, std::string >, std::map< std::string, std::string > > ConfigOverwrites
Definition: config_parser.h:260
Config(const AssocT &parameters, const SeqT &reserved, unsigned int flags=0U, const ConfigOverwrites &config_overwrites={})
Construct a configuration.
Definition: config_parser.h:317
std::vector< std::string > ReservedList
Definition: config_parser.h:505
Config & operator=(const Config &)=default
std::list< ConfigSection * > SectionList
Definition: config_parser.h:257
std::map< SectionKey, ConfigSection > SectionMap
Definition: config_parser.h:504
std::shared_ptr< ConfigSection > defaults_
Definition: config_parser.h:538
ConfigSection::OptionMap OptionMap
Definition: config_parser.h:256
void set_reserved(const SeqT &reserved)
Definition: config_parser.h:329
SectionMap sections_
Definition: config_parser.h:536
unsigned int flags_
Definition: config_parser.h:539
Config(const Config &)=default
ConfigOverwrites config_overwrites_
Definition: config_parser.h:540
virtual ~Config()=default
ReservedList reserved_
Definition: config_parser.h:537
Class representing a path in a file system.
Definition: filesystem.h:63
Convenience class for handling iterator range.
Definition: config_parser.h:53
bool empty() const
Check if range is empty.
Definition: config_parser.h:71
typename std::iterator_traits< Iter >::difference_type difference_type
Definition: config_parser.h:59
Iter end_
Definition: config_parser.h:84
difference_type size_type
Definition: config_parser.h:60
Iter end() const
Get iterator to end of range.
Definition: config_parser.h:68
Iter begin_
Definition: config_parser.h:83
size_type size() const
Get size of the range, that is, number of elements in the range.
Definition: config_parser.h:80
iterator const_iterator
Definition: config_parser.h:58
Iter iterator
Definition: config_parser.h:57
typename Iter::value_type value_type
Definition: config_parser.h:55
Range(Iter start, Iter finish)
Definition: config_parser.h:62
typename Iter::reference reference
Definition: config_parser.h:56
Iter begin() const
Get iterator to beginning of range.
Definition: config_parser.h:65
Exception thrown for option value problems.
Definition: config_parser.h:127
bad_option_value(const std::string &msg)
Definition: config_parser.h:129
Exception thrown for option problems.
Definition: config_parser.h:116
bad_option(const std::string &msg)
Definition: config_parser.h:118
Exception thrown for section problems.
Definition: config_parser.h:105
bad_section(const std::string &msg)
Definition: config_parser.h:107
Exception thrown for syntax errors.
Definition: config_parser.h:94
syntax_error(const std::string &msg)
Definition: config_parser.h:96
static int flags[50]
Definition: hp_test1.cc:40
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
static uint update
Definition: myisamlog.cc:94
static char * path
Definition: mysqldump.cc:149
uint16_t value_type
Definition: vt100.h:184
bool distance(const dd::Spatial_reference_system *srs, const Geometry *g1, const Geometry *g2, double *distance, bool *is_null) noexcept
Computes the distance between two geometries.
Definition: distance.cc:40
bool has(const Container &c, Value &&val)
Definition: generic.h:97
Definition: common.h:42
bool HARNESS_EXPORT is_valid_conf_ident_char(const char ch)
Returns true if a character given as a parameter is valid for config identifier (section,...
Definition: config_parser.cc:57
void get(PSI_field *, PSI_longlong *) noexcept
Definition: pfs_plugin_column_bigint_v1_all_empty.cc:32
static mysql_service_status_t remove(reference_caching_channel channel, const char *implementation_name) noexcept
Definition: component.cc:137
static mysql_service_status_t clear(reference_caching_channel channel) noexcept
Definition: component.cc:146
Definition: gcs_xcom_synode.h:64
bool is_reserved(space_id_t space_id)
Check if the space_id is an undo space ID in the reserved range.
Definition: trx0purge.h:166
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2882
std::list< T, ut::allocator< T > > list
Specialization of list which uses ut_allocator.
Definition: ut0new.h:2878
struct result result
Definition: result.h:34
required string key
Definition: replication_asynchronous_connection_failover.proto:60
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
Definition: result.h:30
Definition: dtoa.cc:589