MySQL 8.4.0
Source Code Documentation
connection_pool.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2021, 2024, 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 MYSQLROUTER_CONNECTION_POOL_INCLUDED
27#define MYSQLROUTER_CONNECTION_POOL_INCLUDED
28
30
31#include <chrono>
32#include <cstdint> // uint32_t
33
34#include <algorithm> // find_if
35#include <concepts>
36#include <list>
37#include <optional>
38
42#include "mysql/harness/tls_types.h" // Ssl
47
48// default max idle server connections set on bootstrap
49static constexpr uint32_t kDefaultMaxIdleServerConnectionsBootstrap{64};
50
51/**
52 * pooled connection.
53 */
55 public:
56 /**
57 * set a remove-callback.
58 *
59 * used when the pooled connection wants to remove itself from the
60 * connection-pool.
61 */
62 void remover(std::function<void()> remover) { remover_ = std::move(remover); }
63
64 /**
65 * calls remove-callback.
66 */
67 void remove_me();
68
69 void reset();
70
71 private:
72 std::function<void()> remover_;
73};
74
75/**
76 * pooled connection.
77 */
78template <class T>
80 public:
82 using connection_type = T;
83
85 : conn_{std::move(conn)}, idle_timer_(conn_.connection()->io_ctx()) {}
86
87 /**
88 * access to conn_.
89 *
90 * allows others to move the connection structs out.
91 */
93
94 const connection_type &connection() const { return conn_; }
95
96 /**
97 * prepares for reusing the connection.
98 */
99 void reset() {
101
102 (void)idle_timer_.cancel();
103 (void)conn_.cancel();
104 }
105
106 friend class ConnectionPool;
107
108 private:
109 /**
110 * wait for idle timeout.
111 */
112 void async_idle(std::chrono::milliseconds idle_timeout) {
113 auto &tmr = idle_timer_;
114
116
117 // if the idle_timer fires, close the connection and remove it from the
118 // pool.
119 tmr.async_wait([this](std::error_code ec) {
120 if (ec) {
121 // either success or cancelled.
122 return;
123 }
124
125 connection_quit(conn_.connection().get(), conn_.channel().ssl());
126 this->remove_me();
127 });
128
130 }
131
132 /**
133 * wait for server message and shutdown.
134 */
136 // for classic we may receive a ERROR for shutdown. Ignore
137 // it and close the connection. for xprotocol we may
138 // receive a NOTICE for shutdown. Ignore it and close the
139 // connection.
140
141 conn_.async_recv([this](std::error_code ec, size_t /* recved */) {
142 if (ec) {
144 // cancel the timer and let that close the connection.
146
147 (void)conn_.close();
148
149 this->remove_me();
150 }
151 return;
152 }
153
154 // discard what has been received.
155 conn_.channel().recv_buffer().clear();
156
157 // wait for the next bytes or connection-close.
159 });
160 }
161
163
165};
166
167/**
168 * connection pool of mysql connections.
169 *
170 * It can contain connections:
171 *
172 * - classic protocol
173 * - to any tcp endpoint.
174 *
175 * It has:
176 *
177 * - a pool, which contains server-side connections without a client-connection
178 * - a stash, which contains server-side connections with a client-connection
179 *
180 */
182 public:
185
187
188 using ConnectionIdentifier = void *;
189
190 ConnectionPool(uint32_t max_pooled_connections,
191 std::chrono::milliseconds idle_timeout)
192 : max_pooled_connections_(max_pooled_connections),
193 idle_timeout_(idle_timeout) {}
194
195 // disable copy
198
199 // disable move
202
203 ~ConnectionPool() = default;
204
205 /**
206 * add a connection to the pool.
207 *
208 * if the pool is full, the connection will be close.
209 */
210 void add(ServerSideConnection conn);
211
212 /**
213 * add connection to the pool if the poll isn't full.
214 */
215 std::optional<ServerSideConnection> add_if_not_full(
217
218 /**
219 * get a connection from the pool that matches a predicate.
220 *
221 * @returns a connection if one exists.
222 */
223 std::optional<ServerSideConnection> pop_if(
224 const std::string &ep,
225 std::predicate<const ServerSideConnection &> auto pred) {
226 return pool_(
227 [this, ep, pred](auto &pool) -> std::optional<ServerSideConnection> {
228 auto key_range = pool.equal_range(ep);
229 if (key_range.first == key_range.second) return std::nullopt;
230
231 auto kv_it = std::find_if(
232 key_range.first, key_range.second,
233 [pred](const auto &kv) { return pred(kv.second.connection()); });
234 if (kv_it == key_range.second) return std::nullopt;
235
236 // found.
237
238 auto pooled_conn = std::move(kv_it->second);
239
240 pool.erase(kv_it);
241
242 pooled_conn.reset();
243
244 ++reused_;
245
246 return std::move(pooled_conn.connection());
247 });
248 }
249
250 /**
251 * number of currently pooled connections.
252 */
253 [[nodiscard]] uint32_t current_pooled_connections() const;
254
255 [[nodiscard]] uint32_t max_pooled_connections() const {
256 return max_pooled_connections_;
257 }
258
259 [[nodiscard]] std::chrono::milliseconds idle_timeout() const {
260 return idle_timeout_;
261 }
262
263 /**
264 * add a server-side connection to the stash.
265 *
266 * @param conn server-side connection to be stashed.
267 * @param from opaque connection-identifier
268 * @param delay allow sharing with other connection after 'delay'
269 * milliseconds.
270 */
271 void stash(ServerSideConnection conn, ConnectionIdentifier from,
272 std::chrono::milliseconds delay);
273
274 // discard all stashed connection and move them to the pool.
275 void discard_all_stashed(ConnectionIdentifier from);
276
277 /**
278 * connection on the stash.
279 */
280 struct Stashed {
281 // constructor for the container's .emplace()
283 std::chrono::steady_clock::time_point tp)
284 : pooled_conn(std::move(pc)), conn_id(ci), after(tp) {}
285
287 ConnectionIdentifier conn_id; //!< opaque connection identifier
288 std::chrono::steady_clock::time_point after; //!< stealable after ...
289 };
290
291 std::optional<ServerSideConnection> unstash_if(
292 const std::string &ep,
293 std::function<bool(const ServerSideConnection &)> pred,
294 bool ignore_sharing_delay = false);
295
296 std::optional<ServerSideConnection> unstash_mine(
297 const std::string &ep, ConnectionIdentifier conn_id);
298
299 /**
300 * number of server-side connections on the stash.
301 */
302 [[nodiscard]] size_t current_stashed_connections() const;
303
304 /**
305 * total number of reused connections.
306 */
307 [[nodiscard]] uint64_t reused_connections() const { return reused_; }
308
309 protected:
310 using pool_type =
311 std::unordered_multimap<std::string,
313 using stash_type = std::unordered_multimap<std::string, Stashed>;
314
315 void erase(pool_type::iterator it);
316
318 const std::chrono::milliseconds idle_timeout_;
319
321
322 // a stash of sharable connections.
323 //
324 // they are associated to a connection.
326
327 void erase_from_stash(stash_type::iterator it);
328
329 uint64_t reused_{};
330};
331
332#endif
connection pool of mysql connections.
Definition: connection_pool.h:181
ConnectionPool & operator=(const ConnectionPool &)=delete
~ConnectionPool()=default
uint32_t max_pooled_connections() const
Definition: connection_pool.h:255
std::chrono::milliseconds idle_timeout() const
Definition: connection_pool.h:259
const uint32_t max_pooled_connections_
Definition: connection_pool.h:317
void * ConnectionIdentifier
Definition: connection_pool.h:188
std::unordered_multimap< std::string, PooledConnection< ServerSideConnection > > pool_type
Definition: connection_pool.h:312
ConnectionPool(uint32_t max_pooled_connections, std::chrono::milliseconds idle_timeout)
Definition: connection_pool.h:190
uint64_t reused_connections() const
total number of reused connections.
Definition: connection_pool.h:307
const std::chrono::milliseconds idle_timeout_
Definition: connection_pool.h:318
std::optional< ServerSideConnection > pop_if(const std::string &ep, std::predicate< const ServerSideConnection & > auto pred)
get a connection from the pool that matches a predicate.
Definition: connection_pool.h:223
ConnectionPool(ConnectionPool &&)=delete
ConnectionPool & operator=(ConnectionPool &&)=delete
std::unordered_multimap< std::string, Stashed > stash_type
Definition: connection_pool.h:313
ConnectionPool(const ConnectionPool &)=delete
Monitor pattern.
Definition: monitor.h:39
pooled connection.
Definition: connection_pool.h:54
void remover(std::function< void()> remover)
set a remove-callback.
Definition: connection_pool.h:62
void remove_me()
calls remove-callback.
Definition: connection_pool.cc:98
std::function< void()> remover_
Definition: connection_pool.h:72
void reset()
Definition: connection_pool.cc:103
pooled connection.
Definition: connection_pool.h:79
connection_type & connection()
access to conn_.
Definition: connection_pool.h:92
T connection_type
Definition: connection_pool.h:82
net::steady_timer idle_timer_
Definition: connection_pool.h:164
PooledConnection(connection_type conn)
Definition: connection_pool.h:84
void async_recv_message()
wait for server message and shutdown.
Definition: connection_pool.h:135
mysql_harness::Ssl Ssl
Definition: connection_pool.h:81
void reset()
prepares for reusing the connection.
Definition: connection_pool.h:99
void async_idle(std::chrono::milliseconds idle_timeout)
wait for idle timeout.
Definition: connection_pool.h:112
const connection_type & connection() const
Definition: connection_pool.h:94
connection_type conn_
Definition: connection_pool.h:162
Definition: timer.h:57
size_t cancel()
Definition: timer.h:101
size_t expires_after(const duration &d)
Definition: timer.h:114
static void connection_quit(ConnectionBase *conn, SSL *ssl)
Definition: connection_pool.cc:43
static constexpr uint32_t kDefaultMaxIdleServerConnectionsBootstrap
Definition: connection_pool.h:49
#define CONNECTION_POOL_EXPORT
Definition: connection_pool_export.h:15
if(!(yy_init))
Definition: lexyy.cc:1144
std::string HARNESS_EXPORT reset()
get 'reset attributes' ESC sequence.
Definition: vt100.cc:37
Container::const_iterator find_if(const Container &c, Find_if &&find_if)
Definition: generic.h:54
std::unique_ptr< SSL, mysql_harness::impl::Deleter_SSL > Ssl
Definition: tls_types.h:48
std::error_condition make_error_condition(net::stream_errc e) noexcept
Definition: buffer.h:107
static mysql_service_status_t add(reference_caching_channel channel, const char *implementation_name) noexcept
Definition: component.cc:127
Definition: gcs_xcom_synode.h:64
connection on the stash.
Definition: connection_pool.h:280
ConnectionIdentifier conn_id
opaque connection identifier
Definition: connection_pool.h:287
Stashed(PooledConnection< ServerSideConnection > pc, ConnectionIdentifier ci, std::chrono::steady_clock::time_point tp)
Definition: connection_pool.h:282
std::chrono::steady_clock::time_point after
stealable after ...
Definition: connection_pool.h:288
PooledConnection< ServerSideConnection > pooled_conn
pooled connection.
Definition: connection_pool.h:286
Definition: my_base.h:1125