MySQL 9.5.0
Source Code Documentation
endpoint_base.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2024, 2025, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTER_SRC_MYSQL_REST_SERVICE_INCLUDE_MRS_INTERFACE_ENDPOINT_BASE_H_
27#define ROUTER_SRC_MYSQL_REST_SERVICE_INCLUDE_MRS_INTERFACE_ENDPOINT_BASE_H_
28
29#include <map>
30#include <memory>
31#include <mutex>
32#include <shared_mutex>
33#include <vector>
34
35#include "http/base/uri.h"
40
42
44
45namespace mrs {
46namespace interface {
47
48/*
49 * Base class to build the Endpoint hierarchy
50 *
51 * Following step should be done manually by
52 * the instance user.
53 * change_parent({});
54 * It's important because parent holds the pointer to this instance in
55 * endpoints_ /shared_ptr/.
56 */
57class EndpointBase : public std::enable_shared_from_this<EndpointBase> {
58 public:
60 using EndpointBasePtr = std::shared_ptr<EndpointBase>;
62 using Children = std::vector<EndpointBasePtr>;
64 using EndpointConfigurationPtr = std::shared_ptr<EndpointConfiguration>;
66 using HandlerPtr = std::shared_ptr<Handler>;
68 using OptionalIndexNames = std::optional<std::vector<std::string>>;
69
70 public:
72 : configuration_{configuration} {}
73 virtual ~EndpointBase() = default;
74
75 /*
76 * Virtual methods, to overwrite in subclass.
77 */
78 public:
79 virtual UniversalId get_id() const = 0;
80 virtual UniversalId get_parent_id() const = 0;
82 virtual std::optional<std::string> get_options() const = 0;
83 virtual std::string get_my_url_path_part() const = 0;
84
85 protected:
87 virtual std::string get_my_url_part() const = 0;
88
89 virtual bool does_this_node_require_authentication() const = 0;
90
91 /*
92 * Predefined behaviors.
93 */
94 public:
95 virtual bool required_authentication() const {
96 bool parents_required_authnetication = false;
97 auto parent = get_parent_ptr();
98
99 if (parent) {
100 parents_required_authnetication = parent->required_authentication();
101 }
102
103 return parents_required_authnetication ||
104 does_this_node_require_authentication();
105 }
106
107 virtual std::string get_url_path() const {
108 auto parent = get_parent_ptr();
109
110 return (parent ? parent->get_url_path() : std::string()) +
111 get_my_url_path_part();
112 }
113
114 virtual Uri get_url() const {
115 auto parent = get_parent_ptr();
116 Uri uri{parent ? parent->get_url() : Uri{}};
117 uri.set_path(uri.get_path() + get_my_url_part());
118
119 return uri;
120 }
121
122 /*
123 * enable-public
124 *
125 * The 'override' methods may expose handlers (http endpoints) that
126 * should be visible/available through HTTP interface.
127 */
128 virtual void activate_public() {}
129
130 /*
131 * enable-private
132 *
133 * The 'override' methods may initialize some per endpoint
134 * data that may be used internally in dependencies from other endpoints.
135 */
136 virtual void activate_private() {}
137
138 /*
139 * disable / deactivate
140 *
141 * The endpoint is still in memory, be should no
142 * expose any handlers (http endpoint) nor should be
143 * used internally.
144 */
145 virtual void deactivate() {}
146
148 auto parent = get_parent_ptr();
149
150 if (!parent) return EnabledType::EnabledType_none;
151
152 auto this_enabled_level = get_this_node_enabled_level();
153
154 if (this_enabled_level == EnabledType::EnabledType_none)
156
157 auto parent_enabled_level = parent->get_enabled_level();
158
159 if (this_enabled_level == EnabledType::EnabledType_public)
160 return parent_enabled_level;
161
162 return parent_enabled_level == EnabledType::EnabledType_public
164 : parent_enabled_level;
165 }
166
168 auto lock = std::unique_lock<std::shared_mutex>(endpoints_access_);
169 change_parent(parent);
170 changed();
171 }
172
174 auto parent_old = get_parent_ptr();
175
176 if (parent_old == parent_new) return;
177 if (parent_old) parent_old->remove_child_endpoint(get_id());
178 if (parent_new) parent_new->add_child_endpoint(shared_from_this());
179
180 parent_ = parent_new;
181 }
182
183 EndpointConfigurationPtr get_configuration() const { return configuration_; }
184
185 const EndpointBasePtr get_parent_ptr() const { return parent_.lock(); }
186 EndpointBasePtr get_parent_ptr() { return parent_.lock(); }
187
189 auto lock = std::unique_lock<std::shared_mutex>(endpoints_access_);
190
191 endpoints_.insert_or_assign(child_ptr->get_id(), child_ptr);
192 }
193
194 void remove_child_endpoint(const UniversalId &child_id) {
195 auto lock = std::unique_lock<std::shared_mutex>(endpoints_access_);
196 endpoints_.erase(child_id);
197 }
198
201 result.reserve(endpoints_.size());
202 for (auto [_, child] : endpoints_) {
203 result.push_back(child);
204 }
205
206 return result;
207 }
208
209 /*
210 * Generic methods
211 */
212 protected:
213 std::optional<EnabledType> last_state_;
214 static const char *get_state_name(EnabledType et) {
215 switch (et) {
217 return "disabled";
219 return "private";
221 return "public";
222 }
223 assert(false && "Missing 'enums' value inside the switch.");
224 return "unknown";
225 }
226 void log_update() {
227 auto current = get_enabled_level();
228 if (last_state_ != current) {
229 last_state_ = current;
230
231 log_info("Endpoint(id=%s, path='%s'%s) changed state to '%s'",
232 get_id().to_string().c_str(), get_url().join().c_str(),
233 get_extra_update_data().c_str(), get_state_name(current));
234 }
235 }
236
237 virtual std::string get_extra_update_data() { return {}; }
238
239 virtual void update() {
240 log_update();
241 switch (get_enabled_level()) {
243 activate_public();
244 break;
246 activate_private();
247 break;
249 deactivate();
250 break;
251 }
252 }
253
255 auto it = endpoints_.find(id);
256 if (it == endpoints_.end()) return {};
257
258 return it->second;
259 }
260
261 /*
262 * Update current endpoint and all its children
263 *
264 * Until now the method was called from other methods like:
265 * `change_parent`, `set`. This was changed because too many
266 * updates were generated. Currently, the user of the class
267 * is responsible to call `changed` in right moment.
268 */
269 void changed() {
270 update();
271 // Make a copy of shared-pointers that hold our children.
272 // This way we can operate in thread safe way.
273 auto children = get_children();
274
275 for (auto &child : children) child->changed();
276 }
277
278 protected:
279 std::shared_mutex endpoints_access_;
280 std::map<UniversalId, EndpointBasePtr> endpoints_;
281 std::weak_ptr<EndpointBase> parent_;
283};
284
285} // namespace interface
286} // namespace mrs
287
288#endif /* ROUTER_SRC_MYSQL_REST_SERVICE_INCLUDE_MRS_INTERFACE_ENDPOINT_BASE_H_ \
289 */
Definition: uri.h:40
virtual void set_path(const std::string &path)
Definition: uri.cc:162
Definition: endpoint_base.h:57
EndpointBasePtr get_parent_ptr()
Definition: endpoint_base.h:186
std::optional< std::vector< std::string > > OptionalIndexNames
Definition: endpoint_base.h:68
virtual std::string get_extra_update_data()
Definition: endpoint_base.h:237
void changed()
Definition: endpoint_base.h:269
virtual void activate_private()
Definition: endpoint_base.h:136
virtual UniversalId get_parent_id() const =0
virtual OptionalIndexNames get_index_files()=0
const EndpointBasePtr get_parent_ptr() const
Definition: endpoint_base.h:185
std::optional< EnabledType > last_state_
Definition: endpoint_base.h:213
EndpointBasePtr get_child_by_id(const UniversalId &id) const
Definition: endpoint_base.h:254
virtual UniversalId get_id() const =0
std::vector< EndpointBasePtr > Children
Definition: endpoint_base.h:62
mrs::database::entry::EnabledType EnabledType
Definition: endpoint_base.h:59
EndpointConfigurationPtr get_configuration() const
Definition: endpoint_base.h:183
virtual std::optional< std::string > get_options() const =0
virtual void update()
Definition: endpoint_base.h:239
virtual std::string get_my_url_path_part() const =0
void log_update()
Definition: endpoint_base.h:226
virtual std::string get_my_url_part() const =0
virtual void deactivate()
Definition: endpoint_base.h:145
void remove_child_endpoint(const UniversalId &child_id)
Definition: endpoint_base.h:194
std::weak_ptr< EndpointBase > parent_
Definition: endpoint_base.h:281
std::shared_mutex endpoints_access_
Definition: endpoint_base.h:279
std::map< UniversalId, EndpointBasePtr > endpoints_
Definition: endpoint_base.h:280
std::shared_ptr< EndpointBase > EndpointBasePtr
Definition: endpoint_base.h:60
void set_parent(EndpointBasePtr parent)
Definition: endpoint_base.h:167
EndpointBase(EndpointConfigurationPtr configuration)
Definition: endpoint_base.h:71
virtual bool does_this_node_require_authentication() const =0
virtual EnabledType get_enabled_level() const
Definition: endpoint_base.h:147
static const char * get_state_name(EnabledType et)
Definition: endpoint_base.h:214
virtual std::string get_url_path() const
Definition: endpoint_base.h:107
mrs::database::entry::UniversalId UniversalId
Definition: endpoint_base.h:61
virtual void activate_public()
Definition: endpoint_base.h:128
virtual Uri get_url() const
Definition: endpoint_base.h:114
EndpointConfigurationPtr configuration_
Definition: endpoint_base.h:282
void change_parent(EndpointBasePtr parent_new)
Definition: endpoint_base.h:173
void add_child_endpoint(EndpointBasePtr child_ptr)
Definition: endpoint_base.h:188
virtual bool required_authentication() const
Definition: endpoint_base.h:95
std::shared_ptr< Handler > HandlerPtr
Definition: endpoint_base.h:66
virtual ~EndpointBase()=default
std::shared_ptr< EndpointConfiguration > EndpointConfigurationPtr
Definition: endpoint_base.h:64
virtual EnabledType get_this_node_enabled_level() const =0
Children get_children()
Definition: endpoint_base.h:199
Definition: endpoint_configuration.h:35
Definition: rest_handler.h:141
#define log_info(...)
Definition: log_client.h:153
static std::string to_string(const LEX_STRING &str)
Definition: lex_string.h:50
Logging interface for using and extending the logging subsystem.
#define IMPORT_LOG_FUNCTIONS()
convenience macro to avoid common boilerplate
Definition: logging.h:331
static uint update
Definition: myisamlog.cc:94
Request::Uri Uri
Definition: request.cc:36
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
EnabledType
Definition: entry.h:56
@ EnabledType_private
Definition: entry.h:59
@ EnabledType_none
Definition: entry.h:57
@ EnabledType_public
Definition: entry.h:58
DbServiceEndpoint::EndpointConfiguration EndpointConfiguration
Definition: db_service_endpoint.cc:49
Definition: authorize_manager.h:48
mrs::database::entry::UniversalId UniversalId
Definition: universal_id.h:33
std::string join(const detail::range auto &rng, std::string_view delim)
join elements of a range into a string separated by a delimiter.
Definition: string.h:74
pid_type get_id()
Definition: process.h:48
struct result result
Definition: result.h:34
required string configuration
Definition: replication_asynchronous_connection_failover.proto:49
Definition: result.h:30
static task_env * deactivate(task_env *t)
Definition: task.cc:564
#define _(str)
Definition: win_i18n.h:33