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