MySQL 8.4.13
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 <array>
42#include <atomic>
43#include <chrono>
44#include <map>
45#include <memory>
46#include <mutex>
47#include <stdexcept>
48
49#ifndef _WIN32
50#include <arpa/inet.h>
51#include <netdb.h>
52#include <netinet/in.h>
53#include <netinet/tcp.h>
54#include <sys/socket.h>
55#include <unistd.h>
56#else
57#include <windows.h>
58#include <winsock2.h>
59#include <ws2tcpip.h>
60#endif
61
62#include "connection.h"
64#include "context.h"
65#include "destination.h"
71#include "mysql/harness/plugin.h"
73#include "mysql_router_thread.h"
74#include "mysql_routing_base.h"
77#include "mysqlrouter/routing.h"
79#include "mysqlrouter/uri.h"
80#include "plugin_config.h"
81#include "socket_container.h"
82#include "tcp_address.h"
83
84namespace mysql_harness {
85class PluginFuncEnv;
86} // namespace mysql_harness
87
88class MySQLRouting;
89
91 public:
93 const std::string &parent_routing_name)
94 : io_ctx_(io_ctx), parent_routing_name_(parent_routing_name) {}
95
97
100 virtual bool is_open() const = 0;
101
102 virtual void start(MySQLRouting *r, std::list<IoThread> &,
103 WaitableMonitor<bool> &waitable) = 0;
104
105 virtual std::string name() = 0;
106
108
109 protected:
111 // used when the acceptor logs
113};
114
116 public:
118 const std::string &parent_routing_name,
119 const std::string &address, uint16_t port);
120
123 bool is_open() const override;
124
125 void start(MySQLRouting *r, std::list<IoThread> &,
126 WaitableMonitor<bool> &waitable) override;
127
128 std::string name() override;
129
130 private:
133
134 std::string address_;
135 uint16_t port_;
136};
137
138#ifndef _WIN32
140 public:
142 const std::string &parent_routing_name,
143 const std::string &socket_name);
144
147 bool is_open() const override;
148
149 void start(MySQLRouting *r, std::list<IoThread> &,
150 WaitableMonitor<bool> &waitable) override;
151
152 std::string name() override;
153
154 private:
157
158 std::string socket_name_;
159};
160#endif
161
162/** @class MySQLRouting
163 * @brief Manage Connections from clients to MySQL servers
164 *
165 * The class MySQLRouter is used to start a service listening on a particular
166 * TCP port for incoming MySQL Client connection and route these to a MySQL
167 * Server.
168 */
170 public:
171 /** @brief Default constructor
172 *
173 * @param routing_config routing configuration
174 * @param io_ctx IO context for routing connections
175 * @param acceptor_io_ctx IO context for accepting client connections
176 * @param route_name Name of connection routing (can be empty string)
177 * @param client_ssl_ctx SSL context of the client side
178 * @param dest_ssl_ctx SSL contexts of the destinations
179 */
180 MySQLRouting(const RoutingConfig &routing_config, net::io_context &io_ctx,
181 net::io_context &acceptor_io_ctx,
182 const std::string &route_name = {},
183 TlsServerContext *client_ssl_ctx = nullptr,
184 DestinationTlsContext *dest_ssl_ctx = nullptr);
185
186 MySQLRouting(const RoutingConfig &routing_config, net::io_context &io_ctx,
187 const std::string &route_name = {},
188 TlsServerContext *client_ssl_ctx = nullptr,
189 DestinationTlsContext *dest_ssl_ctx = nullptr);
190
191 /** @brief Runs the service and accept incoming connections
192 *
193 * Runs the connection routing service and starts accepting incoming
194 * MySQL client connections.
195 *
196 * @throw std::runtime_error on errors.
197 *
198 */
200
201 /** @brief Sets the destinations from URI
202 *
203 * Sets destinations using the given string. The string should be a comma
204 * separated list of MySQL servers.
205 *
206 * Example of destinations:
207 * "10.0.10.5,10.0.11.6:3307"
208 *
209 * @param csv destinations as comma-separated-values
210 */
211 void set_destinations_from_csv(const std::string &csv);
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 */
219 std::chrono::milliseconds get_destination_connect_timeout() const noexcept {
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
264
265 std::vector<mysql_harness::TCPAddress> get_destinations() const override;
266
267 std::vector<MySQLRoutingAPI::ConnData> get_connections() override;
268
269 MySQLRoutingConnectionBase *get_connection(const std::string &) override;
270
271 RouteDestination *destinations() { return destination_.get(); }
272
273 void disconnect_all();
274
275 /**
276 * Stop accepting new connections on a listening socket.
277 */
278 void stop_socket_acceptors() override;
279
280 /**
281 * Check if we are accepting connections on a routing socket.
282 *
283 * @retval true if we are accepting connections, false otherwise
284 */
285 bool is_accepting_connections() const override;
286
287 /**
288 * Refresh routing socket acceptor state based on currently usable
289 * destinations.
290 *
291 * @returns std::string on errors.
292 */
293 stdx::expected<void, std::string> refresh_socket_acceptor_state() override;
294
295 private:
296 /** @brief Sets unix socket permissions so that the socket is accessible
297 * to all users (no-op on Windows)
298 * @param socket_file path to socket file
299 *
300 * @throw std::runtime_error if chmod() inside fails
301 */
302 static void set_unix_socket_permissions(const char *socket_file);
303
306
307 stdx::expected<void, std::string> start_accepting_connections();
308 stdx::expected<void, std::string> restart_accepting_connections();
309
310 /** Stop socket acceptors while socket_acceptor_state_mtx_ is held. */
311 void stop_socket_acceptors_unlocked();
312
313 public:
314 MySQLRoutingContext &get_context() override { return context_; }
315
316 bool is_running() const override { return is_running_; }
317
318 /**
319 * get the purpose of connections to this route.
320 *
321 * - read-write : all statements are treated as "read-write".
322 * - read-only : all statements are treated as "read-only".
323 * - unavailable: it is currently unknown where the statement should go to.
324 *
325 * "Unavailable" is used for read-write splitting where the purpose is
326 * determined per statement, session, ...
327 *
328 * A statement over a read-only server connection may end up on a read-write
329 * server in case all read-only servers aren't reachable. Even if the server
330 * is read-write, the connections purpose is read-only and if the server
331 * changes its role from PRIMARY to SECONDARY, these read-only connections
332 * will not be abort as a SECONDARY is good enough to serve read-only
333 * connections.
334 */
335 mysqlrouter::ServerMode purpose() const override;
336
337 private:
338 /** Monitor for controlling and notifying socket acceptors. */
339 WaitableMonitor<bool> acceptor_waitable_{false};
340
341 /** @brief wrapper for data used by all connections */
343
346
347 /** @brief Destination object to use when getting next connection */
348 std::unique_ptr<RouteDestination> destination_;
349
350 bool is_destination_standalone_{false};
351
352 /** @brief Routing strategy to use when getting next destination */
354
355 /** @brief access_mode of the servers in the routing */
357
358 /** @brief Maximum active connections
359 *
360 * Maximum number of incoming connections that will be accepted
361 * by this MySQLRouter instances. There is no maximum for outgoing
362 * connections since it is one-to-one with incoming.
363 */
365
366 /** @brief used to unregister from subscription on allowed nodes changes */
368
369 /** @brief container for connections */
371
372 /** Information if the routing plugin is still running. */
373 std::atomic<bool> is_running_{true};
374
375 /** Serializes socket acceptor state transitions. */
377
378 /** Used when the accepting port is been reopened and it failed, to schedule
379 * another retry for standalone-destination(s) route. */
380 net::steady_timer accept_port_reopen_retry_timer_{io_ctx_};
381
382#ifdef FRIEND_TEST
383 FRIEND_TEST(RoutingTests, bug_24841281);
384 FRIEND_TEST(RoutingTests, get_routing_thread_name);
385 FRIEND_TEST(RoutingTests, NoAcceptorRestartRetryAfterRoutingStops);
386 FRIEND_TEST(ClassicProtocolRoutingTest, NoValidDestinations);
387 FRIEND_TEST(TestSetupTcpService, single_addr_ok);
388 FRIEND_TEST(TestSetupTcpService, getaddrinfo_fails);
389 FRIEND_TEST(TestSetupTcpService, socket_fails_for_all_addr);
390 FRIEND_TEST(TestSetupTcpService, socket_fails);
391 FRIEND_TEST(TestSetupTcpService, bind_fails);
392 FRIEND_TEST(TestSetupTcpService, listen_fails);
393#ifndef _WIN32
394 FRIEND_TEST(TestSetupTcpService, setsockopt_fails);
395 FRIEND_TEST(TestSetupNamedSocketService, unix_socket_permissions_failure);
396#endif
397#endif
398
399 std::vector<std::unique_ptr<AcceptingEndpoint>> accepting_endpoints_;
400};
401
402extern "C" {
403extern mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing;
404}
405
406#endif // ROUTING_MYSQLROUTING_INCLUDED
Definition: mysql_routing.h:115
std::string address_
Definition: mysql_routing.h:134
uint16_t port_
Definition: mysql_routing.h:135
net::ip::tcp::acceptor service_
Definition: mysql_routing.h:131
net::ip::tcp::endpoint service_endpoint_
Definition: mysql_routing.h:132
Definition: mysql_routing.h:139
local::stream_protocol::acceptor service_
Definition: mysql_routing.h:155
std::string socket_name_
Definition: mysql_routing.h:158
local::stream_protocol::endpoint service_endpoint_
Definition: mysql_routing.h:156
Definition: mysql_routing.h:90
virtual ~AcceptingEndpoint()
Definition: mysql_routing.h:107
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:112
net::io_context & io_ctx_
Definition: mysql_routing.h:110
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:92
virtual stdx::expected< void, std::error_code > cancel()=0
container for connections to MySQL Server.
Definition: connection_container.h:167
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:44
MySQLRoutingContext holds data used by MySQLRouting (1 per plugin instances) and MySQLRoutingConnecti...
Definition: context.h:59
Manage Connections from clients to MySQL servers.
Definition: mysql_routing.h:169
std::chrono::milliseconds get_destination_connect_timeout() const noexcept
Returns timeout when connecting to destination.
Definition: mysql_routing.h:219
std::unique_ptr< RouteDestination > destination_
Destination object to use when getting next connection.
Definition: mysql_routing.h:348
MySQLRoutingContext & get_context() override
Definition: mysql_routing.h:314
ConnectionContainer connection_container_
container for connections
Definition: mysql_routing.h:370
std::mutex socket_acceptor_state_mtx_
Serializes socket acceptor state transitions.
Definition: mysql_routing.h:376
routing::AccessMode access_mode_
access_mode of the servers in the routing
Definition: mysql_routing.h:356
AllowedNodesChangeCallbacksListIterator allowed_nodes_list_iterator_
used to unregister from subscription on allowed nodes changes
Definition: mysql_routing.h:367
std::vector< std::unique_ptr< AcceptingEndpoint > > accepting_endpoints_
Definition: mysql_routing.h:399
MySQLRoutingContext context_
wrapper for data used by all connections
Definition: mysql_routing.h:342
net::io_context & io_ctx_
Definition: mysql_routing.h:344
net::io_context & acceptor_io_ctx_
Definition: mysql_routing.h:345
RouteDestination * destinations()
Definition: mysql_routing.h:271
int max_connections_
Maximum active connections.
Definition: mysql_routing.h:364
bool is_running() const override
Definition: mysql_routing.h:316
int get_max_connections() const noexcept override
Returns maximum active connections.
Definition: mysql_routing.h:249
routing::RoutingStrategy routing_strategy_
Routing strategy to use when getting next destination.
Definition: mysql_routing.h:353
Manage destinations for a Connection Routing.
Definition: destination.h:174
virtual mysql_harness::TCPAddress get(const std::string &address, uint16_t port)
Gets destination based on address and port.
Definition: destination.cc:122
route specific configuration.
Definition: routing_config.h:40
TLS Context for the server side.
Definition: tls_server_context.h:51
Monitor can be waited for.
Definition: monitor.h:62
PluginFuncEnv object.
Definition: loader.h:673
Parse and create URIs according to RFC3986.
Definition: uri.h:70
Definition: socket.h:1293
Definition: timer.h:57
Definition: io_context.h:61
Definition: internet.h:678
Definition: expected.h:286
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:197
mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing
Definition: routing_plugin.cc:593
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:498
Definition: common.h:42
ServerMode
Definition: datatypes.h:50
stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol)
Definition: socket.h:63
RoutingStrategy get_routing_strategy(const std::string &value)
Returns RoutingStrategy for its literal representation.
Definition: routing.cc:87
AccessMode
Definition: routing.h:259
RoutingStrategy
Routing strategies supported by Routing plugin.
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
AllowedNodesChangeCallbacksList::iterator AllowedNodesChangeCallbacksListIterator
Definition: destination.h:65
case opt name
Definition: sslopt-case.h:29