1 /* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6 
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation.  The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License, version 2.0, for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #ifndef MYSQL_SERVER_PERSISTENT_DYNAMIC_LOADER_H
24 #define MYSQL_SERVER_PERSISTENT_DYNAMIC_LOADER_H
25 
26 #include <mysql/components/service_implementation.h>
27 #include <mysql/components/services/persistent_dynamic_loader.h>
28 #include <mysql/psi/mysql_mutex.h>
29 #include <atomic>
30 #include <map>
31 
32 #include "my_inttypes.h"
33 
34 /*
35   This header file is used in mysql_server component, which is not
36   server-enabled, and can't have following declaration acquired by including
37   mysql headers.
38 */
39 
40 bool persistent_dynamic_loader_init(void *thd);
41 void persistent_dynamic_loader_deinit();
42 
43 /**
44   Allows to wrap another Service Implementation of the Dynamic Loader service
45   and add ability to store a list of groups of loaded components. It reacts on
46   successful invocations of the underlying Dynamic Loader Service Implementation
47   methods load() and unload() and saves changes. It also loads during the start
48   of the MySQL Server all groups of the Components that were still loaded on
49   last MySQL Server shutdown, they are loaded in order of the original loads.
50   It assumes that components does not any not fully-deterministic loads of
51   another Components, which would break dependencies if they are decided to load
52   other Components than last time. The list of groups of Components is stored in
53   the 'mysql.component' table. It is valid to unload only part of the group of
54   the previously loaded group of Components. In such a situation, as long as all
55   dependencies are met, which is assured by the underlying Service
56   Implementation, the rest of Components in group should load successfully after
57   the MySQL Server restart.
58 */
59 class mysql_persistent_dynamic_loader_imp {
60  public:
61   /**
62     Initializes persistence store, loads all groups of components registered in
63     component table. Shouldn't be called multiple times. We assume the order
64     specified by group ID is correct one. This should be assured by dynamic
65     loader as long as it will not allow to unload the component that has
66     dependency on, in case there would be a possibility to switch that
67     dependency to other component that is not to be unloaded. If this is
68     assured, then it will not be possible for components with lower group IDs
69     to have a dependency on component with higher group ID, even after state is
70     restored in this initialization method.
71 
72     @param thdp Current thread execution context
73     @return Status of performed operation
74     @retval false success
75     @retval true failure
76   */
77   static bool init(void *thdp);
78   /**
79     De-initializes persistence loader.
80   */
81   static void deinit();
82 
83   /**
84    Initialisation status of persistence loader. An helper function.
85   */
86   static bool initialized();
87 
88  public: /* service implementations */
89   /**
90     Loads specified group of components by URN, initializes them and
91     registers all service implementations present in these components.
92     Assures all dependencies will be met after loading specified components.
93     The dependencies may be circular, in such case it's necessary to specify
94     all components on cycle to load in one batch. From URNs specified the
95     scheme part of URN (part before "://") is extracted and used to acquire
96     service implementation of scheme component loader service for specified
97     scheme. If the loading process successes then a group of Components by their
98     URN is added to the component table.
99 
100     @param thd_ptr Current thread execution context.
101     @param urns List of URNs of Components to load.
102     @param component_count Number of Components on list to load.
103     @return Status of performed operation
104     @retval false success
105     @retval true failure
106   */
107   static DEFINE_BOOL_METHOD(load, (void *thd_ptr, const char *urns[],
108                                    int component_count));
109 
110   /**
111     Unloads specified group of Components by URN, deinitializes them and
112     unregisters all service implementations present in these components.
113     Assumes, although does not check it, all dependencies of not unloaded
114     components will still be met after unloading specified components.
115     The dependencies may be circular, in such case it's necessary to specify
116     all components on cycle to unload in one batch. From URNs specified the
117     scheme part of URN (part before "://") is extracted and used to acquire
118     service implementation of scheme component loader service for specified
119     scheme. URN specified should be identical to ones specified in load()
120     method, i.e. all letters must have the same case. If the unloading process
121     successes then a group of Components by their URN is added to the component
122     table.
123 
124     @param thd_ptr Current thread execution context.
125     @param urns List of URNs of components to unload.
126     @param component_count Number of components on list to unload.
127     @return Status of performed operation
128     @retval false success
129     @retval true failure
130   */
131   static DEFINE_BOOL_METHOD(unload, (void *thd_ptr, const char *urns[],
132                                      int component_count));
133 
134  private:
135   /**
136     Stores last group ID used in component table. It is initialized on init()
137     on component table scan with maximum group ID used in table.
138   */
139   static std::atomic<uint64> s_group_id;
140   /**
141     Stores mapping of component URNs to their component_id used in component
142     table, to ease row deletion.
143   */
144   static std::map<std::string, uint64> component_id_by_urn;
145   /**
146     Indicates the initialization status of dynamic loader persistence.
147   */
148   static bool is_initialized;
149 
150   /**
151     Serializes access to @ref component_id_by_urn
152   */
153   static mysql_mutex_t component_id_by_urn_mutex;
154 };
155 
156 #endif /* MYSQL_SERVER_PERSISTENT_DYNAMIC_LOADER_H */
157