MySQL 9.4.0
Source Code Documentation
dynamic_loader_imp.h
Go to the documentation of this file.
1/* Copyright (c) 2016, 2025, 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 For all Services that are provided by specified Components
239 checks if the required Service is present in provided Services.
240 If so, no further action is taken for the Service.
241 If not, tries to acquire the Service.
242 This time acquire() can fail and we continue the load process,
243 because we hope the required Service might be possibly registered later by
244 some Component init().
245
246 @param loaded_components List of Components to continue load of.
247 @param services_provided List of Services that are being provided by
248 Components to be loaded.
249 @return Status of performed operation
250 @retval false success
251 @retval true failure
252 */
253 static bool load_do_check_acquire(
254 std::vector<std::unique_ptr<mysql_component>> &loaded_components,
255 const std::set<my_string> &services_provided);
256
257 /**
258 Calls Components initialization method to make Components ready to function.
259 In case of failure rollbacks all changes, i.e. calls deinitialization
260 methods on initialized Components.
261
262 @param loaded_components List of Components to continue load of.
263 @return Status of performed operation
264 @retval false success
265 @retval true failure
266 */
268 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
269
270 /**
271 Registers all Services that are provided by specified Components.
272 In case of failure rollbacks all changes, i.e. unregister registered Service
273 Implementations.
274
275 @param loaded_components List of Components to continue load of.
276 @return Status of performed operation
277 @retval false success
278 @retval true failure
279 */
280 static bool load_do_register_services(
281 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
282
283 /**
284 Acquires Service Implementations for these dependencies of Components,
285 which are not acquired yet.
286 In case of failure rollbacks all changes, i.e. release Services that were
287 acquired.
288
289 @param loaded_components List of Components to continue load of.
290 @return Status of performed operation
291 @retval false success
292 @retval true failure
293 */
294 static bool load_do_acquire(
295 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
296
297 /**
298 Adds all Components to main list of loaded Components. Marks changes done by
299 all previous steps as not to be rolled back.
300
301 @param loaded_components List of Components to continue load of.
302 @return Status of performed operation
303 @retval false success
304 @retval true failure
305 */
306 static bool load_do_commit(
307 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
308
309 /**
310 Unloads all Components specified in list. It does not acquire a write lock
311 on dynamic loader, but requires it to be acquired by caller.
312
313 @param urns List of URNs of Components to unload.
314 @param component_count Number of Components on list to unload.
315 @return Status of performed operation
316 @retval false success
317 @retval true failure
318 */
319 static bool unload_do_list_components(const char *urns[],
320 int component_count);
321
322 /**
323 Orders components in a order that would allow allow deinitialization to be
324 done always for components that have all their dependencies still not
325 deinitialized. It also creates a graph of dependencies between the Service
326 Implementations provided by the Components to be unloaded and Components
327 that use this Service Implementation.
328
329 @param components_to_unload List of Components to continue unload of.
330 @return Status of performed operation
331 @retval false success
332 @retval true failure
333 */
334 static bool unload_do_topological_order(
335 const std::vector<mysql_component *> &components_to_unload);
336
337 /**
338 Takes a lock on the registry, to prevent reference count from being changed
339 and then invokes:
340 - unload_do_check_provided_services_reference_count,
341 - unload_do_unload_dependencies,
342 - unload_do_unregister_services.
343 Lock is removed then and the unload_do_deinitialize_components is invoked.
344 Manages the rollback in case of deinit failure - with use of scope guard.
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 @return Status of performed operation
350 @retval false success
351 @retval true failure
352 */
354 const std::vector<mysql_component *> &components_to_unload,
355 const std::map<const void *, std::vector<mysql_component *>>
356 &dependency_graph);
357
358 /**
359 Checks if all Service Implementations provided by the Components to be
360 unloaded have no references outside the group of Components to be unloaded.
361 This assures that continuing deinitialization of these Components in
362 topological order, and by this also unregistration of all provided Service
363 Implementations will succeed.
364
365 @param components_to_unload List of Components to continue unload of.
366 @param dependency_graph A graph of dependencies between the Components
367 to be unloaded.
368 @return Status of performed operation
369 @retval false success
370 @retval true failure
371 */
373 const std::vector<mysql_component *> &components_to_unload,
374 const std::map<const void *, std::vector<mysql_component *>>
375 &dependency_graph);
376
377 /**
378 Releases Service Implementations acquired to satisfy dependencies.
379
380 @param components_to_unload List of Components to continue unload of.
381 @param [out] released_services Vector of services actually released (for
382 rollback purposes)
383 @return Status of performed operation
384 @retval false success
385 @retval true failure
386 */
388 const std::vector<mysql_component *> &components_to_unload,
389 std::vector<mysql_service_placeholder_ref_t *> &released_services);
390
391 /**
392 Unregisters all Service Implementations of specified Components.
393
394 @param components_to_unload List of Components to continue unload of.
395 @param [out] unregistered_services Vactor of services actually unregistered
396 (for rollback purposes)
397 @return Status of performed operation
398 @retval false success
399 @retval true failure
400 */
402 const std::vector<mysql_component *> &components_to_unload,
403 std::vector<const mysql_service_ref_t *> &unregistered_services);
404
405 /**
406 Deinitialize Components using their deinitialization method.
407
408 @param components_to_unload List of Components to continue unload of.
409 @return Status of performed operation
410 @retval false success
411 @retval true failure
412*/
414 const std::vector<mysql_component *> &components_to_unload);
415
416 /**
417 Uses Component URN to extract the scheme part of URN (part before "://") and
418 use it to acquire Service Implementation of scheme Component loader Service
419 for specified scheme, used then to unload specified Components. The unloaded
420 Components are removed from the main list of all loaded Components.
421
422 @param components_to_unload List of Components to continue unload of.
423 @return Status of performed operation
424 @retval false success
425 @retval true failure
426 */
427 static bool unload_do_unload_components(
428 const std::vector<mysql_component *> &components_to_unload);
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
459extern REQUIRES_SERVICE_PLACEHOLDER(mysql_runtime_error);
461
462#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:679
static bool unload_do_unregister_services(const std::vector< mysql_component * > &components_to_unload, std::vector< const mysql_service_ref_t * > &unregistered_services)
Unregisters all Service Implementations of specified Components.
Definition: dynamic_loader.cc:1402
static void rw_lock_deinit()
De-initializes RW lock.
Definition: dynamic_loader.cc:419
static void deinit()
De-initializes loader.
Definition: dynamic_loader.cc:376
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:1146
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:618
static bool unload_do_deinitialize_components(const std::vector< mysql_component * > &components_to_unload)
Deinitialize Components using their deinitialization method.
Definition: dynamic_loader.cc:1436
static bool load_do_check_acquire(std::vector< std::unique_ptr< mysql_component > > &loaded_components, const std::set< my_string > &services_provided)
For all Services that are provided by specified Components checks if the required Service is present ...
Definition: dynamic_loader.cc:871
static void iterator_release(my_h_component_iterator iterator) noexcept
Releases Component iterator.
Definition: dynamic_loader.cc:591
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:566
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)
Takes a lock on the registry, to prevent reference count from being changed and then invokes:
Definition: dynamic_loader.cc:1236
static bool unload_do_unload_components(const std::vector< mysql_component * > &components_to_unload)
Uses Component URN to extract the scheme part of URN (part before "://") and use it to acquire Servic...
Definition: dynamic_loader.cc:1470
static void init()
Initializes loader for usage.
Definition: dynamic_loader.cc:366
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:1559
static mysql_rwlock_t LOCK_dynamic_loader
Definition: dynamic_loader_imp.h:67
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)
Checks if all Service Implementations provided by the Components to be unloaded have no references ou...
Definition: dynamic_loader.cc:1326
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:937
static bool unload_do_unload_dependencies(const std::vector< mysql_component * > &components_to_unload, std::vector< mysql_service_placeholder_ref_t * > &released_services)
Releases Service Implementations acquired to satisfy dependencies.
Definition: dynamic_loader.cc:1366
static mysql_service_status_t iterator_next(my_h_component_iterator iterator) noexcept
Advances specified iterator to next element.
Definition: dynamic_loader.cc:652
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:722
static bool unload_do_list_components(const char *urns[], int component_count)
Unloads all Components specified in list.
Definition: dynamic_loader.cc:1105
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:1080
static bool unload_do_commit()
Finishes unloading process by marking changes to not be rolled back.
Definition: dynamic_loader.cc:1539
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:985
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:826
static bool load_do_acquire(std::vector< std::unique_ptr< mysql_component > > &loaded_components)
Acquires Service Implementations for these dependencies of Components, which are not acquired yet.
Definition: dynamic_loader.cc:1036
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:440
static my_component_registry components_list
Definition: dynamic_loader_imp.h:66
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:500
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:2900
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2876
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2894
#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:338
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:51