MySQL 8.4.0
Source Code Documentation
mysql_harness::Loader Class Reference

#include <loader.h>

Classes

class  PluginInfo
 Holds plugin's API call information. More...
 

Public Member Functions

 Loader (std::string program, LoaderConfig &config)
 Constructor for Loader. More...
 
 Loader (const Loader &)=delete
 
Loaderoperator= (const Loader &)=delete
 
 ~Loader ()
 Destructor. More...
 
std::list< Config::SectionKeyavailable () const
 Fetch available plugins. More...
 
void start ()
 Initialize and start all loaded plugins. More...
 
LoaderConfigget_config ()
 Get reference to configuration object. More...
 
std::vector< std::string > & waitable_services ()
 service names to wait on. More...
 
const std::vector< std::string > & waitable_services () const
 service names to wait on. More...
 
void after_all_started (std::function< void()> &&func)
 set a function that's called after all plugins have been started. More...
 
void after_first_finished (std::function< void()> &&func)
 set a function that's called after the first plugin exited. More...
 
template<size_t N>
void register_supported_app_options (const std::array< std::string_view, N > &options)
 Register global configuration options supported by the application. More...
 
void register_expose_app_config_callback (std::function< void(const bool, const ConfigSection &)> clb)
 Register a callback that the Loader will call when exposing of the whole configuration is requested. More...
 
void load_all ()
 Load all the configured plugins. More...
 
void expose_config_all (const bool initial)
 Request the application and all the configured plugins to expose their configuration in the DyncamicConfig object. More...
 

Private Types

enum class  Status { UNVISITED , ONGOING , VISITED }
 
enum class  Stage {
  Unset , Loading , Initializing , Starting ,
  Running , Stopping , Deinitializing , Unloading
}
 Flags progress of Loader. More...
 
using PluginMap = std::map< std::string, PluginInfo >
 

Private Member Functions

const Plugin * load_from (const std::string &plugin_name, const std::string &library_name)
 Load the named plugin from a specific library. More...
 
const Plugin * load (const std::string &plugin_name)
 
const Plugin * load (const std::string &plugin_name, const std::string &key)
 Load the named plugin and all dependent plugins. More...
 
void setup_info ()
 
std::exception_ptr run ()
 
std::exception_ptr init_all ()
 
void start_all ()
 
std::exception_ptr main_loop ()
 wait for shutdown signal or plugins exit. More...
 
std::exception_ptr stop_and_wait_all ()
 
std::exception_ptr stop_all ()
 
std::exception_ptr deinit_all ()
 
void unload_all ()
 
size_t external_plugins_to_load_count ()
 
bool topsort ()
 Topological sort of all plugins and their dependencies. More...
 
bool visit (const std::string &name, std::map< std::string, Status > *seen, std::list< std::string > *order)
 
void spawn_signal_handler_thread ()
 
void check_config_options_supported ()
 Checks if all the options in the configuration fed to the Loader are supported. More...
 
void check_default_config_options_supported ()
 Checks if all the options in the section [DEFAULT] in the configuration fed to the Loader are supported. More...
 

Private Attributes

LoaderConfigconfig_
 Configuration sections for all plugins. More...
 
PluginMap plugins_
 Map of all successfully-loaded plugins (without key name). More...
 
std::map< const ConfigSection *, std::shared_ptr< PluginFuncEnv > > plugin_start_env_
 Map of all {plugin instance -> plugin start() PluginFuncEnv} objects. More...
 
PluginThreads plugin_threads_
 active plugin threads. More...
 
std::list< std::string > order_
 Initialization order. More...
 
std::string logging_folder_
 
std::string plugin_folder_
 
std::string runtime_folder_
 
std::string config_folder_
 
std::string data_folder_
 
std::string program_
 
AppInfo appinfo_
 
std::mutex signal_thread_ready_m_
 
std::condition_variable signal_thread_ready_cond_
 
bool signal_thread_ready_ {false}
 
std::thread signal_thread_
 
