The Component for the Dynamic Loader needs to be a dynamic library (for example .so or .dll) with specified entry-point method.
The only exception is the MySQL server, for which, for now, it will be statically linked. All these implementation details are hidden away by macros defined in header files. All macros to define Services are specified in service.h, for defining Service Implementations in service_implementation.h and for specifying Components in component_implementation.h.
The Component example
Example Components are located in components/example directory. These Components are used also for unit and MTR test, which assures these Components are fully functional and they quality is maintained. The example Services are defined in example_services.h, while implemented in three example Components defined in files example_component1.cc, example_component2.cc, and example_component3.cc. These files are specifically prepared to be used as examples as they provide simplicity and an extensive documentation. The following tutorial bases on these Components and will try to show a process to create similar.
Services defined in the example
Example contains definition of 3 Services which will be used to show a general idea of services, basic implementations and simple example of one of concepts possible with the Component Infrastructure. These example Services are defined in example_services.h and are s_mysql_greetings, s_mysql_greetings_localization and s_mysql_example_math.
Common problems
Step by step tutorial for creating new Component
The creation of component is a mean to get some functionality exported for the Components infrastructure. It can be divided into several steps:
- List all high level functionalities Component is planned to have implemented. This will assure we know exactly what we need to benefit from next steps. In the example, we would like to have a "Hello, World!" string provider and simple math functions.
- Look for existing Services, that are designed specifically to provide some part of the new functionalities to reuse them, or other that are in any degree similar in functionality, design or use cases to use as an example. The Component infrastructure is highly oriented on reuse of Services and will benefit with every reuse case, as it will decrease total size of Services. In the example the existing base of Services is really small, with the core Components infrastructure Services available only leading to no reuse possible.
- Design list of functions needed to provide all functionalities. Try to make they follow existing patterns and ideas, possibly having some identical to existing ones.
- Try to separate groups of functions that specify some complete part of functionality into separate small Services to improve re-usability. Also, try to separate groups that seem to have more potential to be extended or modified in future, because changing existing Services is forbidden, in such a case this will lead to a lot of functions in Services that will be duplicates and will introduce more boilerplate code to implement them. Remove all functions that can be found in fully reused existing Services.
- Create definitions of Services, ideally one Service per file, or a group of really closely connected Services. In most cases you want to make these definitions public, in case of MySQL that means placing them in include/mysql/components/services/ directory to include them in mysql-dev package. See example_services.h, which in contrary is not made public and resides in example component source directory.
- Create declarations of all handles, the Opaque pointers for all opaque objects that are meant to be returned to the Services users. See usages of DEFINE_SERVICE_HANDLE in registry.h.
- Create basic structure of new Component. Use BEGIN_COMPONENT_PROVIDES, BEGIN_COMPONENT_REQUIRES, BEGIN_COMPONENT_METADATA, DECLARE_COMPONENT and DECLARE_LIBRARY_COMPONENTS. Fill in all information necessary to describe the new Component extensively. The example_component1.cc and example_component2.cc shows how structure should look like, and in example_component3.cc there is an example with additional Service references, for which placeholder definitions are kept in header file of the new Component, see example_component3.h. Note the placeholder for the Registry Service, which is available by default in every component.
- Create implementations of the desired Service interfaces. Implement handles used, as for example my_h_service_iterator_imp and my_h_service_metadata_iterator_imp in registry.cc. Create separate source and header files for each Service or closely connected group of Services. Remember to include the header file for Service Implementation in the Service Implementation source file to have no linkage problems. The Service Implementations in english_greeting_service_imp.cc and simple_example_math_imp.cc are implementations used in example_component1, polish_greeting_service_imp.cc and example_math_wrapping_imp.cc are implementations for example_component2 and example_component3 respectively.
- Make sure component is loaded/initialized before using its services. Atomic variable is_intialized represents the state of the component. Please check the details about the variable from validate_password_imp.cc file.
- Using registry acquire/release services inside component's init/deint functions is not supported. All the required services for the component has to be specified under BEGIN_COMPONENT_REQUIRES section only.