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