std::vector< std::string > supported_app_options_
 
std::vector< std::string > waitable_services_
 
std::function< void()> after_all_started_
 
std::function< void()> after_first_finished_
 
std::function< void(const bool, const ConfigSection &)> expose_app_config_clb_
 

Detailed Description

Introduction

The loader class is responsible for managing the life-cycle of plugins in the harness. Each plugin goes through seven steps in the life-cycle, of which steps #2, #3, #5 and #6 are optional:

  1. Loading
  2. Initialization
  3. Starting
  4. Running
  5. Stopping
  6. Deinitialization
  7. Unloading

Overview of Life-cycle Steps

1. Loading

When loading, the plugin is loaded using the dynamic library support available on the operating system. Symbols are evaluated lazily (for example, the RTLD_LAZY flag is used for dlopen) to allow plugins to be loaded in any order. The symbols that are exported by the plugin are made available to all other plugins loaded (flag RTLD_GLOBAL to dlopen).

As part of the loading procedure, the plugin structure (see Plugin class) is fetched from the module and used for the four optional steps below.

2. Initialization

After all the plugins are successfully loaded, each plugin is given a chance to perform initialization. This step is only executed if the plugin structure defines an init function. Note that it is guaranteed that the init function of a plugin is called after the init function of all plugins it requires have been called. The list of these dependencies is specified via requires field of the Plugin struct.

Note
if some plugin init() function fails, any plugin init() functions schedulled to run after will not run, and harness will proceed straight to deinitialization step, bypassing calling start() and stop() functions.

3. Starting

After all plugins have been successfully initialized, a thread is created for each plugin that has a non-NULL start field in the plugin structure. The threads are started in an arbitrary order, so you have to be careful about not assuming that, for example, other plugins required by the plugin have started their thread. If the plugin does not define a start function, no thread is created. There is a "running" flag associated with each such thread; this flag is set when the thread starts but before the start function is called. If necessary, the plugin can spawn more threads using standard C++11 thread calls, however, these threads should not call harness API functions.

4. Running

After starting all plugins (that needed to be started), the harness will enter the running step. This is the "normal" phase, where the application spends most of its lifetime (application and plugins service requests or do whatever it is they do). Harness will remain in this step until one of two things happen:

  1. shutdown signal is received by the harness
  2. one of the plugins exits with error

When one of these two events occurs, harness progresses to the next step.

5. Stopping

In this step, harness "tells" plugins running start() to exit this function by clearing the "running" flag. It also invokes stop() function for all plugins that provided it. It then waits for all running plugin threads to exit.

Note
under certain circumstances, stop() may overlap execution with start(), or even be called before start().

6. Deinitialization

After all threads have stopped, regardless of whether they stopped with an error or not, the plugins are deinitialized in reverse order of initialization by calling the function in the deinit field of the Plugin structure. Regardless of whether the deinit() functions return an error or not, all plugins schedulled for deinitialisation will be deinitialized.

Note
for any init() functions that failed, deinit() functions will not run.
plugins may have a deinit() function despite not having a corresponding init(). In such cases, the missing init() is treated as if it existed and ran successfully.

7. Unloading

After a plugin has deinitialized, it can be unloaded. It is guaranteed that no module is unloaded before it has been deinitialized.

Note
This step is currently unimplemented - meaning, it does nothing. The plugins will remain loaded in memory until the process shuts down. This makes no practical difference on application behavior at present, but might be needed if Harness gained ability to reload plugins in the future.

Behavior Diagrams

Previous section described quickly each step of the life-cycle process. In this section, two flow charts are presented which show the operation of all seven steps. First shows a high-level overview, and the second shows all 7 life-cycle steps in more detail. Discussion of details follows in the following sections.

