MySQL 8.0.40
Source Code Documentation
component_implementation.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 COMPONENT_IMPLEMENTATION_H
25#define COMPONENT_IMPLEMENTATION_H
26
29#include <cstddef> // NULL
31
32/**
33 @page PAGE_COMPONENTS_COMPONENT A Component
34
35 A component is a code container that contains one or more Service
36 Implementations. Components can be internal (part of the MySQL Server binary)
37 and external (hosted in a OS binary file different from the one of the MySQL
38 Server).
39
40 Each component will have:
41 - Name
42 - List of service implementations it provides.
43 - List of services or service implementations it needs.
44 - Initialization function that's called when a container is loaded. Takes a
45 reference to the currently active service registry implementation.
46 - De-initialization function that's called when a container unload is
47 requested.
48
49 Opposite to old plugin infrastructure, Components don't need linkage against
50 mysqld executable, neither on Linux nor Windows. In fact, in Components we
51 strongly discourage from linking against mysqld executable at all, as it
52 presents significant threat to them being independent and using only
53 Components infrastructure to communicate with other parts of software.
54
55 @subpage PAGE_COMPONENTS_IMPLEMENTATION
56
57 @page PAGE_COMPONENTS_IMPLEMENTATION MySQL Component - creating implementation
58 The Component for the Dynamic Loader needs to be a dynamic library (for
59 example .so or .dll) with specified entry-point method. The only exception is
60 the MySQL server, for which, for now, it will be statically linked. All these
61 implementation details are hidden away by macros defined in header files.
62 All macros to define Services are specified in service.h, for defining Service
63 Implementations in service_implementation.h and for specifying Components in
64 component_implementation.h.
65
66 @section EXAMPLE The Component example
67 Example Components are located in components/example directory. These
68 Components are used also for unit and MTR test, which assures these Components
69 are fully functional and they quality is maintained. The example Services are
70 defined in example_services.h, while implemented in three example Components
71 defined in files example_component1.cc, example_component2.cc,
72 and example_component3.cc. These files are specifically prepared to be used as
73 examples as they provide simplicity and an extensive documentation. The
74 following tutorial bases on these Components and will try to show a process to
75 create similar.
76
77 @subsection EXAMPLE_SERVICES Services defined in the example
78 Example contains definition of 3 Services which will be used to show a general
79 idea of services, basic implementations and simple example of one of concepts
80 possible with the Component Infrastructure. These example Services are defined
81 in example_services.h and are s_mysql_greetings,
82 s_mysql_greetings_localization and s_mysql_example_math.
83
84 @section TROUBLESHOOTING Common problems
85
86 @section TUTORIAL Step by step tutorial for creating new Component
87 The creation of component is a mean to get some functionality exported for the
88 Components infrastructure. It can be divided into several steps:
89 -# %List all high level functionalities Component is planned to have
90 implemented. This will assure we know exactly what we need to benefit from
91 next steps. In the example, we would like to have a "Hello, World!" string
92 provider and simple math functions.
93 -# Look for existing Services, that are designed specifically to provide some
94 part of the new functionalities to reuse them, or other that are in any
95 degree similar in functionality, design or use cases to use as an example.
96 The Component infrastructure is highly oriented on reuse of Services and
97 will benefit with every reuse case, as it will decrease total size of
98 Services. In the example the existing base of Services is really small,
99 with the core Components infrastructure Services available only leading to
100 no reuse possible.
101 -# Design list of functions needed to provide all functionalities. Try to make
102 they follow existing patterns and ideas, possibly having some identical to
103 existing ones.
104 -# Try to separate groups of functions that specify some complete part of
105 functionality into separate small Services to improve re-usability. Also,
106 try to separate groups that seem to have more potential to be extended or
107 modified in future, because changing existing Services is forbidden, in
108 such a case this will lead to a lot of functions in Services that will be
109 duplicates and will introduce more boilerplate code to implement them.
110 Remove all functions that can be found in fully reused existing Services.
111 -# Create definitions of Services, ideally one Service per file, or a group of
112 really closely connected Services. In most cases you want to make these
113 definitions public, in case of MySQL that means placing them in
114 include/mysql/components/services/ directory to include them in mysql-dev
115 package. See example_services.h, which in contrary is not made public and
116 resides in example component source directory.
117 -# Create declarations of all handles, the Opaque pointers for all opaque
118 objects that are meant to be returned to the Services users. See usages of
119 DEFINE_SERVICE_HANDLE in registry.h.
120 -# Create basic structure of new Component. Use BEGIN_COMPONENT_PROVIDES,
121 BEGIN_COMPONENT_REQUIRES, BEGIN_COMPONENT_METADATA, DECLARE_COMPONENT and
122 DECLARE_LIBRARY_COMPONENTS. Fill in all information necessary to describe
123 the new Component extensively. The example_component1.cc and
124 example_component2.cc shows how structure should look like, and in
125 example_component3.cc there is an example with additional Service
126 references, for which placeholder definitions are kept in header file of the
127 new Component, see example_component3.h. Note the placeholder for the
128 Registry Service, which is available by default in every component.
129 -# Create implementations of the desired Service interfaces. Implement handles
130 used, as for example my_h_service_iterator_imp and
131 my_h_service_metadata_iterator_imp in registry.cc. Create separate
132 source and header files for each Service or closely connected group of
133 Services. Remember to include the header file for Service Implementation in
134 the Service Implementation source file to have no linkage problems.
135 The Service Implementations in english_greeting_service_imp.cc and
136 simple_example_math_imp.cc are implementations used in example_component1,
137 polish_greeting_service_imp.cc and example_math_wrapping_imp.cc are
138 implementations for example_component2 and example_component3 respectively.
139 -# Make sure component is loaded/initialized before using its services.
140 Atomic variable is_intialized represents the state of the component.
141 Please check the details about the variable from validate_password_imp.cc
142 file.
143 -# Using registry acquire/release services inside component's init/deint
144 functions is not supported. All the required services for the component
145 has to be specified under BEGIN_COMPONENT_REQUIRES section only.
146 .
147
148 @file include/mysql/components/component_implementation.h
149 Specifies macros to define Components.
150*/
151
152/**
153 Declares a component. For specified name following macros must be executed
154 earlier: BEGIN_COMPONENT_PROVIDES, BEGIN_COMPONENT_REQUIRES and
155 BEGIN_COMPONENT_METADATA.
156 It fills mysql_component_t structure with all of the component data. The
157 info object will be named mysql_component_{source_name}.
158 After this macro it is required to specify comma-separated pointers to
159 initialize and deinitialize methods for components to be used during loading
160 and unloading of component.
161
162 @param source_name The source name used in other macros.
163 @param name Name string with human readable name.
164*/
165#define DECLARE_COMPONENT(source_name, name) \
166 mysql_component_t mysql_component_##source_name = { \
167 name, __##source_name##_provides, __##source_name##_requires, \
168 __##source_name##_metadata,
169
170/**
171 A macro to end the last declaration of a Component.
172*/
173#define END_DECLARE_COMPONENT() }
174
175/**
176 Creates a service implementation list that are provided by specified
177 component. Only a series of PROVIDES_SERVICE and PROVIDES_CUSTOM_SERVICE
178 macros are expected to be used after this macro and before the
179 END_COMPONENT_PROVIDES counterpart.
180
181 @param name Component name.
182*/
183#define BEGIN_COMPONENT_PROVIDES(name) \
184 static struct mysql_service_ref_t __##name##_provides[] = {
185/**
186 Declare a Service Implementation provided by a Component. It assumes standard
187 Service Implementation name to be referenced.
188 @sa SERVICE_IMPLEMENTATION
189
190 @param component Component name.
191 @param service A Service name for which the Service Implementation will be
192 added.
193*/
194#define PROVIDES_SERVICE(component, service) \
195 { \
196#service "." #component, \
197 const_cast < void *> \
198 ((const void *)&SERVICE_IMPLEMENTATION(component, service)) \
199 }
200
201/**
202 A macro to end the last declaration started with the BEGIN_COMPONENT_PROVIDES.
203*/
204#define END_COMPONENT_PROVIDES() \
205 { NULL, NULL } \
206 }
207
208/**
209 A macro to specify requirements of the component. Creates a structure with
210 a list for requirements and pointers to their placeholders.
211
212 @param name Name of component.
213*/
214#define BEGIN_COMPONENT_REQUIRES_WITHOUT_REGISTRY(name) \
215 static struct mysql_service_placeholder_ref_t __##name##_requires[] = {
216/**
217 A macro to specify requirements of the component. Creates a placeholder for
218 the Registry service and structure with a list for requirements and
219 pointers to their placeholders, adding the Registry service as first element.
220
221 @param name Name of component.
222*/
223#define BEGIN_COMPONENT_REQUIRES(name) \
224 REQUIRES_SERVICE_PLACEHOLDER(registry); \
225 static struct mysql_service_placeholder_ref_t __##name##_requires[] = { \
226 REQUIRES_SERVICE(registry),
227
228/**
229 Create a service placeholder, based on the service name.
230
231 A service placeholder is a pointer to the service.
232 It is named mysql_service_{service name}.
233
234 This pointer is initialized by the framework upon loading a component,
235 based on the component dependencies declared by @ref REQUIRES_SERVICE.
236
237 When defining a service 'foo', in the header file for the service,
238 a service placeholder is declared as follows:
239
240 @verbatim
241 extern REQUIRES_SERVICE_PLACEHOLDER(foo);
242 @endverbatim
243
244 When implementing a component 'bar', which requires the service 'foo',
245 the definition of the component 'bar' should contain the following:
246
247 @verbatim
248 REQUIRES_SERVICE_PLACEHOLDER(foo);
249
250 BEGIN_COMPONENT_REQUIRES(bar)
251 REQUIRES_SERVICE(foo),
252 ...
253 END_COMPONENT_REQUIRES();
254 @endverbatim
255
256 The code in the implementation of service 'bar' can use
257 the service placeholder pointer to invoke apis in service foo:
258
259 @verbatim
260 mysql_service_foo->some_api();
261 @endverbatim
262
263 Similarly to use a service in another service within the same
264 component. Call the implementation of the service directly in
265 the other service since both services belong to the same component.
266 Suppose mysql_bar_imp and mysql_foo_imp services belongs to the
267 same component. And if foo service is required in bar service then
268 use below method.
269
270 @verbatim
271 mysql_bar_imp::bar_api() {
272 ...
273 mysql_foo_imp::foo_api();
274 ...
275 }
276 @endverbatim
277
278 @param service A referenced Service name.
279*/
280#define REQUIRES_SERVICE_PLACEHOLDER(service) \
281 SERVICE_TYPE(service) * mysql_service_##service
282
283/**
284 Create a service placeholder, with an arbitrary name.
285
286 Identical to @ref REQUIRES_SERVICE_PLACEHOLDER(),
287 except that the service handle name is provided
288 by the caller, instead of being derived from the service type.
289
290 Use with @ref REQUIRES_SERVICE_AS().
291
292 @param service A referenced Service name.
293 @param name Service handle name.
294*/
295
296#define REQUIRES_SERVICE_PLACEHOLDER_AS(service, name) \
297 SERVICE_TYPE(service) * name
298
299/**
300 Adds a Service requirement with a pointer to placeholder to the list of
301 components.
302
303 @param service A referenced Service name.
304*/
305#define REQUIRES_SERVICE(service) \
306 { \
307#service, \
308 static_cast < void **> \
309 (static_cast <void *>(const_cast <mysql_service_##service##_t **>( \
310 &mysql_service_##service))) \
311 }
312
313/**
314 Adds a Service requirement with a pointer to placeholder to the list of
315 components.
316
317 Use with @ref REQUIRES_SERVICE_PLACEHOLDER_AS().
318
319 @param service A referenced Service name.
320 @param name Service handle name.
321*/
322#define REQUIRES_SERVICE_AS(service, name) \
323 { \
324#service, \
325 static_cast < void **>(static_cast <void *>( \
326 const_cast <mysql_service_##service##_t **>(&name))) \
327 }
328
329/**
330 Use this macro to reference the service placeholder as defined by the
331 REQUIRES_SERVICE_PLACEHOLDER macro.
332
333Example:
334 REQUIRES_SERVICE_PLACEHOLDER(foo);
335
336 ...
337
338 code() {
339 ....
340 SERVICE_PLACEHOLDER(foo)->bar(1);
341 ...
342 }
343
344 BEGIN_COMPONENT_REQUIRES(comp)
345 REQUIRES_SERVICE(foo);
346 END_COMPONENT_REQUIRES(comp)
347
348 @param service A valid service name.
349*/
350#define SERVICE_PLACEHOLDER(service) mysql_service_##service
351
352/**
353 A macro to end the last declaration started with the BEGIN_COMPONENT_REQUIRES.
354*/
355#define END_COMPONENT_REQUIRES() \
356 { NULL, NULL } \
357 }
358
359/**
360 A macro to specify metadata of the component. Creates a list of metadata.
361 Only a series of METADATA macros are expected to be used after this macro and
362 before the END_COMPONENT_METADATA counterpart.
363
364 @param name Name of component.
365*/
366#define BEGIN_COMPONENT_METADATA(name) \
367 static struct mysql_metadata_ref_t __##name##_metadata[] = {
368/**
369 Adds a Service requirement with a pointer to placeholder to the list of
370 components.
371
372 @param key A string name of the metadata to add.
373 @param value A string value of the metadata to add.
374*/
375#define METADATA(key, value) \
376 { key, value }
377
378/**
379 A macro to end the last declaration started with the BEGIN_COMPONENT_METADATA.
380*/
381#define END_COMPONENT_METADATA() \
382 { NULL, NULL } \
383 }
384
385/* On Windows, exports from DLL need to be declared.
386 Also, plug-in needs to be declared as extern "C" because MSVC
387 unlike other compilers, uses C++ mangling for variables not only
388 for functions. */
389#if defined(_MSC_VER) /* Microsoft */
390#ifdef __cplusplus
391#define DLL_EXPORT extern "C" __declspec(dllexport)
392#define DLL_IMPORT extern "C" __declspec(dllimport)
393#else
394#define DLL_EXPORT __declspec(dllexport)
395#define DLL_IMPORT __declspec(dllimport)
396#endif
397#else /* non _MSC_VER */
398#ifdef __cplusplus
399#define DLL_EXPORT extern "C" __attribute__((visibility("default")))
400#define DLL_IMPORT
401#else
402#define DLL_EXPORT __attribute__((visibility("default")))
403#define DLL_IMPORT
404#endif
405#endif
406
407/**
408 Creates a list of component implementations included in this dynamic library.
409 It can be used only once in whole library. It defines an entry point method
410 for library to be used with the Dynamic Loader. A list of pointers to
411 Component structures is required after this macro up to the usage of
412 the END_DECLARE_LIBRARY_COMPONENTS macro. Current implementation of the
413 Dynamic Loader supports only one Component being specified in the library.
414*/
415#define DECLARE_LIBRARY_COMPONENTS \
416 mysql_component_t *library_components_list = {
417/**
418 A macro to end the last declaration started with the
419 DECLARE_LIBRARY_COMPONENTS.
420*/
421#define END_DECLARE_LIBRARY_COMPONENTS \
422 } \
423 ; \
424 DLL_EXPORT mysql_component_t *list_components() { \
425 return library_components_list; \
426 }
427
428/**
429 Defines a reference to the specified Component data info structure.
430*/
431#define COMPONENT_REF(name) mysql_component_##name
432
433/**
434 This is the component module entry function, used to get the component's
435 structure to register the required services.
436*/
437#define COMPONENT_ENTRY_FUNC "list_components"
438
439#endif /* COMPONENT_IMPLEMENTATION_H */
Specifies macros to define Service Implementations.