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