Some points to keep in mind while viewing the diagrams:

  • diagrams describe code behavior rather than implementation. So for example:
    • pseudocode does not directly correspond 1:1 to real code. However, it behaves exactly like the real code.
  • seven life-cycle functions shown are actual functions (Loader's methods, to be more precise)
    • load_all(), init_all(), start_all(), main_loop(), stop_all(), deinit_all() are implemented functions (first 6 steps of life-cycle)
    • unload_all() is the 7th step of life-cycle, but it's currently unimplemented
  • when plugin functions exit with error, they do so by calling set_error() before exiting
  • some things are not shown to keep the diagram simple:
    • first error returned by any of the 7 life-cycle functions is saved and passed at the end of life-cycle flow to the calling code

Overview

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\                                                                              \
\   START                                                                      \
\     |                                                                        \
\     |                                                                        \
\     |                                                                        \
\     V                                                                        \
\   [load_all()]                                                               \
\     |                                                                        \
\     V                                                                        \
\   <LOAD_OK?>                                                                 \
\     |   |                                                                    \
\ +---N   Y                                                                    \
\ |       |                                                                    \
\ |       v                                                                    \
\ | [init_all()]                                                               \
\ |   |                                                                        \
\ |   v                                                                        \
\ | <INIT_OK?>                                         (  each plugin runs  )  \
\ |   |   |                                            (in a separate thread)  \
\ |   N   Y                                                                    \
\ |   |   |                                             [plugin[1]->start()]   \
\ |   |   v             start plugin threads            [plugin[2]->start()]   \
\ |   | [start_all()] - - - - - - - - - - - - - - - - ->[    ..      ..    ]   \
\ |   |   |                                             [    ..      ..    ]   \
\ |   |   |  + - - - - - - - - - - - - - - - - - - - - -[plugin[n]->start()]   \
\ |   |   |            notification when each                     ^            \
\ |   |   |  |           thread terminates                                     \
\ |   |   |                                                       |            \
\ |   |   |  |                                                     stop plugin \
\ |   |   |                                                       |  threads   \
\ |   |   |  |                                                                 \
\ |   |   |                                                       |            \
\ |   |   v  v                                                                 \
\ |   | [main_loop()]= call ==>[stop_all()] - - - - - - - - - - - +            \
\ |   |   |                                                                    \
\ |   |   |        \                                                           \
\ |   *<--+         \                                                          \
\ |   |              \__ waits for all plugin                                  \
\ |   v                  threads to terminate                                  \
\ | [deinit_all()]                                                             \
\ |   |                                                                        \
\ |   v                                                                        \
\ +-->*                                                                        \
\     |                                                                        \
\     v                                                                        \
\   [unload_all()]                                                             \
\     |                                                                        \
\     |         \                                                              \
\     |          \                                                             \
\     v           \__ currently not implemented                                \
\    END                                                                       \
\                                                                              \
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Detailed View

            START
              |
              |
              v
\\\\ load_all() \\\\\\\\\\\\\\\\\\\\\\
\                                    \
\  LOAD_OK = true                    \
\  foreach plugin:                   \
\    load plugin                     \
\    if (exit_status != ok):         \
\      LOAD_OK = false               \
\      break loop                    \
\                                    \
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
              |
              |
              v
            <LOAD_OK?>
              |   |
              Y   N----> unload_all() (see further down)
              |
              |
\\\\\\\\\\\\\\|\\\ init_all() \\\\\\\\\\\\\\\\\
\             |                               \
\             v                               \
\           [INIT_OK = true, i = 1]           \
\             |                               \
\             v                               \
\     +----><plugin[i] exists?>               \
\     |       |   |                           \
\   [i++]     Y   N---------------------+     \
\     ^       |                         |     \
\     |       |                         |     \
\     |       v                         |     \
\     |     <plugin[i] has init()?>     |     \
\     |       |   |                     |     \
\     |       N   Y---+                 |     \
\     |       |       |                 |     \
\     |       |       |                 |     \
\     |       |       v                 |     \
\     |       |     [plugin[i]->init()] |     \
\     |       |       |                 |     \
\     |       |       |                 |     \
\     |       |       |                 |     \
\     |       |       |                 |     \
\     |       |       v                 |     \
\     |       |     <exit ok?>          |     \
\     |       v       |   |             |     \
\     +-------*<------Y   N             |     \
\                         |             |     \
\                         |             |     \
\                         v             |     \
\                   [INIT_OK = false]   |     \
\                     |                 |     \
\                     v                 |     \
\                     *<----------------+     \
\                     |                       \
\                     v                       \
\                   [LAST_PLUGIN = i-1]       \
\                     |                       \
\\\\\\\\\\\\\\\\\\\\\\|\\\\\\\\\\\\\\\\\\\\\\\\
                      |
                      |
                      v
                    <INIT_OK?>
                      |   |
                      Y   N----> deinit_all() (see further down)
                      |
                      |
                      v
\\\\ start_all() \\\\\\\\\\\\\\\\\\\\\\\\\
\                                        \
\   for i = 1 to LAST_PLUGIN:            \
\     if plugin[i] has start():          \  start start() in new thread
\       new thread(plugin[i]->start()) - - - - - - - - - - - - - - - - +
\                                        \
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\                             |
                      |
                      |                                                |
    +-----------------+
    |                                                                  |
\\\\|\\\ main_loop() \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \\\\\\\\
    |                                                                  |       \
    v                                                                          \
+-->*                                                                  |       \
|   |                                                                          \
|   v                                                                  |       \
| <any plugin threads running?>                                                \
|   |   |                                                              |       \
|   N   Y---+                                                                  \
|   |       |                                                          |       \
|   |     <shutdown signal received && stop_all() not called yet?>             \
|   |       |   |                                                      |       \
|   |       N   Y                                                              \
|   |       |    == call ==>[stop_all()]- - - - - - - - - - - - - +    |       \
|   |       |   |                     tell (each) start() to exit              \
|   |       *<--+                                                 |    |       \
|   |       |                                                                  \
|   |       |                                                     v    v       \
|   |       |                                             [plugin[1]->start()] \
|   |       v                 (one) plugin thread exits   [plugin[2]->start()] \
|   |     [wait for (any)]<- - - - - - - - - - - - - - - -[    ..      ..    ] \
|   |     [ thread exit  ]                                [    ..      ..    ] \
|   |       |                                             [plugin[n]->start()] \
|   |       |                                                     ^            \
|   |       |                                                                  \
|   |       v                                                     |            \
|   |     <thread exit ok?>                                                    \
|   |       |   |                                                 |            \
|   |       Y   N---+                                                          \
|   |       |       |                                             |            \
|   |       |       v                                                          \
|   |       |     <stop_all() called already?>                    |            \
|   |       v       |   |                                                      \
|   |       *<------Y   N                                    tell (each)       \
|   |       |            = call ==+                        start() to exit     \
|   |       |           |         |                               |            \
|   |       v           |         |                                            \
+---|-------*<----------+         *==>[stop_all()]- - - - - - - - +            \
    |                             |                                            \
    |                             |        |                                   \
    v                             |        |                                   \
  <stop_all() called already?>    |        |                                   \
    |   |                         |        |                                   \
    Y   N                         |        |                                   \
    |    == call =================+        |                                   \
    |   |                                  |                                   \
    *---+                                  |                                   \
    |                                      |                                   \
\\\\|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    |                                      |
    |                                      |
    v                                      |
    *<---- init_all() (if !INIT_OK)        |
    |                                      |
    |                                      |
    v                                      |
\\\\ deinit_all() \\\\\\\\\\\\\\\\\\\\     |
\                                    \     |
\  for i = LAST_PLUGIN to 1:         \     |
\    if plugin[i] has deinit():      \     |
\      plugin[i]->deinit()           \     |
\      if (exit_status != ok):       \     |
\        # ignore error              \     |
\                                    \     |
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\     |
    |                                      |
    |                                      |
    v                                      |
    *<---- load_all() (if !LOAD_OK)        |
    |                                      |
    v                                      |
\\\\ unload_all() \\\\\\\\\\\\\\\\\\\\     |
\                                    \     |
\  no-op (currently unimplemented)   \     |
\                                    \     |
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\     |
    |                                      |
    |                                      |
    v                                      /
   END                                    /
                                         /
                                        /
                                       /                  (  each plugin runs  )
                                      /                   (in a separate thread)
\\\\ stop_all() \\\\\\\\\\\\\\\\\\\\\\  run_flag == false
\                                    \    tells start()    [plugin[1]->start()]
\  for i = 1 to LAST_PLUGIN:         \      to exit        [plugin[2]->start()]
\    run_flag[i] = false - - - - - - - - - - - - - - - - ->[    ..      ..    ]
\    if plugin[i] has stop():        \                     [    ..      ..    ]
\      plugin[i]->stop()             \                     [    ..      ..    ]
\      if (exit_status != ok):       \                     [plugin[n]->start()]
\        # ignore error              \
\                                    \
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Discussion

Persistence (definition)

Before continuing, we need to define the word "persist", used later on. When we say "persist", we'll mean the opposite of "exit". So when we say a function or a thread persists, it means that it's not returning/exiting, but instead is running some forever-loop or is blocked on something, etc. What it's doing exactly doesn't matter, what matters, is that it hasn't terminated but "lives on" (in case of a function, to "persist" means the same as to "block", but for threads that might sound confusing, this is why we need a new word). So when we call start() in a new thread, it will either run and keep running (thread will persist), or it will run briefly and return (thread will exit). In short, "to persist" means the opposite of "to finish running and exit".

Plugin API functions

Each plugin can define none, any or all of the following 4 callbacks. They're function pointers, that can be null if not implemented. They're typically called in the order as listed below (under certain circumstances, stop() may overlap execution with start(), or even be called before start()).

  • init() – called inside of main thread
  • start() – main thread creates a new thread, then calls this
  • stop() – called inside of main thread
  • deinit() – called inside of main thread

Starting and Stopping: Start()

It is typical to implement start function in such a way that it will "persist" (i.e. it will run some forever-loop processing requests rather than exit briefly after being called). In such case, Harness must have a way to terminate it during shutdown operation.

For this purpose, Harness exposes a boolean "running" flag to each plugin, which serves as means to communicate the need to shutdown; it is read by is_running() function. This function should be routinely polled by plugin's start() function to determine if it should shut down, and once it returns false, plugin start() should terminate as soon as possible. Failure to terminate will block Harness from progressing further in its shutdown procedure, resulting in application "hanging" during shutdown. Typically, start() would be implemented more-or-less like so:

void start()
{

run-once code

  while (is_running())
  {

forever-loop code }

clean-up code }

There is also an alternative blocking function available, wait_for_stop(), should that be better suited for the particular plugin design. Instead of quickly returning a boolean flag, it will block (with an optional timeout) until Harness flags to shut down this plugin. It is an efficient functional equivalent of:

while (is_running())
{

sleep a little or break on timeout }

When entering shutdown phase, Harness will notify all plugins to shut down via mechanisms described above. It is also permitted for plugins to exit on their own, whether due to error or intended behavior, without consulting this "running" flag. Polling the "running" flag is only needed when start() "persists" and does not normally exit until told to do so.

Also, in some designs, start() function might find it convenient to be able to set the "running" flag to false, in order to trigger its own shutdown in another piece of code. For such cases, clear_running() function is provided, which will do exactly that.

IMPORTANT! Please note that all 3 functions described above (is_running(), wait_for_stop() and clear_running()) can only be called from a thread running start() function. If start() spawns more theads, these functions CANNOT be called from them. These functions also cannot be called from the other three plugin functions (init(), stop() and deinit()).

Starting and Stopping: Stop()

During shutdown, or after plugin start() function exits (whichever comes first), plugin's stop() function will be called, if defined.

IMPORTANT: start() function runs in a different thread than stop() function. By the time stop() runs, depending on the circumstances, start() thread may or may not exist.

IMPORTANT: stop() will always be called during shutdown, regardless of whether start() exited with error, exited successfully or is still running. stop() must be able to deal with all 3 scenarios. The rationale for this design decision is given Error Handling section.

Persistence in Plugin Functions

While start() may persist, the other three functions (init(), stop() and deinit()) must obviously not persist, since they run in the main thread. Any blocking behavior exhibited in these functions (caused by a bug or otherwise) will cause the entire application to hang, as will start() that does not poll and/or honor is_running() flag.

Returning Success/Failure from Plugin Function

Harness expects all four plugin functions (init(),start(),stop()and deinit()`) to notify it in case of an error. This is done via function:

set_error(PluginFuncEnv* env, ErrorType error, const char* format, ...);

Calling this function flags that the function has failed, and passes the error type and string back to Harness. The converse is also true: not calling this function prior to exiting the function implies success. This distinction is important, because Harness may take certain actions based on the status returned by each function.

IMPORTANT! Throwing exceptions from these functions is not supported. If your plugin uses exceptions internally, that is fine, but please ensure they are handled before reaching the Harness-Plugin boundary.

Threading Concerns

For each plugin (independent of other plugins): Of the 4 plugin functions, init() runs first. It is guaranteed that it will exit before start() and stop() are called. start() and stop() can be called in parallel to each other, in any order, with their lifetimes possibly overlapping. They are guaranteed to both have exited before deinit() is called.

If any of the 4 plugin functions spawn any additional threads, Harness makes no provisions for interacting with them in any way: calling Harness functions from them is not supported in particular; also such threads should exit before their parent function finishes running.

Error Handling

NOTE: WL#9558 HLD version of this section additionally discusses design, rationale for the approach chosen, etc; look there if interested.

When plugin functions encounter an error, they are expected to signal it via set_error(). What happens next, depends on the case, but in all four cases the error will be logged automatically by the harness. Also, the first error passed from any plugin will be saved until the end of life-cycle processing, then passed down to the code calling the harness. This will allow the application code to deal with it accordingly (probably do some of its own cleaning and shut down, but that's up to the application). In general, the first error from init() or start() will cause the harness to initiate shut down procedure, while the errors from stop() and deinit() will be ignored completely (except of course for being logged and possibly saved for passing on at the end). Actions taken for each plugin function are as follows:

init() fails:

  • skip init() for remaining plugins
  • don't run any start() and stop() (proceed directly to deinitialisation)
  • run deinit() only for plugins initialiased so far (excluding the failing one), in reverse order of initialisation, and exit
  • when init() is not provided (is null), it counts as if it ran, if it would have run before the failing plugin (according to topological order)

start() fails:

  • proceed to stop all plugins, then deinit() all in reverse order of initialisation and exit. Please note that ALL plugins will be flagged to stop and have their stop() function called (not just the ones that succeeded in starting - plugin's stop() must be able to deal with such a situation)

stop() or deinit() fails:

  • log error and ignore, proceed as if it didn't happen

Member Typedef Documentation

◆ PluginMap

using mysql_harness::Loader::PluginMap = std::map<std::string, PluginInfo>
private

Member Enumeration Documentation

◆ Stage

enum class mysql_harness::Loader::Stage
strongprivate

Flags progress of Loader.

The progress always proceeds from top to bottom order in this list.

Enumerator
Unset 
Loading 
Initializing 
Starting 
Running 
Stopping 
Deinitializing 
Unloading 

◆ Status

enum class mysql_harness::Loader::Status
strongprivate
Enumerator
UNVISITED 
ONGOING 
VISITED 

Constructor & Destructor Documentation

◆ Loader() [1/2]

mysql_harness::Loader::Loader ( std::string  program,
LoaderConfig config 
)
inline

Constructor for Loader.

Parameters
programName of our program
configRouter configuration

◆ Loader() [2/2]

mysql_harness::Loader::Loader ( const Loader )
delete

◆ ~Loader()

Loader::~Loader ( )
default

Destructor.

The destructor will call dlclose() on all unclosed shared libraries.

Member Function Documentation

◆ after_all_started()

void mysql_harness::Loader::after_all_started ( std::function< void()> &&  func)
inline

set a function that's called after all plugins have been started.

See also
after_all_finished()

◆ after_first_finished()

void mysql_harness::Loader::after_first_finished ( std::function< void()> &&  func)
inline

set a function that's called after the first plugin exited.

See also
after_all_started()

◆ available()

std::list< Config::SectionKey > Loader::available ( ) const

Fetch available plugins.

Returns
List of names of available plugins.

◆ check_config_options_supported()

void Loader::check_config_options_supported ( )
private

Checks if all the options in the configuration fed to the Loader are supported.

Exceptions
std::runtime_errorif there is unsupported option in the configuration

◆ check_default_config_options_supported()

void Loader::check_default_config_options_supported ( )
private

Checks if all the options in the section [DEFAULT] in the configuration fed to the Loader are supported.

Exceptions
std::runtime_errorif there is unsupported option in the [DEFAULT] section of the configuration

◆ deinit_all()

std::exception_ptr Loader::deinit_all ( )
private

◆ expose_config_all()

void Loader::expose_config_all ( const bool  initial)

Request the application and all the configured plugins to expose their configuration in the DyncamicConfig object.

Parameters
initialif true initial configuration is to exposed, default configuration otherwise

◆ external_plugins_to_load_count()

size_t Loader::external_plugins_to_load_count ( )
private

◆ get_config()

LoaderConfig & mysql_harness::Loader::get_config ( )
inline

Get reference to configuration object.

Note
In production code we initialize Loader with LoaderConfig reference maintained by DIM, so this method will return this object.

◆ init_all()

std::exception_ptr Loader::init_all ( )
private

◆ load() [1/2]

const Plugin * Loader::load ( const std::string &  plugin_name)
private

◆ load() [2/2]

const Plugin * Loader::load ( const std::string &  plugin_name,
const std::string &  key 
)
private

Load the named plugin and all dependent plugins.

Parameters
plugin_nameName of the plugin to be loaded.
keyKey of the plugin to be loaded.
Exceptions
bad_plugin(std::runtime_error) on load error
bad_section(std::runtime_error) when section 'plugin_name' is not present in configuration
Postcondition
After the execution of this procedure, the plugin and all plugins required by that plugin will be loaded. This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

◆ load_all()

void Loader::load_all ( )

Load all the configured plugins.

◆ load_from()

const Plugin * Loader::load_from ( const std::string &  plugin_name,
const std::string &  library_name 
)
private

Load the named plugin from a specific library.

Parameters
plugin_nameName of the plugin to be loaded.
library_nameName of the library the plugin should be loaded from.
Exceptions
bad_plugin(std::runtime_error) on load error

◆ main_loop()

std::exception_ptr Loader::main_loop ( )
private

wait for shutdown signal or plugins exit.

blocks until one of the following happens:

  • shutdown signal is received
  • one plugin return an exception
  • all plugins finished
Returns
first exception returned by any of the plugins start() or stop() functions
Return values
nullptrif no exception was returned

◆ operator=()

Loader & mysql_harness::Loader::operator= ( const Loader )
delete

◆ register_expose_app_config_callback()

void mysql_harness::Loader::register_expose_app_config_callback ( std::function< void(const bool, const ConfigSection &)>  clb)
inline

Register a callback that the Loader will call when exposing of the whole configuration is requested.

This callback is supposed to expose the application-level configration options (not plugin specific ones).

Parameters
clbcallback to register that takes 2 parameters
  • bool indicating if the requested configuration is the initial one (if true) or default (false)
  • object representing default section of the current configuration

◆ register_supported_app_options()

template<size_t N>
void mysql_harness::Loader::register_supported_app_options ( const std::array< std::string_view, N > &  options)
inline

Register global configuration options supported by the application.

Will be used by the Loader to verify the [DEFAULT] options in the configuration.

Parameters
optionsarray of global options supported by the applications

◆ run()

std::exception_ptr Loader::run ( )
private

◆ setup_info()

void Loader::setup_info ( )
private

◆ spawn_signal_handler_thread()

void mysql_harness::Loader::spawn_signal_handler_thread ( )
private

◆ start()

void Loader::start ( )

Initialize and start all loaded plugins.

All registered plugins will be initialized in proper order and started (if they have a start callback).

Exceptions
firstexception that was triggered by an error returned from any plugin function.

◆ start_all()

void Loader::start_all ( )
private

◆ stop_all()

std::exception_ptr Loader::stop_all ( )
private

◆ stop_and_wait_all()

std::exception_ptr Loader::stop_and_wait_all ( )
private

◆ topsort()

bool Loader::topsort ( )
private

Topological sort of all plugins and their dependencies.

Will create a list of plugins in topological order from "top" to "bottom".

◆ unload_all()

void Loader::unload_all ( )
private

◆ visit()

bool Loader::visit ( const std::string &  name,
std::map< std::string, Status > *  seen,
std::list< std::string > *  order 
)
private

◆ waitable_services() [1/2]

std::vector< std::string > & mysql_harness::Loader::waitable_services ( )
inline

service names to wait on.

add a service name and call on_service_ready() when the service ready().

See also
on_service_ready()

◆ waitable_services() [2/2]

const std::vector< std::string > & mysql_harness::Loader::waitable_services ( ) const
inline

service names to wait on.

See also
on_service_ready()

Member Data Documentation

◆ after_all_started_

std::function<void()> mysql_harness::Loader::after_all_started_
private

◆ after_first_finished_

std::function<void()> mysql_harness::Loader::after_first_finished_
private

◆ appinfo_

AppInfo mysql_harness::Loader::appinfo_
private

◆ config_

LoaderConfig& mysql_harness::Loader::config_
private

Configuration sections for all plugins.

◆ config_folder_

std::string mysql_harness::Loader::config_folder_
private

◆ data_folder_

std::string mysql_harness::Loader::data_folder_
private

◆ expose_app_config_clb_

std::function<void(const bool, const ConfigSection &)> mysql_harness::Loader::expose_app_config_clb_
private

◆ logging_folder_

std::string mysql_harness::Loader::logging_folder_
private

◆ order_

std::list<std::string> mysql_harness::Loader::order_
private

Initialization order.

◆ plugin_folder_

std::string mysql_harness::Loader::plugin_folder_
private

◆ plugin_start_env_

std::map<const ConfigSection *, std::shared_ptr<PluginFuncEnv> > mysql_harness::Loader::plugin_start_env_
private

Map of all {plugin instance -> plugin start() PluginFuncEnv} objects.

Initially these objects are created in Loader::start_all() and then kept around until the end of Loader::stop_all(). At the time of writing, PluginFuncEnv objects for remaining plugin functions (init(), stop() and deinit()) are not required to live beyond their respective functions calls, and are therefore created on stack (automatic variables) as needed during those calls.

◆ plugin_threads_

PluginThreads mysql_harness::Loader::plugin_threads_
private

active plugin threads.

◆ plugins_

PluginMap mysql_harness::Loader::plugins_
private

Map of all successfully-loaded plugins (without key name).

◆ program_

std::string mysql_harness::Loader::program_
private

◆ runtime_folder_

std::string mysql_harness::Loader::runtime_folder_
private

◆ signal_thread_

std::thread mysql_harness::Loader::signal_thread_
private

◆ signal_thread_ready_

bool mysql_harness::Loader::signal_thread_ready_ {false}
private

◆ signal_thread_ready_cond_

std::condition_variable mysql_harness::Loader::signal_thread_ready_cond_
private

◆ signal_thread_ready_m_

std::mutex mysql_harness::Loader::signal_thread_ready_m_
private

◆ supported_app_options_

std::vector<std::string> mysql_harness::Loader::supported_app_options_
private

◆ waitable_services_

std::vector<std::string> mysql_harness::Loader::waitable_services_
private

The documentation for this class was generated from the following files: