MySQL  8.0.17
Source Code Documentation
dynamic_loader.h
Go to the documentation of this file.
1 /* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6 
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef MYSQL_SERVER_DYNAMIC_LOADER_H
24 #define MYSQL_SERVER_DYNAMIC_LOADER_H
25 
29 #include <map>
30 #include <memory>
31 #include <set>
32 
33 #include "c_string_less.h"
35 #include "rwlock_scoped_lock.h"
36 
37 typedef std::map<const char *, std::unique_ptr<mysql_component>, c_string_less>
39 
40 /**
41  A class with an implementation of the Dynamic Loader Service.
42 */
44  typedef std::unordered_map<my_string,
47 
48  /* contain the actual fields definitions */
51 
52  public:
53  /**
54  Initializes loader for usage. Initializes RW lock, all other structures
55  should be empty. Shouldn't be called multiple times.
56  */
57  static void init();
58  /**
59  De-initializes loader. De-initializes RW lock, all other structures
60  doesn't require any action.
61  */
62  static void deinit();
63 
64  public: /* Service Implementations */
65  /**
66  Loads specified group of Components by URN, initializes them and
67  registers all Service Implementations present in these Components.
68  Assures all dependencies will be met after loading specified Components.
69  The dependencies may be circular, in such case it's necessary to specify
70  all Components on cycle to load in one batch. From URNs specified the
71  scheme part of URN (part before "://") is extracted and used to acquire
72  Service Implementation of scheme Component loader Service for specified
73  scheme.
74 
75  @param urns List of URNs of Components to load.
76  @param component_count Number of Components on list to load.
77  @return Status of performed operation
78  @retval false success
79  @retval true failure
80  */
81 
82  static DEFINE_BOOL_METHOD(load, (const char *urns[], int component_count));
83  /**
84  Unloads specified group of Components by URN, deinitializes them and
85  unregisters all Service Implementations present in these Components.
86  Assumes, thous does not check it, all dependencies of not unloaded
87  Components will still be met after unloading specified Components.
88  The dependencies may be circular, in such case it's necessary to specify
89  all Components on cycle to unload in one batch. From URNs specified the
90  scheme part of URN (part before "://") is extracted and used to acquire
91  Service Implementation of scheme Component loader Service for specified
92  scheme. URN specified should be identical to ones specified in load()
93  method, i.e. all letters must have the same case.
94 
95  @param urns List of URNs of Components to unload.
96  @param component_count Number of Components on list to unload.
97  @return Status of performed operation
98  @retval false success
99  @retval true failure
100  */
101 
102  static DEFINE_BOOL_METHOD(unload, (const char *urns[], int component_count));
103 
104  typedef std::pair<my_component_registry::const_iterator, rwlock_scoped_lock>
106 
107  /**
108  Creates iterator that iterates through all loaded Components.
109  If successful it leaves read lock on dynamic loader until iterator is
110  released.
111 
112  @param [out] out_iterator Pointer to Component iterator handle.
113  @return Status of performed operation
114  @retval false success
115  @retval true failure
116  */
118  (my_h_component_iterator * out_iterator));
119 
120  /**
121  Releases Component iterator. Releases read lock on dynamic loader.
122 
123  @param iterator Component iterator handle.
124  @return Status of performed operation
125  @retval false success
126  @retval true failure
127  */
128  static DEFINE_METHOD(void, iterator_release,
129  (my_h_component_iterator iterator));
130 
131  /**
132  Gets name and URN of Service pointed to by iterator.
133 
134  @param iterator Component iterator handle.
135  @param [out] out_name Pointer to string with Component name to set result
136  pointer to.
137  @param [out] out_urn Pointer to string with URN from which the Component was
138  loaded from, to set result pointer to.
139  @return Status of performed operation
140  @retval false success
141  @retval true Failure, may be caused when called on iterator that went
142  through all values already.
143  */
145  (my_h_component_iterator iterator,
146  const char **out_name, const char **out_urn));
147 
148  /**
149  Advances specified iterator to next element. Will succeed but return true if
150  it reaches one-past-last element.
151 
152  @param iterator Component iterator handle.
153  @return Status of performed operation and validity of iterator after
154  operation.
155  @retval false success
156  @retval true Failure or called on iterator that was on last element.
157  */
159 
160  /**
161  Checks if specified iterator is valid, i.e. have not reached one-past-last
162  element.
163 
164  @param iterator Component iterator handle.
165  @return Validity of iterator
166  @retval false Valid
167  @retval true Invalid or reached one-past-last element.
168  */
170  (my_h_component_iterator iterator));
171 
172  /* This includes metadata-related method implementations that are shared
173  by registry and dynamic_loader, so we don't duplicate the code. Following
174  defines set up all required symbols. Unfortunately they are not only the
175  types, but also static members with different name, so usage of templates
176  is not enough to reuse that part of code. */
177 
178 #define OBJECT_ITERATOR my_h_component_iterator
179 #define METADATA_ITERATOR my_h_component_metadata_iterator
180 
181 #include "registry_metadata.h.inc"
182 
183  private:
184  /**
185  Loads specified group of Components by URN. From URNs specified the
186  scheme part of URN (part before "://") is extracted and used to acquire
187  Service Implementation of scheme Component loader Service for specified
188  scheme. In case of failure rollbacks all changes, i.e. unloads loaded
189  Components.
190 
191  @param urns List of URNs of Components to load.
192  @param component_count Number of Components on list to load.
193  @return Status of performed operation
194  @retval false success
195  @retval true failure
196  */
197  static bool load_do_load_component_by_scheme(const char *urns[],
198  int component_count);
199 
200  /**
201  Prepares a list of all Services that are provided by specified Components.
202  This will enable us in next step to check if these may be used to satisfy
203  other Components dependencies.
204 
205  @param loaded_components List of Components to continue load of.
206  @return Status of performed operation
207  @retval false success
208  @retval true failure
209  */
211  std::vector<std::unique_ptr<mysql_component>> &loaded_components);
212 
213  /**
214  Checks if all dependencies can be satisfied with existing or to be added
215  Services.
216 
217  @param loaded_components List of Components to continue load of.
218  @param services_provided List of Services that are being provided by
219  Components to be loaded.
220  @return Status of performed operation
221  @retval false success
222  @retval true failure
223  */
224  static bool load_do_check_dependencies(
225  std::vector<std::unique_ptr<mysql_component>> &loaded_components,
226  const std::set<my_string> &services_provided);
227 
228  /**
229  Registers all Services that are provided by specified Components.
230  In case of failure rollbacks all changes, i.e. unregister registered Service
231  Implementations.
232 
233  @param loaded_components List of Components to continue load of.
234  @return Status of performed operation
235  @retval false success
236  @retval true failure
237  */
238  static bool load_do_register_services(
239  std::vector<std::unique_ptr<mysql_component>> &loaded_components);
240 
241  /**
242  Acquires Service Implementations for all dependencies of Components.
243  In case of failure rollbacks all changes, i.e. release Services that were
244  acquired.
245 
246  @param loaded_components List of Components to continue load of.
247  @return Status of performed operation
248  @retval false success
249  @retval true failure
250  */
251  static bool load_do_resolve_dependencies(
252  std::vector<std::unique_ptr<mysql_component>> &loaded_components);
253 
254  /**
255  Calls Components initialization method to make Components ready to function.
256  In case of failure rollbacks all changes, i.e. calls deinitialization
257  methods on initialized Components.
258 
259  @param loaded_components List of Components to continue load of.
260  @return Status of performed operation
261  @retval false success
262  @retval true failure
263  */
264  static bool load_do_initialize_components(
265  std::vector<std::unique_ptr<mysql_component>> &loaded_components);
266 
267  /**
268  Adds all Components to main list of loaded Components. Marks changes done by
269  all previous steps as not to be rolled back.
270 
271  @param loaded_components List of Components to continue load of.
272  @return Status of performed operation
273  @retval false success
274  @retval true failure
275  */
276  static bool load_do_commit(
277  std::vector<std::unique_ptr<mysql_component>> &loaded_components);
278 
279  /**
280  Unloads all Components specified in list. It does not acquire a write lock
281  on dynamic loader, but requires it to be acquired by caller.
282 
283  @param urns List of URNs of Components to unload.
284  @param component_count Number of Components on list to unload.
285  @return Status of performed operation
286  @retval false success
287  @retval true failure
288  */
289  static bool unload_do_list_components(const char *urns[],
290  int component_count);
291 
292  /**
293  Orders components in a order that would allow allow deinitialization to be
294  done always for components that have all their dependencies still not
295  deinitialized. It also creates a graph of dependencies between the Service
296  Implementations provided by the Components to be unloaded and Components
297  that use this Service Implementation.
298 
299  @param components_to_unload List of Components to continue unload of.
300  @return Status of performed operation
301  @retval false success
302  @retval true failure
303  */
304  static bool unload_do_topological_order(
305  const std::vector<mysql_component *> &components_to_unload);
306 
307  /**
308  Prefetch all scheme loading Services before we get a lock on a Registry.
309 
310  @param components_to_unload List of Components to continue unload of.
311  @param dependency_graph A graph of dependencies between the Components
312  to be unloaded.
313  @return Status of performed operation
314  @retval false success
315  @retval true failure
316  */
317  static bool unload_do_get_scheme_services(
318  const std::vector<mysql_component *> &components_to_unload,
319  const std::map<const void *, std::vector<mysql_component *>>
320  &dependency_graph);
321 
322  /**
323  Takes a lock on all services that are provided by the Components to be
324  unloaded, to prevent reference count from being changed.
325 
326  @param components_to_unload List of Components to continue unload of.
327  @param dependency_graph A graph of dependencies between the Components
328  to be unloaded.
329  @param scheme_services Map of scheme loading Services prefetched with
330  Service Implementations required to unload all Components to unload.
331  @return Status of performed operation
332  @retval false success
333  @retval true failure
334  */
336  const std::vector<mysql_component *> &components_to_unload,
337  const std::map<const void *, std::vector<mysql_component *>>
338  &dependency_graph,
339  scheme_service_map &scheme_services);
340 
341  /**
342  Checks if all Service Implementations provided by the Components to be
343  unloaded have no references outside the group of Components to be unloaded.
344  This assures that continuing deinitialization of these Components in
345  topological order, and by this also unregistration of all provided Service
346  Implementations will succeed.
347 
348  @param components_to_unload List of Components to continue unload of.
349  @param dependency_graph A graph of dependencies between the Components
350  to be unloaded.
351  @param scheme_services Map of scheme loading Services prefetched with
352  Service Implementations required to unload all Components to unload.
353  @return Status of performed operation
354  @retval false success
355  @retval true failure
356  */
358  const std::vector<mysql_component *> &components_to_unload,
359  const std::map<const void *, std::vector<mysql_component *>>
360  &dependency_graph,
361  scheme_service_map &scheme_services);
362 
363  /**
364  Deinitialize Components using their deinitialization method.
365  In case of failure rollbacks all changes, i.e. calls initialization
366  method again on deinitialized Components.
367 
368  @param components_to_unload List of Components to continue unload of.
369  @param scheme_services Map of scheme loading Services prefetched with
370  Service Implementations required to unload all Components to unload.
371  @return Status of performed operation
372  @retval false success
373  @retval true failure
374  */
376  const std::vector<mysql_component *> &components_to_unload,
377  scheme_service_map &scheme_services);
378 
379  /**
380  Releases Service Implementations acquired to satisfy dependencies.
381  In case of failure rollbacks all changes, i.e. acquires Services for
382  released dependencies again.
383 
384  @param components_to_unload List of Components to continue unload of.
385  @param scheme_services Map of scheme loading Services prefetched with
386  Service Implementations required to unload all Components to unload.
387  @return Status of performed operation
388  @retval false success
389  @retval true failure
390  */
391  static bool unload_do_unload_dependencies(
392  const std::vector<mysql_component *> &components_to_unload,
393  scheme_service_map &scheme_services);
394 
395  /**
396  Unregisters all Service Implementations of specified Components.
397  In case of failure rollbacks all changes, i.e. registers unregistered
398  Service Implementations again.
399 
400  @param components_to_unload List of Components to continue unload of.
401  @param scheme_services Map of scheme loading Services prefetched with
402  Service Implementations required to unload all Components to unload.
403  @return Status of performed operation
404  @retval false success
405  @retval true failure
406  */
407  static bool unload_do_unregister_services(
408  const std::vector<mysql_component *> &components_to_unload,
409  scheme_service_map &scheme_services);
410 
411  /**
412  Uses Component URN to extract the scheme part of URN (part before "://") and
413  use it to acquire Service Implementation of scheme Component loader Service
414  for specified scheme, used then to unload specified Components. The unloaded
415  Components are removed from the main list of all loaded Components.
416  In case of failure rollbacks all changes, i.e. loads unloaded Components
417  by their URN and add them to the main list of loaded Components again.
418 
419  @param components_to_unload List of Components to continue unload of.
420  @param scheme_services Map of scheme loading Services prefetched with
421  Service Implementations required to unload all Components to unload.
422  @return Status of performed operation
423  @retval false success
424  @retval true failure
425  */
426  static bool unload_do_unload_components(
427  const std::vector<mysql_component *> &components_to_unload,
428  scheme_service_map &scheme_services);
429 
430  /**
431  Finishes unloading process by marking changes to not be rolled back.
432 
433  @return Status of performed operation
434  @retval false success
435  @retval true failure
436  */
437  static bool unload_do_commit();
438 
439  /**
440  Returns scheme loading Service based on given URN. It uses supplied cache to
441  reuse Services. If Service is not present in cache, it will be acquired from
442  registry.
443 
444  @param urn URN of Components to get scheme loader Service for.
445  @param [out] out_scheme_service Pointer to store result scheme loader
446  Service.
447  @param [in,out] scheme_services Map of scheme loader services already
448  acquired.
449  @return Status of performed operation
450  @retval false success
451  @retval true failure
452  */
453  static bool get_scheme_service_from_urn(const my_string &urn,
454  SERVICE_TYPE(dynamic_loader_scheme) *
455  *out_scheme_service,
456  scheme_service_map &scheme_services);
457 };
458 
459 #endif /* MYSQL_SERVER_DYNAMIC_LOADER_H */
static bool unload_do_unload_components(const std::vector< mysql_component *> &components_to_unload, scheme_service_map &scheme_services)
Uses Component URN to extract the scheme part of URN (part before "://") and use it to acquire Servic...
Definition: dynamic_loader.cc:1276
static bool load_do_check_dependencies(std::vector< std::unique_ptr< mysql_component >> &loaded_components, const std::set< my_string > &services_provided)
Checks if all dependencies can be satisfied with existing or to be added Services.
Definition: dynamic_loader.cc:720
static bool load_do_collect_services_provided(std::vector< std::unique_ptr< mysql_component >> &loaded_components)
Prepares a list of all Services that are provided by specified Components.
Definition: dynamic_loader.cc:682
Wraps my_h_service struct conforming ABI into RAII C++ object with ability to cast to desired service...
Definition: my_service.h:34
static bool get_scheme_service_from_urn(const my_string &urn, const mysql_service_dynamic_loader_scheme_t **out_scheme_service, scheme_service_map &scheme_services)
Returns scheme loading Service based on given URN.
Definition: dynamic_loader.cc:1342
static bool load_do_resolve_dependencies(std::vector< std::unique_ptr< mysql_component >> &loaded_components)
Acquires Service Implementations for all dependencies of Components.
Definition: dynamic_loader.cc:811
#define DEFINE_BOOL_METHOD(name, args)
static bool unload_do_unregister_services(const std::vector< mysql_component *> &components_to_unload, scheme_service_map &scheme_services)
Unregisters all Service Implementations of specified Components.
Definition: dynamic_loader.cc:1235
static bool unload_do_commit()
Finishes unloading process by marking changes to not be rolled back.
Definition: dynamic_loader.cc:1322
#define SERVICE_TYPE(name)
static mysql_service_status_t unload(const char *urns[], int component_count) noexcept
Unloads specified group of Components by URN, deinitializes them and unregisters all Service Implemen...
Definition: dynamic_loader.cc:409
static mysql_service_status_t iterator_next(my_h_component_iterator iterator) noexcept
Advances specified iterator to next element.
Definition: dynamic_loader.cc:544
A class with an implementation of the Dynamic Loader Service.
Definition: dynamic_loader.h:43
std::pair< my_component_registry::const_iterator, rwlock_scoped_lock > component_iterator
Definition: dynamic_loader.h:105
static mysql_service_status_t iterator_create(my_h_component_iterator *out_iterator) noexcept
Creates iterator that iterates through all loaded Components.
Definition: dynamic_loader.cc:449
static my_component_registry components_list
Definition: dynamic_loader.h:49
#define DEFINE_METHOD(retval, name, args)
static bool load_do_load_component_by_scheme(const char *urns[], int component_count)
Loads specified group of Components by URN.
Definition: dynamic_loader.cc:614
static mysql_service_status_t iterator_is_valid(my_h_component_iterator iterator) noexcept
Checks if specified iterator is valid, i.e.
Definition: dynamic_loader.cc:571
static bool unload_do_check_provided_services_reference_count(const std::vector< mysql_component *> &components_to_unload, const std::map< const void *, std::vector< mysql_component *>> &dependency_graph, scheme_service_map &scheme_services)
Checks if all Service Implementations provided by the Components to be unloaded have no references ou...
Definition: dynamic_loader.cc:1116
static bool unload_do_unload_dependencies(const std::vector< mysql_component *> &components_to_unload, scheme_service_map &scheme_services)
Releases Service Implementations acquired to satisfy dependencies.
Definition: dynamic_loader.cc:1197
static void init()
Initializes loader for usage.
Definition: dynamic_loader.cc:302
static bool unload_do_list_components(const char *urns[], int component_count)
Unloads all Components specified in list.
Definition: dynamic_loader.cc:925
static mysql_rwlock_t LOCK_dynamic_loader
Definition: dynamic_loader.h:50
static mysql_service_status_t load(const char *urns[], int component_count) noexcept
Loads specified group of Components by URN, initializes them and registers all Service Implementation...
Definition: dynamic_loader.cc:362
static void iterator_release(my_h_component_iterator iterator) noexcept
Releases Component iterator.
Definition: dynamic_loader.cc:482
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:50
static bool unload_do_get_scheme_services(const std::vector< mysql_component *> &components_to_unload, const std::map< const void *, std::vector< mysql_component *>> &dependency_graph)
Prefetch all scheme loading Services before we get a lock on a Registry.
Definition: dynamic_loader.cc:1052
static bool unload_do_topological_order(const std::vector< mysql_component *> &components_to_unload)
Orders components in a order that would allow allow deinitialization to be done always for components...
Definition: dynamic_loader.cc:966
std::unordered_map< my_string, my_service< const mysql_service_dynamic_loader_scheme_t > > scheme_service_map
Definition: dynamic_loader.h:46
std::string my_string
Definition: dynamic_loader_path_filter.cc:36
static bool unload_do_lock_provided_services(const std::vector< mysql_component *> &components_to_unload, const std::map< const void *, std::vector< mysql_component *>> &dependency_graph, scheme_service_map &scheme_services)
Takes a lock on all services that are provided by the Components to be unloaded, to prevent reference...
Definition: dynamic_loader.cc:1086
static mysql_service_status_t iterator_get(my_h_component_iterator iterator, const char **out_name, const char **out_urn) noexcept
Gets name and URN of Service pointed to by iterator.
Definition: dynamic_loader.cc:510
std::map< const char *, std::unique_ptr< mysql_component >, c_string_less > my_component_registry
Definition: dynamic_loader.h:38
static bool unload_do_deinitialize_components(const std::vector< mysql_component *> &components_to_unload, scheme_service_map &scheme_services)
Deinitialize Components using their deinitialization method.
Definition: dynamic_loader.cc:1160
static bool load_do_commit(std::vector< std::unique_ptr< mysql_component >> &loaded_components)
Adds all Components to main list of loaded Components.
Definition: dynamic_loader.cc:904
Specifies macros to define Service Implementations.
static bool load_do_initialize_components(std::vector< std::unique_ptr< mysql_component >> &loaded_components)
Calls Components initialization method to make Components ready to function.
Definition: dynamic_loader.cc:859
static bool load_do_register_services(std::vector< std::unique_ptr< mysql_component >> &loaded_components)
Registers all Services that are provided by specified Components.
Definition: dynamic_loader.cc:764
Compares two strings for order, assures ascending lexicographical order.
Definition: c_string_less.h:38
Definition: dynamic_loader.cc:288
static void deinit()
De-initializes loader.
Definition: dynamic_loader.cc:310