MySQL 8.0.39
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 @return Status of performed operation
228 @retval false success
229 @retval true failure
230 */
232 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
233
234 /**
235 Checks if all dependencies can be satisfied with existing or to be added
236 Services.
237
238 @param loaded_components List of Components to continue load of.
239 @param services_provided List of Services that are being provided by
240 Components to be loaded.
241 @return Status of performed operation
242 @retval false success
243 @retval true failure
244 */
245 static bool load_do_check_dependencies(
246 std::vector<std::unique_ptr<mysql_component>> &loaded_components,
247 const std::set<my_string> &services_provided);
248
249 /**
250 Registers all Services that are provided by specified Components.
251 In case of failure rollbacks all changes, i.e. unregister registered Service
252 Implementations.
253
254 @param loaded_components List of Components to continue load of.
255 @return Status of performed operation
256 @retval false success
257 @retval true failure
258 */
259 static bool load_do_register_services(
260 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
261
262 /**
263 Acquires Service Implementations for all dependencies of Components.
264 In case of failure rollbacks all changes, i.e. release Services that were
265 acquired.
266
267 @param loaded_components List of Components to continue load of.
268 @return Status of performed operation
269 @retval false success
270 @retval true failure
271 */
273 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
274
275 /**
276 Calls Components initialization method to make Components ready to function.
277 In case of failure rollbacks all changes, i.e. calls deinitialization
278 methods on initialized Components.
279
280 @param loaded_components List of Components to continue load of.
281 @return Status of performed operation
282 @retval false success
283 @retval true failure
284 */
286 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
287
288 /**
289 Adds all Components to main list of loaded Components. Marks changes done by
290 all previous steps as not to be rolled back.
291
292 @param loaded_components List of Components to continue load of.
293 @return Status of performed operation
294 @retval false success
295 @retval true failure
296 */
297 static bool load_do_commit(
298 std::vector<std::unique_ptr<mysql_component>> &loaded_components);
299
300 /**
301 Unloads all Components specified in list. It does not acquire a write lock
302 on dynamic loader, but requires it to be acquired by caller.
303
304 @param urns List of URNs of Components to unload.
305 @param component_count Number of Components on list to unload.
306 @return Status of performed operation
307 @retval false success
308 @retval true failure
309 */
310 static bool unload_do_list_components(const char *urns[],
311 int component_count);
312
313 /**
314 Orders components in a order that would allow allow deinitialization to be
315 done always for components that have all their dependencies still not
316 deinitialized. It also creates a graph of dependencies between the Service
317 Implementations provided by the Components to be unloaded and Components
318 that use this Service Implementation.
319
320 @param components_to_unload List of Components to continue unload of.
321 @return Status of performed operation
322 @retval false success
323 @retval true failure
324 */
325 static bool unload_do_topological_order(
326 const std::vector<mysql_component *> &components_to_unload);
327
328 /**
329 Prefetch all scheme loading Services before we get a lock on a Registry.
330
331 @param components_to_unload List of Components to continue unload of.
332 @param dependency_graph A graph of dependencies between the Components
333 to be unloaded.
334 @return Status of performed operation
335 @retval false success
336 @retval true failure
337 */
339 const std::vector<mysql_component *> &components_to_unload,
340 const std::map<const void *, std::vector<mysql_component *>>
341 &dependency_graph);
342
343 /**
344 Takes a lock on all services that are provided by the Components to be
345 unloaded, to prevent reference count from being changed.
346
347 @param components_to_unload List of Components to continue unload of.
348 @param dependency_graph A graph of dependencies between the Components
349 to be unloaded.
350 @param scheme_services Map of scheme loading Services prefetched with
351 Service Implementations required to unload all Components to unload.
352 @return Status of performed operation
353 @retval false success
354 @retval true failure
355 */
357 const std::vector<mysql_component *> &components_to_unload,
358 const std::map<const void *, std::vector<mysql_component *>>
359 &dependency_graph,
360 scheme_service_map &scheme_services);
361
362 /**
363 Checks if all Service Implementations provided by the Components to be
364 unloaded have no references outside the group of Components to be unloaded.
365 This assures that continuing deinitialization of these Components in
366 topological order, and by this also unregistration of all provided Service
367 Implementations will succeed.
368
369 @param components_to_unload List of Components to continue unload of.
370 @param dependency_graph A graph of dependencies between the Components
371 to be unloaded.
372 @param scheme_services Map of scheme loading Services prefetched with
373 Service Implementations required to unload all Components to unload.
374 @return Status of performed operation
375 @retval false success
376 @retval true failure
377 */
379 const std::vector<mysql_component *> &components_to_unload,
380 const std::map<const void *, std::vector<mysql_component *>>
381 &dependency_graph,
382 scheme_service_map &scheme_services);
383
384 /**
385 Deinitialize Components using their deinitialization method.
386 In case of failure rollbacks all changes, i.e. calls initialization
387 method again on deinitialized Components.
388
389 @param components_to_unload List of Components to continue unload of.
390 @param scheme_services Map of scheme loading Services prefetched with
391 Service Implementations required to unload all Components to unload.
392 @return Status of performed operation
393 @retval false success
394 @retval true failure
395 */
397 const std::vector<mysql_component *> &components_to_unload,
398 scheme_service_map &scheme_services);
399
400 /**
401 Releases Service Implementations acquired to satisfy dependencies.
402 In case of failure rollbacks all changes, i.e. acquires Services for
403 released dependencies again.
404
405 @param components_to_unload List of Components to continue unload of.
406 @param scheme_services Map of scheme loading Services prefetched with
407 Service Implementations required to unload all Components to unload.
408 @return Status of performed operation
409 @retval false success
410 @retval true failure
411 */
413 const std::vector<mysql_component *> &components_to_unload,
414 scheme_service_map &scheme_services);
415
416 /**
417 Unregisters all Service Implementations of specified Components.
418 In case of failure rollbacks all changes, i.e. registers unregistered
419 Service Implementations again.
420
421 @param components_to_unload List of Components to continue unload of.
422 @param scheme_services Map of scheme loading Services prefetched with
423 Service Implementations required to unload all Components to unload.
424 @return Status of performed operation
425 @retval false success
426 @retval true failure
427 */
429 const std::vector<mysql_component *> &components_to_unload,
430 scheme_service_map &scheme_services);
431
432 /**
433 Uses Component URN to extract the scheme part of URN (part before "://") and
434 use it to acquire Service Implementation of scheme Component loader Service
435 for specified scheme, used then to unload specified Components. The unloaded
436 Components are removed from the main list of all loaded Components.
437 In case of failure rollbacks all changes, i.e. loads unloaded Components
438 by their URN and add them to the main list of loaded Components again.
439
440 @param components_to_unload List of Components to continue unload of.
441 @param scheme_services Map of scheme loading Services prefetched with
442 Service Implementations required to unload all Components to unload.
443 @return Status of performed operation
444 @retval false success
445 @retval true failure
446 */
447 static bool unload_do_unload_components(
448 const std::vector<mysql_component *> &components_to_unload,
449 scheme_service_map &scheme_services);
450
451 /**
452 Finishes unloading process by marking changes to not be rolled back.
453
454 @return Status of performed operation
455 @retval false success
456 @retval true failure
457 */
458 static bool unload_do_commit();
459
460 /**
461 Returns scheme loading Service based on given URN. It uses supplied cache to
462 reuse Services. If Service is not present in cache, it will be acquired from
463 registry.
464
465 @param urn URN of Components to get scheme loader Service for.
466 @param [out] out_scheme_service Pointer to store result scheme loader
467 Service.
468 @param [in,out] scheme_services Map of scheme loader services already
469 acquired.
470 @return Status of performed operation
471 @retval false success
472 @retval true failure
473 */
474 static bool get_scheme_service_from_urn(const my_string &urn,
475 SERVICE_TYPE(dynamic_loader_scheme) *
476 *out_scheme_service,
477 scheme_service_map &scheme_services);
478};
479
480extern REQUIRES_SERVICE_PLACEHOLDER(mysql_runtime_error);
482
483#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:605
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:1121
static void rw_lock_deinit()
De-initializes RW lock.
Definition: dynamic_loader.cc:380
static void deinit()
De-initializes loader.
Definition: dynamic_loader.cc:337
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:1002
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:544
static void iterator_release(my_h_component_iterator iterator) noexcept
Releases Component iterator.
Definition: dynamic_loader.cc:516
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:490
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:1087
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:1233
static void init()
Initializes loader for usage.
Definition: dynamic_loader.cc:327
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:1271
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:1401
static mysql_rwlock_t LOCK_dynamic_loader
Definition: dynamic_loader_imp.h:67
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:716
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:891
static mysql_service_status_t iterator_next(my_h_component_iterator iterator) noexcept
Advances specified iterator to next element.
Definition: dynamic_loader.cc:578
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:648
static bool unload_do_list_components(const char *urns[], int component_count)
Unloads all Components specified in list.
Definition: dynamic_loader.cc:961
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:1196
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:754
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:936
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:1152
static bool unload_do_commit()
Finishes unloading process by marking changes to not be rolled back.
Definition: dynamic_loader.cc:1381
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:845
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:798
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:401
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:1312
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:449
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:50
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:2898
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2874
std::map< Key, Value, Compare, ut::allocator< std::pair< const Key, Value > > > map
Specialization of map which uses ut_allocator.
Definition: ut0new.h:2892
#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:299
An instrumented rwlock structure.
Definition: mysql_rwlock_bits.h:51