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