MySQL 8.0.39
Source Code Documentation
router_app.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 ROUTER_MYSQL_ROUTER_INCLUDED
27#define ROUTER_MYSQL_ROUTER_INCLUDED
28
30
31/** @file
32 * @brief Defining the main class MySQLRouter
33 *
34 * This file defines the main class `MySQLRouter`.
35 *
36 */
37
43
44#include <cstdint>
45#include <iostream>
46#include <stdexcept>
47#include <vector>
48
49static const size_t kHelpScreenWidth = 72;
50static const size_t kHelpScreenIndent = 8;
51
52class ConfigFiles;
53
54/** @class MySQLRouter
55 * @brief Manage the MySQL Router application.
56 *
57 * The class MySQLRouter manages the MySQL Router application. It handles the
58 * command arguments, finds valid configuration files, and starts all plugins.
59 *
60 * Since MySQL Router requires at least 1 configuration file to be available
61 * for reading, if no default configuration file location could be read and no
62 * explicit location was given, the application exits.
63 *
64 * The class depends on MySQL Harness to, among other things, load the
65 * configuration and initialize all request plugins.
66 *
67 * Example usage:
68 *
69 * int main(int argc, char** argv) {
70 * MySQLRouter router(argc, argv);
71 * router.start();
72 * }
73 *
74 */
76 public:
77 /** @brief Default constructor
78 *
79 * Default constructor of MySQL Router which will not initialize.
80 *
81 * Usage:
82 *
83 * MySQLRouter router;
84 * router.start();
85 *
86 */
88 : can_start_(false),
89 showing_info_(false),
90 out_stream_(std::cout),
91 err_stream_(std::cerr)
92#ifndef _WIN32
93 ,
94 sys_user_operations_(mysqlrouter::SysUserOperations::instance())
95#endif
96 {
97 }
98
99 /** @brief Constructor with command line arguments as vector
100 *
101 * Constructor of MySQL Router which will start with the given command
102 * line arguments as a vector of strings.
103 *
104 * Example usage:
105 *
106 * MySQLRouter router(argv[0],
107 * vector<string>({argv + 1, argv + argc}));
108 * router.start();
109 *
110 * @param program_name path of the started executable
111 * @param arguments a vector of strings
112 * @param out_stream output stream representing "stdout"
113 * @param err_stream output stream representing "stderr"
114 */
115#ifndef _WIN32
116 /// @param sys_user_operations system operations which provide chown, ...
117#endif
118 MySQLRouter(const std::string &program_name,
119 const std::vector<std::string> &arguments,
120 std::ostream &out_stream = std::cout,
121 std::ostream &err_stream = std::cerr
122#ifndef _WIN32
123 ,
124 mysqlrouter::SysUserOperationsBase *sys_user_operations =
126#endif
127 );
128
129 /** @brief Constructor with command line arguments
130 *
131 * Constructor of MySQL Router which will start with the given command
132 * line arguments given as the arguments argc and argv. Typically, argc
133 * and argv are passed on from the global main function.
134 *
135 * Example usage:
136 *
137 * int main(int argc, char** argv) {
138 * MySQLRouter router(argc, argv);
139 * router.start();
140 * }
141 *
142 * @param argc number of arguments
143 * @param argv pointer to first command line argument
144 * @param out_stream output stream representing "stdout"
145 * @param err_stream output stream representing "stderr"
146 */
147#ifndef _WIN32
148 /// @param sys_user_operations system operations which provide chown, ...
149#endif
150 MySQLRouter(const int argc, char **argv, std::ostream &out_stream,
151 std::ostream &err_stream
152#ifndef _WIN32
153 ,
154 mysqlrouter::SysUserOperationsBase *sys_user_operations =
156#endif
157 );
158
159 virtual ~MySQLRouter() = default;
160
161 /** @brief Initialize main logger
162 *
163 * Initializes main logger, according to options in the configuration.
164 *
165 * @param config Configuration to be used to initialize logger
166 * @param raw_mode If true, all messages are logged raw; if false, messages
167 * are subject formatting
168 * @param use_os_log If true, Windows EventLog will be used instead of STDERR;
169 * Currently this option is only meaningful on Windows
170 *
171 * @throws std::runtime_error on:
172 * - failure to initialize file or OS logger
173 * - bad configuration
174 *
175 * @note This function is static and public, because unlike
176 * create_plugin_loggers(), it's also meant to be called very early during
177 * startup, close to main().
178 */
180 bool raw_mode = false, bool use_os_log = false);
181
182 // Information member function
183 std::string get_package_name() noexcept;
184
185 /** @brief Returns the MySQL Router version as string
186 *
187 * Returns the MySQL Router as a string. The string is a concatenation
188 * of version's major, minor and patch parts, for example `1.0.2`.
189 *
190 * @return string containing the version
191 */
192 std::string get_version() noexcept;
193
194 /** @brief Returns string version details.
195 *
196 * Returns string with name and version details, including:
197 *
198 * * name of the application,
199 * * version,
200 * * platform and architecture,
201 * * edition,
202 * * and a special part-of-clause.
203 *
204 * The architecture is either 32-bit or 64-bit. Edition is usually used to
205 * denote whether release is either GPLv2 license or commercial.
206 *
207 * The part-of clause is used to show which product family MySQL Router
208 * belongs to.
209 *
210 * @internal
211 * Most information can be defined while configuring using CMake and will
212 * become available through the router_config.h file (generated from
213 * router_config.h.in).
214 * @endinternal
215 *
216 * @return a string containing version details
217 */
218 std::string get_version_line() noexcept;
219
220 /** @brief Starts the MySQL Router application
221 *
222 * Starts the MySQL Router application, reading the configuration file(s) and
223 * loading and starting all plugins.
224 *
225 * Example:
226 *
227 * MySQLRouter router;
228 * router.start();
229 *
230 * Throws std::runtime_error on configuration or plugin errors.
231 *
232 * @internal
233 * We are using MySQL Harness to load and start the plugins. We give Harness
234 * a configuration files and it will parse it. Not that at this moment,
235 * Harness only accept one configuration file.
236 * @endinternal
237 */
238 void start();
239
240 /** @brief Stop and cleanup the MySQL Router application
241 *
242 * Cleanup to perform when the MySQL Router application shuts down.
243 *
244 * Example:
245 *
246 * MySQLRouter router;
247 * router.start();
248 * ...
249 * router.stop();
250 *
251 * Throws std::runtime_error on errors during cleanup.
252 *
253 * @internal
254 * We ensure that the Harness pidfile is removed if present.
255 * @endinternal
256 */
257 void stop();
258
259 /** @brief Gets list of default configuration files
260 *
261 * Returns a list of configuration files which will be read (if available)
262 * by default.
263 *
264 * @return std::vector<string>
265 */
266 const std::vector<std::string> &get_default_config_files() const noexcept {
268 }
269
270 /** @brief Gets list of configuration files passed using command line
271 *
272 * Returns a list of configuration files which were passed through command
273 * line options.
274 *
275 * @return std::vector<string>
276 */
277 const std::vector<std::string> &get_config_files() const noexcept {
278 return config_files_;
279 }
280
281 /** @brief Gets list of extra configuration files passed using command line
282 *
283 * Returns a list of extra configuration files which were passed through
284 * command line options.
285 *
286 * @return std::vector<string>
287 */
288 const std::vector<std::string> &get_extra_config_files() const noexcept {
289 return extra_config_files_;
290 }
291
292#if !defined(_MSC_VER) && !defined(UNIT_TESTS)
293 // MSVC produces different symbols for private vs public methods, which mean
294 // the #define private public trick for unit-testing private methods doesn't
295 // work. Thus, we turn private methods public in Windows.
296 private:
297#endif
298
299 /** @brief Initializes the MySQL Router application
300 *
301 * Initialized the MySQL Router application by
302 *
303 * * setting the default configuration files,
304 * * loading the command line options,
305 * * processing the given command line arguments,
306 * * and finding all the usable configuration files.
307 *
308 * The command line options are passed using the `arguments`
309 * argument. It should be a vector of strings. For example, to start
310 * MySQL Router using the `main()` functions `argc` and `argv`
311 * arguments:
312 *
313 * MySQLRouter router(vector<string>({argv + 1, argv + argc}));
314 * router.start();
315 *
316 * @internal
317 * We do not need the first command line argument, argv[0] since we do not
318 * use it.
319 * @endinternal
320 *
321 * @param program_name path to the executable.
322 * @param arguments command line arguments as vector of strings
323 */
324 virtual void init(const std::string &program_name,
325 const std::vector<std::string> &arguments);
326
327 /** @brief Prepares a command line option
328 *
329 * Prepares command line options for the MySQL Router `mysqlrouter`
330 * application.
331 *
332 * @internal
333 * Currently, to add options to the command line, you need to add it to the
334 * `prepare_command_options`-method using `CmdArgHandler::add_option()`.
335 * @endinternal
336 */
337 void prepare_command_options() noexcept;
338
339 /** @brief Process command line options
340 *
341 * Processes command line options for the MySQL Router `mysqlrouter`
342 * application.
343 */
345 const std::vector<std::string> &arguments); // throws std::runtime_error
346
347 /** @brief Finds all valid configuration files
348 *
349 * Finds all valid configuration files from the list of default
350 * configuration file locations.
351 *
352 * An exception of type `std::runtime_error` is thrown when no valid
353 * configuration file was found.
354 *
355 * @return returns a list of valid configuration file locations
356 *
357 */
358 std::vector<std::string> check_config_files();
359
360 /** @brief Shows the help screen on the console
361 *
362 * Shows the help screen on the console including
363 *
364 * * copyright and trademark notice,
365 * * command line usage,
366 * * default configuration file locations,
367 * * and options with their descriptions.
368 *
369 * Users would use the command line option `--help`:
370 *
371 * shell> mysqlrouter --help
372 */
373 void show_help();
374
375 /** @brief Saves the selected command line option in the internal options
376 * array after verifying it's value not empty and the router is doing
377 * bootstrap.
378 *
379 * Throws: std::runtime_error
380 */
381 void save_bootstrap_option_not_empty(const std::string &option_name,
382 const std::string &save_name,
383 const std::string &option_value);
384
385 /**
386 * @brief verify that bootstrap option (--bootstrap or -B) was given by user.
387 *
388 * @throw std::runtime_error if called in non-bootstrap mode.
389 */
390 void assert_bootstrap_mode(const std::string &option_name) const;
391
392 /**
393 * @brief verify that option given by user is not used with bootstrap option
394 * (--bootstrap or -B).
395 *
396 * @throw std::runtime_error if called in bootstrap mode.
397 */
398 void assert_not_bootstrap_mode(const std::string &option_name) const;
399
400 /**
401 * @brief verify that option given by user is an integer value in the given
402 * range.
403 *
404 * @throw std::out_of_range - option not in [min, max] range
405 * @throw std::invalid_argument - not a valid integer
406 */
407 void assert_option_value_in_range(const std::string &option_value,
408 const int min, const int max) const;
409
410 /** @brief Shows command line usage and option description
411 *
412 * Shows command line usage and all available options together with their
413 * description. It is possible to prevent the option listing by setting the
414 * argument `include_options` to `false`.
415 *
416 * @internal
417 * This method is used by the `MySQLRouter::show_help()`. We keep a separate
418 * method so we could potentionally show the usage in other places or using
419 * different option combinations, for example after an error.
420 * @endinternal
421 *
422 * @param include_options bool whether we show the options and descriptions
423 */
424 void show_usage(bool include_options) noexcept;
425
426 /* @overload */
427 void show_usage() noexcept;
428
429 /** @brief Sets default configuration file locations
430 *
431 * Sets the default configuration file locations based on information
432 * found in the locations argument. The locations should be provided
433 * as a semicolon separated list.
434 *
435 * The previous loaded locations are first removed. If not new locations
436 * were provider (if locations argument is empty), then no configuration
437 * files will be available.
438 *
439 * Locations can include environment variable placeholders. These
440 * placeholders are replaced using the provided name. For example, user Jane
441 * executing MySQL Router:
442 *
443 * /opt/ENV{USER}/etc becomes /opt/jane/etc
444 *
445 * If the environment variable is not available, for example if
446 * MYSQL_ROUTER_HOME was not set before starting MySQL Router, every location
447 * using this environment variable will be ignored.
448 *
449 * @param locations a char* with semicolon separated file locations
450 */
451 void set_default_config_files(const char *locations) noexcept;
452
453 void bootstrap(const std::string &program_name,
454 const std::string &metadata_server_uri);
455
456 /*
457 * @brief returns id of the router.
458 *
459 * @throw bad_section
460 */
461 uint32_t get_router_id(mysql_harness::Config &config);
462
463 void init_keyring(mysql_harness::Config &config);
464
465 void init_dynamic_state(mysql_harness::Config &config);
466
467 /**
468 * @brief Initializes keyring using master-key-reader and master-key-writer.
469 *
470 * @throw MasterKeyReadError
471 */
473
474 /**
475 * @brief Initializes keyring using master key file.
476 *
477 * @throw std::runtime_error
478 */
480
481 /**
482 * @brief Initializes keyring using password read from STDIN.
483 *
484 * @throw std::runtime_error
485 */
487
488 // throws std::runtime_error
489 void init_loader(mysql_harness::LoaderConfig &config);
490
491 // throws std::runtime_error
492 mysql_harness::LoaderConfig *make_config(
493 const std::map<std::string, std::string> params,
494 const std::vector<std::string> &config_files);
495
496 std::map<std::string, std::string> get_default_paths() const;
497
498 /** @brief Tuple describing the MySQL Router version, with major, minor and
499 * patch level **/
500 std::tuple<const uint8_t, const uint8_t, const uint8_t> version_;
501
502 /** @brief Vector with default configuration file locations as strings **/
504 /** @brief Vector with extra configuration file locations as strings **/
506 /** @brief Vector with configuration files passed through command line
507 * arguments **/
509 /** @brief PID file location **/
511 bool pid_file_created_{false};
512
513 /** @brief CmdArgHandler object handling command line arguments **/
515 /** @brief Harness loader **/
516 std::unique_ptr<mysql_harness::Loader> loader_;
517 /** @brief Whether the MySQLRouter can start or not **/
519 /** @brief Whether we are showing information on command line, for example,
520 * using --help or --version **/
522 /**
523 * @brief Value of the argument passed to the -B or --bootstrap
524 * command line option for bootstrapping.
525 */
526 std::string bootstrap_uri_;
527 /**
528 * @brief Valueof the argument passed to the --directory command line option
529 */
531 /**
532 * @brief key/value map of additional configuration options for bootstrap
533 */
534 std::map<std::string, std::string> bootstrap_options_;
535
536 /**
537 * @brief key/list-of-values map of additional configuration options for
538 * bootstrap
539 */
540 std::map<std::string, std::vector<std::string>> bootstrap_multivalue_options_;
541
542 /**
543 * Path to origin of executable.
544 *
545 * This variable contain the directory that the executable is
546 * running from.
547 */
549
551
552 std::ostream &out_stream_;
553 std::ostream &err_stream_;
554
555 bool core_file_{false};
556
557#ifndef _WIN32
558 /** @brief Value of the --user parameter given on the command line if router
559 * is launched in bootstrap mode **/
560 std::string user_cmd_line_;
561
562 /** @brief Value of the --user parameter given on the command line. It is used
563 *to buffer the value of --user parameter till all command line parameters are
564 *parsed. If router is launched in bootstrap mode, then username_ is copied to
565 *user_cmd_line_, otherwise it is copied to bootstrap_options_["user"]
566 **/
567 std::string username_;
568
569 /** @brief Pointer to the object to be used to perform system specific
570 * user-related operations **/
572#endif
573
575
576#ifdef FRIEND_TEST
577 FRIEND_TEST(Bug24909259, PasswordPrompt_plain);
578 FRIEND_TEST(Bug24909259, PasswordPrompt_keyed);
579#endif
580};
581
582class silent_exception : public std::exception {
583 public:
584 silent_exception() : std::exception() {}
585};
586
587#endif // ROUTER_MYSQL_ROUTER_INCLUDED
Defining the commandline argument handler class CmdArgHandler.
Handles command line arguments.
Definition: arg_handler.h:141
KeyringInfo class encapsulates loading and storing master key using master-key-reader and master-key-...
Definition: keyring_info.h:76
Manage the MySQL Router application.
Definition: router_app.h:75
std::ostream & out_stream_
Definition: router_app.h:552
void assert_not_bootstrap_mode(const std::string &option_name) const
verify that option given by user is not used with bootstrap option (–bootstrap or -B).
Definition: router_app.cc:873
void stop()
Stop and cleanup the MySQL Router application.
Definition: router_app.cc:776
void init_dynamic_state(mysql_harness::Config &config)
Definition: router_app.cc:350
const std::vector< std::string > & get_extra_config_files() const noexcept
Gets list of extra configuration files passed using command line.
Definition: router_app.h:288
bool showing_info_
Whether we are showing information on command line, for example, using –help or –version.
Definition: router_app.h:521
void prepare_command_options() noexcept
Prepares a command line option.
Definition: router_app.cc:936
uint32_t get_router_id(mysql_harness::Config &config)
Definition: router_app.cc:308
std::vector< std::string > check_config_files()
Finds all valid configuration files.
Definition: router_app.cc:814
std::string get_package_name() noexcept
void show_help()
Shows the help screen on the console.
Definition: router_app.cc:1924
bool core_file_
Definition: router_app.h:555
std::string bootstrap_uri_
Value of the argument passed to the -B or –bootstrap command line option for bootstrapping.
Definition: router_app.h:526
std::map< std::string, std::vector< std::string > > bootstrap_multivalue_options_
key/list-of-values map of additional configuration options for bootstrap
Definition: router_app.h:540
void parse_command_options(const std::vector< std::string > &arguments)
Process command line options.
Definition: router_app.cc:210
std::string user_cmd_line_
Value of the –user parameter given on the command line if router is launched in bootstrap mode.
Definition: router_app.h:560
std::string username_
Value of the –user parameter given on the command line.
Definition: router_app.h:567
std::vector< std::string > extra_config_files_
Vector with extra configuration file locations as strings.
Definition: router_app.h:505
virtual void init(const std::string &program_name, const std::vector< std::string > &arguments)
Initializes the MySQL Router application.
Definition: router_app.cc:222
void init_keyring(mysql_harness::Config &config)
Definition: router_app.cc:324
mysql_harness::LoaderConfig * make_config(const std::map< std::string, std::string > params, const std::vector< std::string > &config_files)
Definition: router_app.cc:481
void assert_option_value_in_range(const std::string &option_value, const int min, const int max) const
verify that option given by user is an integer value in the given range.
Definition: router_app.cc:880
bool pid_file_created_
Definition: router_app.h:511
std::map< std::string, std::string > bootstrap_options_
key/value map of additional configuration options for bootstrap
Definition: router_app.h:534
std::map< std::string, std::string > get_default_paths() const
Definition: router_app.cc:409
void init_keyring_using_external_facility(mysql_harness::Config &config)
Initializes keyring using master-key-reader and master-key-writer.
Definition: router_app.cc:363
KeyringInfo keyring_info_
Definition: router_app.h:550
void save_bootstrap_option_not_empty(const std::string &option_name, const std::string &save_name, const std::string &option_value)
Saves the selected command line option in the internal options array after verifying it's value not e...
Definition: router_app.cc:857
const std::vector< std::string > & get_default_config_files() const noexcept
Gets list of default configuration files.
Definition: router_app.h:266
std::unique_ptr< mysql_harness::Loader > loader_
Harness loader.
Definition: router_app.h:516
std::string pid_file_path_
PID file location.
Definition: router_app.h:510
void init_keyring_using_prompted_password()
Initializes keyring using password read from STDIN.
Definition: router_app.cc:381
CmdArgHandler arg_handler_
CmdArgHandler object handling command line arguments.
Definition: router_app.h:514
std::string get_version() noexcept
Returns the MySQL Router version as string.
Definition: router_app.cc:805
mysql_harness::Path origin_
Path to origin of executable.
Definition: router_app.h:548
mysql_harness::SignalHandler signal_handler_
Definition: router_app.h:574
void assert_bootstrap_mode(const std::string &option_name) const
verify that bootstrap option (–bootstrap or -B) was given by user.
Definition: router_app.cc:867
std::vector< std::string > default_config_files_
Vector with default configuration file locations as strings.
Definition: router_app.h:503
const std::vector< std::string > & get_config_files() const noexcept
Gets list of configuration files passed using command line.
Definition: router_app.h:277
void init_keyring_using_master_key_file()
Initializes keyring using master key file.
Definition: router_app.cc:376
std::string bootstrap_directory_
Valueof the argument passed to the –directory command line option.
Definition: router_app.h:530
void start()
Starts the MySQL Router application.
Definition: router_app.cc:519
MySQLRouter()
Default constructor.
Definition: router_app.h:87
std::vector< std::string > config_files_
Vector with configuration files passed through command line arguments.
Definition: router_app.h:508
virtual ~MySQLRouter()=default
void show_usage() noexcept
Definition: router_app.cc:2109
static void init_main_logger(mysql_harness::LoaderConfig &config, bool raw_mode=false, bool use_os_log=false)
Initialize main logger.
Definition: router_app.cc:415
std::ostream & err_stream_
Definition: router_app.h:553
void set_default_config_files(const char *locations) noexcept
Sets default configuration file locations.
Definition: router_app.cc:787
mysqlrouter::SysUserOperationsBase * sys_user_operations_
Pointer to the object to be used to perform system specific user-related operations.
Definition: router_app.h:571
void init_loader(mysql_harness::LoaderConfig &config)
Definition: router_app.cc:507
bool can_start_
Whether the MySQLRouter can start or not.
Definition: router_app.h:518
std::tuple< const uint8_t, const uint8_t, const uint8_t > version_
Tuple describing the MySQL Router version, with major, minor and patch level.
Definition: router_app.h:500
std::string get_version_line() noexcept
Returns string version details.
Definition: router_app.cc:807
Configuration file handler for the loader.
Definition: loader_config.h:46
Class representing a path in a file system.
Definition: filesystem.h:63
Definition: signal_handler.h:41
Base class to allow multiple SysUserOperations implementations.
Definition: sys_user_operations.h:45
static SysUserOperations * instance()
Definition: sys_user_operations.cc:49
Definition: router_app.h:582
silent_exception()
Definition: router_app.h:584
Definition: bootstrap.cc:70
Definition: common.h:42
Definition: dim.h:358
Definition: gcs_xcom_synode.h:64
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2874
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2892
static const size_t kHelpScreenWidth
Definition: router_app.h:49
static const size_t kHelpScreenIndent
Definition: router_app.h:50