MySQL 26.10.0
Source Code Documentation
mysql_routing.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 2026, 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 ROUTING_MYSQLROUTING_INCLUDED
27#define ROUTING_MYSQLROUTING_INCLUDED
28
32
33/** @file
34 * @brief Defining the class MySQLRouting
35 *
36 * This file defines the main class `MySQLRouting` which is used to configure,
37 * start and manage a connection routing from clients and MySQL servers.
38 *
39 */
40
41#include <atomic>
42#include <chrono>
43#include <memory>
44
45#ifndef _WIN32
46#include <arpa/inet.h>
47#include <netdb.h>
48#include <netinet/in.h>
49#include <netinet/tcp.h>
50#include <sys/socket.h>
51#include <unistd.h>
52#else
53#include <windows.h>
54#include <winsock2.h>
55#include <ws2tcpip.h>
56#endif
57
58#include "connection.h"
60#include "context.h"
61#include "destination.h"
67#include "mysql/harness/plugin.h"
69#include "mysql_router_thread.h"
70#include "mysql_routing_base.h"
74#include "mysqlrouter/routing.h"
76#include "mysqlrouter/uri.h"
77#include "plugin_config.h"
79#include "socket_container.h"
80
81namespace mysql_harness {
82class PluginFuncEnv;
83} // namespace mysql_harness
84
85class MySQLRouting;
86
88 public:
90 const std::string &parent_routing_name)
91 : io_ctx_(io_ctx), parent_routing_name_(parent_routing_name) {}
92
94
97 virtual bool is_open() const = 0;
98
99 virtual void start(MySQLRouting *r, std::list<IoThread> &,
100 WaitableMonitor<bool> &waitable) = 0;
101
102 virtual std::string name() = 0;
103
105
106 protected:
108 // used when the acceptor logs
110};
111
113 public:
115 const std::string &parent_routing_name,
116 const std::string &address, uint16_t port);
117
120 bool is_open() const override;
121
122 void start(MySQLRouting *r, std::list<IoThread> &,
123 WaitableMonitor<bool> &waitable) override;
124
125 std::string name() override;
126
127 private:
130
131 std::string address_;
132 uint16_t port_;
133};
134
135#ifndef _WIN32
137 public:
139 const std::string &parent_routing_name,
140 const std::string &socket_name);
141
144 bool is_open() const override;
145
146 void start(MySQLRouting *r, std::list<IoThread> &,
147 WaitableMonitor<bool> &waitable) override;
148
149 std::string name() override;
150
151 private:
154
155 std::string socket_name_;
156};
157#endif
158
159/** @class MySQLRouting
160 * @brief Manage Connections from clients to MySQL servers
161 *
162 * The class MySQLRouter is used to start a service listening on a particular
163 * TCP port for incoming MySQL Client connection and route these to a MySQL
164 * Server.
165 */
167 public:
168 /** @brief Default constructor
169 *
170 * @param routing_config routing configuration
171 * @param io_ctx IO context for routing connections
172 * @param acceptor_io_ctx IO context for accepting client connections
173 * @param guidelines routing guidelines engine
174 * @param route_name Name of connection routing (can be empty string)
175 * @param client_ssl_ctx SSL context of the client side
176 * @param dest_ssl_ctx SSL contexts of the destinations
177 */
179 const RoutingConfig &routing_config, net::io_context &io_ctx,
180 net::io_context &acceptor_io_ctx,
181 std::shared_ptr<routing_guidelines::Routing_guidelines_engine> guidelines,
182 const std::string &route_name = {},
183 std::shared_ptr<TlsServerContext> client_ssl_ctx = nullptr,
184 DestinationTlsContext *dest_ssl_ctx = nullptr);
185
187 const RoutingConfig &routing_config, net::io_context &io_ctx,
188 std::shared_ptr<routing_guidelines::Routing_guidelines_engine> guidelines,
189 const std::string &route_name = {},
190 std::shared_ptr<TlsServerContext> client_ssl_ctx = nullptr,
191 DestinationTlsContext *dest_ssl_ctx = nullptr);
192
193 /** @brief Runs the service and accept incoming connections
194 *
195 * Runs the connection routing service and starts accepting incoming
196 * MySQL client connections.
197 *
198 * @throw std::runtime_error on errors.
199 *
200 */
202
203 void set_destinations(const std::string &dests);
204
205 /**
206 * Sets the destinations.
207 *
208 * @param dests destinations
209 */
210 void set_destinations_from_dests(
211 const std::vector<mysql_harness::Destination> &dests);
212
213 void set_destinations_from_uri(const mysqlrouter::URI &uri);
214
215 /** @brief Returns timeout when connecting to destination
216 *
217 * @return Timeout in seconds as int
218 */
220 return context_.get_destination_connect_timeout();
221 }
222
223 /** @brief Sets timeout when connecting to destination
224 *
225 * Checks timeout connecting with destination servers.
226 *
227 * @throw std::invalid_argument when an invalid value was provided.
228 *
229 * @param timeout Timeout
230 */
231 void validate_destination_connect_timeout(std::chrono::milliseconds timeout);
232
233 /** @brief Sets maximum active connections
234 *
235 * Sets maximum of active connections. Maximum must be between 1 and
236 * 65535.
237 *
238 * @throw std::invalid_argument when an invalid value was provided.
239 *
240 * @param maximum Max number of connections allowed
241 * @return New value as int
242 */
243 int set_max_connections(int maximum);
244
245 /** @brief Returns maximum active connections
246 *
247 * @return Maximum as int
248 */
249 int get_max_connections() const noexcept override { return max_connections_; }
250
251 /**
252 * create new connection to MySQL Server than can handle client's
253 * traffic and adds it to connection container.
254 *
255 * @param client_socket socket used to transfer data to/from client
256 * @param client_endpoint endpoint of client
257 */
258 template <class ClientProtocol>
259 void create_connection(
260 typename ClientProtocol::socket client_socket,
261 const typename ClientProtocol::endpoint &client_endpoint);
262
263 std::optional<routing::RoutingStrategy> get_routing_strategy()
264 const override {
265 return routing_strategy_;
266 }
267
268 std::vector<mysql_harness::Destination> get_destination_candidates()
269 const override;
270
271 std::vector<MySQLRoutingAPI::ConnData> get_connections() override;
272
273 MySQLRoutingConnectionBase *get_connection(const std::string &) override;
274
276 return destination_manager_.get();
277 }
278
279 void disconnect_all();
280
281 /**
282 * Stop accepting new connections on a listening socket.
283 *
284 * @param shutting_down is plugin shutting down.
285 */
286 void stop_socket_acceptors(const bool shutting_down) override;
287
288 /**
289 * Check if we are accepting connections on a routing socket.
290 *
291 * @retval true if we are accepting connections, false otherwise
292 */
293 bool is_accepting_connections() const override;
294
295 /**
296 * Refresh routing socket acceptor state based on currently usable
297 * destinations.
298 *
299 * @returns std::string on errors.
300 */
301 stdx::expected<void, std::string> refresh_socket_acceptor_state() override;
302
303 /**
304 * In case when routing guideline was updated go through each established
305 * connection and verify if it is allowed according to the new guideline. If
306 * not then such connection is dropped.
307 *
308 * @param affected_routing_sources list of routing guideline route names that
309 * were affected by the guideline update
310 */
311 void on_routing_guidelines_update(
313 &affected_routing_sources);
314
315 /**
316 * Try to update routing guideline with a new guideline.
317 *
318 * @return list of routing guideline route names that were affected by the
319 * guideline update
320 */
322 update_routing_guidelines(const std::string &routing_guidelines_document);
323
324 /**
325 * If the router info was updated then register this info in routing context.
326 *
327 * @param router_info updated router info
328 */
329 void on_router_info_update(
330 const routing_guidelines::Router_info &router_info);
331
332 bool is_standalone() const override { return is_destination_standalone_; }
333
334 private:
335 /** @brief Sets unix socket permissions so that the socket is accessible
336 * to all users (no-op on Windows)
337 * @param socket_file path to socket file
338 *
339 * @throw std::runtime_error if chmod() inside fails
340 */
341 static void set_unix_socket_permissions(const char *socket_file);
342
345
346 stdx::expected<void, std::string> start_accepting_connections();
347 stdx::expected<void, std::string> restart_accepting_connections();
348
349 /** Stop socket acceptors while socket_acceptor_state_mtx_ is held. */
350 void stop_socket_acceptors_unlocked(bool shutting_down);
351
352 stdx::expected<void, std::string> run_with_no_acceptor(
354
355 public:
356 MySQLRoutingContext &get_context() override { return context_; }
357
358 bool is_running() const override { return is_running_; }
359
360 /**
361 * get the purpose of connections to this route.
362 *
363 * - read-write : all statements are treated as "read-write".
364 * - read-only : all statements are treated as "read-only".
365 * - unavailable: it is currently unknown where the statement should go to.
366 *
367 * "Unavailable" is used for read-write splitting where the purpose is
368 * determined per statement, session, ...
369 *
370 * A statement over a read-only server connection may end up on a read-write
371 * server in case all read-only servers aren't reachable. Even if the server
372 * is read-write, the connections purpose is read-only and if the server
373 * changes its role from PRIMARY to SECONDARY, these read-only connections
374 * will not be abort as a SECONDARY is good enough to serve read-only
375 * connections.
376 */
377 mysqlrouter::ServerMode purpose() const override;
378
379 private:
380 bool accept_connections_{true};
381
382 /** Monitor for controlling and notifying socket acceptors. */
383 WaitableMonitor<bool> acceptor_waitable_{false};
384
385 /** @brief wrapper for data used by all connections */
387
390
391 /** @brief Destination object to use when getting next connection */
392 std::unique_ptr<DestinationManager> destination_manager_{nullptr};
393
394 bool is_destination_standalone_{false};
395
396 /** @brief Routing strategy to use when getting next destination */
397 std::optional<routing::RoutingStrategy> routing_strategy_;
398
399 /** @brief access_mode of the servers in the routing */
401
402 /** @brief Maximum active connections
403 *
404 * Maximum number of incoming connections that will be accepted
405 * by this MySQLRouter instances. There is no maximum for outgoing
406 * connections since it is one-to-one with incoming.
407 */
409
410 /** @brief used to unregister from subscription on allowed nodes changes */
412
413 /** @brief container for connections */
415
416 /** Information if the routing plugin is still running. */
417 std::atomic<bool> is_running_{true};
418
419 /** Serializes socket acceptor state transitions. */
421 bool acceptors_started_{false};
422
423 /** Used when the accepting port is been reopened and it failed, to schedule
424 * another retry for standalone-destination(s) route. */
425 net::steady_timer accept_port_reopen_retry_timer_{io_ctx_};
426
427#ifdef FRIEND_TEST
428 FRIEND_TEST(RoutingTests, bug_24841281);
429 FRIEND_TEST(RoutingTests, get_routing_thread_name);
430 FRIEND_TEST(RoutingTests, NoAcceptorRestartRetryAfterRoutingStops);
431 FRIEND_TEST(ClassicProtocolRoutingTest, NoValidDestinations);
432 FRIEND_TEST(TestSetupTcpService, single_addr_ok);
433 FRIEND_TEST(TestSetupTcpService, getaddrinfo_fails);
434 FRIEND_TEST(TestSetupTcpService, socket_fails_for_all_addr);
435 FRIEND_TEST(TestSetupTcpService, socket_fails);
436 FRIEND_TEST(TestSetupTcpService, bind_fails);
437 FRIEND_TEST(TestSetupTcpService, listen_fails);
438#ifndef _WIN32
439 FRIEND_TEST(TestSetupTcpService, setsockopt_fails);
440 FRIEND_TEST(TestSetupNamedSocketService, unix_socket_permissions_failure);
441#endif
442#endif
443
444 std::vector<std::unique_ptr<AcceptingEndpoint>> accepting_endpoints_;
445};
446
447extern "C" {
448extern mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing;
449}
450
451#endif // ROUTING_MYSQLROUTING_INCLUDED
Definition: mysql_routing.h:112
std::string address_
Definition: mysql_routing.h:131
uint16_t port_
Definition: mysql_routing.h:132
net::ip::tcp::acceptor service_
Definition: mysql_routing.h:128
net::ip::tcp::endpoint service_endpoint_
Definition: mysql_routing.h:129
Definition: mysql_routing.h:136
local::stream_protocol::acceptor service_
Definition: mysql_routing.h:152
std::string socket_name_
Definition: mysql_routing.h:155
local::stream_protocol::endpoint service_endpoint_
Definition: mysql_routing.h:153
Definition: mysql_routing.h:87
virtual ~AcceptingEndpoint()
Definition: mysql_routing.h:104
virtual stdx::expected< void, std::error_code > setup()=0
virtual void start(MySQLRouting *r, std::list< IoThread > &, WaitableMonitor< bool > &waitable)=0
virtual std::string name()=0
std::string parent_routing_name_
Definition: mysql_routing.h:109
net::io_context & io_ctx_
Definition: mysql_routing.h:107
AcceptingEndpoint(const AcceptingEndpoint &)=delete
virtual bool is_open() const =0
AcceptingEndpoint(net::io_context &io_ctx, const std::string &parent_routing_name)
Definition: mysql_routing.h:89
virtual stdx::expected< void, std::error_code > cancel()=0
container for connections to MySQL Server.
Definition: connection_container.h:164
Manage destinations for a Connection Routing.
Definition: destination.h:84
TlsClientContext per destination.
Definition: destination_ssl_context.h:42
Facade to avoid a tight coupling between Routing component and actual routing endpoint implementation...
Definition: mysql_routing_base.h:41
Definition: connection.h:47
MySQLRoutingContext holds data used by MySQLRouting (1 per plugin instances) and MySQLRoutingConnecti...
Definition: context.h:54
Manage Connections from clients to MySQL servers.
Definition: mysql_routing.h:166
std::chrono::milliseconds get_destination_connect_timeout() const noexcept
Returns timeout when connecting to destination.
Definition: mysql_routing.h:219
bool is_standalone() const override
Definition: mysql_routing.h:332
MySQLRoutingContext & get_context() override
Definition: mysql_routing.h:356
std::optional< routing::RoutingStrategy > routing_strategy_
Routing strategy to use when getting next destination.
Definition: mysql_routing.h:397
ConnectionContainer connection_container_
container for connections
Definition: mysql_routing.h:414
std::mutex socket_acceptor_state_mtx_
Serializes socket acceptor state transitions.
Definition: mysql_routing.h:420
routing::AccessMode access_mode_
access_mode of the servers in the routing
Definition: mysql_routing.h:400
std::optional< routing::RoutingStrategy > get_routing_strategy() const override
Definition: mysql_routing.h:263
AllowedNodesChangeCallbacksListIterator allowed_nodes_list_iterator_
used to unregister from subscription on allowed nodes changes
Definition: mysql_routing.h:411
DestinationManager * destination_manager() override
Definition: mysql_routing.h:275
std::vector< std::unique_ptr< AcceptingEndpoint > > accepting_endpoints_
Definition: mysql_routing.h:444
MySQLRoutingContext context_
wrapper for data used by all connections
Definition: mysql_routing.h:386
net::io_context & io_ctx_
Definition: mysql_routing.h:388
net::io_context & acceptor_io_ctx_
Definition: mysql_routing.h:389
int max_connections_
Maximum active connections.
Definition: mysql_routing.h:408
bool is_running() const override
Definition: mysql_routing.h:358
int get_max_connections() const noexcept override
Returns maximum active connections.
Definition: mysql_routing.h:249
route specific configuration.
Definition: routing_config.h:40
Monitor can be waited for.
Definition: monitor.h:62
PluginFuncEnv object.
Definition: loader.h:675
Parse and create URIs according to RFC3986.
Definition: uri.h:66
Definition: socket.h:1292
Definition: timer.h:57
Definition: io_context.h:61
Definition: internet.h:678
Definition: expected.h:286
AllowedNodesChangeCallbacksList::iterator AllowedNodesChangeCallbacksListIterator
Definition: destination_nodes_state_notifier.h:51
static int get_connection(MEM_ROOT *mem_root, FEDERATED_SHARE *share)
Definition: ha_federated.cc:608
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
static void run(mysql_harness::PluginFuncEnv *)
Definition: io_plugin.cc:199
mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing
Definition: mrs_component_backend.cc:84
std::string get_routing_thread_name(const std::string &config_name, const std::string &prefix)
return a short string suitable to be used as a thread name
Definition: mysql_routing_common.cc:30
static bool timeout(bool(*wait_condition)())
Timeout function.
Definition: log0meb.cc:499
std::chrono::milliseconds milliseconds
Definition: authorize_manager.cc:70
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Singleton class that stores the application type.
Definition: component_application_type_name.h:31
ServerMode
Definition: datatypes.h:50
stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol)
Definition: socket.h:63
AccessMode
Definition: routing.h:265
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:33
#define ROUTING_EXPORT
Definition: routing_export.h:15
#define ROUTING_PLUGIN_EXPORT
Definition: routing_plugin_export.h:15
case opt name
Definition: sslopt-case.h:29
Information about this Router instance.
Definition: routing_guidelines.h:59
Type for names of Routes changed during routing guidelines document update.
Definition: routing_guidelines.h:324