MySQL 9.1.0
Source Code Documentation
metadata_cache.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2016, 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_METADATA_CACHE_INCLUDED
27#define MYSQLROUTER_METADATA_CACHE_INCLUDED
28
30
31#include <atomic>
32#include <chrono>
33#include <exception>
34#include <list>
35#include <map>
36#include <stdexcept>
37#include <string>
38#include <vector>
39
40#include "my_rapidjson_size_t.h"
41
42#include <rapidjson/document.h>
43
45#include "mysql_router_thread.h"
51#include "tcp_address.h"
52
53namespace metadata_cache {
54constexpr const uint16_t kDefaultMetadataPort{32275};
55constexpr const std::string_view kDefaultMetadataAddress{"127.0.0.1:32275"};
56constexpr const std::string_view kDefaultMetadataUser{""};
57constexpr const std::string_view kDefaultMetadataPassword{""};
58constexpr const std::chrono::milliseconds kDefaultAuthCacheTTL{
60constexpr const std::chrono::milliseconds kDefaultAuthCacheRefreshInterval{
61 2000};
62// blank cluster name means pick the 1st (and only) cluster
63constexpr const std::string_view kDefaultMetadataCluster{""};
64constexpr const unsigned int kDefaultConnectTimeout{
66constexpr const unsigned int kDefaultReadTimeout{
68
69/** @class metadata_error
70 * Class that represents all the exceptions that are thrown while fetching the
71 * metadata.
72 *
73 */
74class metadata_error : public std::runtime_error {
75 public:
76 explicit metadata_error(const std::string &what_arg)
77 : std::runtime_error(what_arg) {}
78};
79
80/**
81 * @brief Abstract class that provides interface for listener on
82 * cluster status changes.
83 *
84 * When state of cluster is changed, notify function is called.
85 */
87 public:
88 /**
89 * @brief Callback function that is called when state of cluster is
90 * changed.
91 *
92 * @param cluster_topology current cluster topology
93 * @param md_servers_reachable true if metadata changed, false if metadata
94 * unavailable
95 * @param view_id current metadata view_id in case of ReplicaSet cluster
96 */
97 virtual void notify_instances_changed(const ClusterTopology &cluster_topology,
98 const bool md_servers_reachable,
99 const uint64_t view_id) = 0;
100
102 // disable copy as it isn't needed right now. Feel free to enable
103 // must be explicitly defined though.
105 const ClusterStateListenerInterface &) = delete;
107 const ClusterStateListenerInterface &) = delete;
109};
110
111/**
112 * @brief Abstract class that provides interface for listener on
113 * whether the listening sockets acceptors state should be updated.
114 */
116 public:
117 /**
118 * @brief Callback function that is called when the state of the sockets
119 * acceptors is handled during the metadata refresh.
120 *
121 * @param instances list of the current cluster nodes
122 */
124 const metadata_cache::cluster_nodes_list_t &instances) = 0;
125
127
129 default;
131 const AcceptorUpdateHandlerInterface &) = default;
132
135 default;
136
138};
139
140/**
141 * Abstract class that provides interface for listener on metadata refresh.
142 */
144 public:
146
148 default;
150 default;
151
153 const MetadataRefreshListenerInterface &) = default;
156
157 /**
158 * Callback that is going to be used on each metadata refresh.
159 *
160 * @param[in] instances_changed Informs if the cluster topology has changed
161 * since last md refresh.
162 * @param[in] cluster_topology current cluster topology
163 */
164 virtual void on_md_refresh(const bool instances_changed,
165 const ClusterTopology &cluster_topology) = 0;
166
168};
169/**
170 * @brief Abstract class that provides interface for adding and removing
171 * observers on cluster status changes.
172 *
173 * When state of cluster is changed, then
174 * ClusterStateListenerInterface::notify function is called
175 * for every registered observer.
176 */
178 public:
179 /**
180 * @brief Register observer that is notified when there is a change in the
181 * cluster nodes setup/state discovered.
182 *
183 * @param listener Observer object that is notified when cluster nodes
184 * state is changed.
185 *
186 * @throw std::runtime_error if metadata cache not initialized
187 */
189
190 /**
191 * @brief Unregister observer previously registered with add_state_listener()
192 *
193 * @param listener Observer object that should be unregistered.
194 *
195 * @throw std::runtime_error if metadata cache not initialized
196 */
198 ClusterStateListenerInterface *listener) = 0;
199
201 // disable copy as it isn't needed right now. Feel free to enable
202 // must be explicitly defined though.
204 const ClusterStateNotifierInterface &) = delete;
206 const ClusterStateNotifierInterface &) = delete;
208};
209
210/**
211 * @brief Metadata TTL configuration
212 */
214 // The time to live for the cached data
215 std::chrono::milliseconds ttl;
216
217 // auth_cache_ttl TTL of the rest user authentication data
218 std::chrono::milliseconds auth_cache_ttl;
219
220 // auth_cache_refresh_interval Refresh rate of the rest user authentication
221 // data
222 std::chrono::milliseconds auth_cache_refresh_interval;
223};
224
227 public:
228 /** @brief Initialize a MetadataCache object and start caching
229 *
230 * The metadata_cache::cache_init function will initialize a MetadataCache
231 * object using the given arguments and store it globally using the given
232 * cache_name.
233 *
234 * Parameters host, port, user, password are used to setup the connection with
235 * the metadata server.
236 *
237 * Cache name given by cache_name can be empty, but must be unique.
238 *
239 * The parameters connection_timeout and connection_attempts are used when
240 * connected to the metadata server.
241 *
242 * Throws a std::runtime_error when the cache object was already
243 * initialized.
244 *
245 * @param cluster_type type of the cluster the metadata cache object will
246 * represent (GR or ReplicaSet)
247 * @param router_id id of the router in the cluster metadata
248 * @param clusterset_id UUID of the ClusterSet the Cluster belongs to (if
249 * bootstrapped as a ClusterSet, empty otherwise)
250 * @param metadata_servers The list of cluster metadata servers
251 * @param ttl_config metadata TTL configuration
252 * @param ssl_options SSL related options for connection
253 * @param target_cluster object identifying the Cluster this operation refers
254 * to
255 * @param session_config Metadata MySQL session configuration
256 * @param router_attributes Router attributes to be registered in the metadata
257 * @param thread_stack_size memory in kilobytes allocated for thread's stack
258 * @param use_cluster_notifications Flag indicating if the metadata cache
259 * should use cluster notifications as an
260 * additional trigger for metadata refresh
261 * (only available for GR cluster type)
262 * @param view_id last known view_id of the cluster metadata (only relevant
263 * for ReplicaSet cluster)
264 *
265 */
266 virtual void cache_init(
267 const mysqlrouter::ClusterType cluster_type, const unsigned router_id,
268 const std::string &clusterset_id,
269 const metadata_servers_list_t &metadata_servers,
270 const MetadataCacheTTLConfig &ttl_config,
271 const mysqlrouter::SSLOptions &ssl_options,
272 const mysqlrouter::TargetCluster &target_cluster,
273 const MetadataCacheMySQLSessionConfig &session_config,
274 const RouterAttributes &router_attributes,
275 size_t thread_stack_size = mysql_harness::kDefaultStackSizeInKiloBytes,
276 bool use_cluster_notifications = false, const uint64_t view_id = 0) = 0;
277
278 virtual void instance_name(const std::string &inst_name) = 0;
279 virtual std::string instance_name() const = 0;
280
281 virtual bool is_initialized() noexcept = 0;
282
283 virtual bool fetch_whole_topology() const = 0;
284 virtual void fetch_whole_topology(bool val) = 0;
285
286 virtual mysqlrouter::ClusterType cluster_type() const = 0;
287
288 /**
289 * @brief Start the metadata cache
290 */
291 virtual void cache_start() = 0;
292
293 /**
294 * @brief Teardown the metadata cache
295 */
296 virtual void cache_stop() noexcept = 0;
297
298 /** @brief Returns list of managed server in a HA cluster
299 * * Returns a list of MySQL servers managed by the topology for the given
300 * HA cluster.
301 *
302 * @return List of ManagedInstance objects
303 */
304 virtual cluster_nodes_list_t get_cluster_nodes() = 0;
305
306 /** @brief Return object containing current cluster topology.
307 *
308 * @return List of ManagedInstance objects
309 */
310 virtual ClusterTopology get_cluster_topology() = 0;
311
312 /** @brief Wait until there's a primary member in the cluster
313 *
314 * To be called when the primary member of a single-primary cluster is down
315 * and we want to wait until one becomes elected.
316 *
317 * @param primary_server_uuid - server_uuid of the PRIMARY that shall be
318 * failover from.
319 * @param timeout - amount of time to wait for a failover, in seconds
320 * @return true if a primary member exists
321 */
322 virtual bool wait_primary_failover(const std::string &primary_server_uuid,
323 const std::chrono::seconds &timeout) = 0;
324
325 /**
326 * @brief Register observer that is notified when there is a change in the
327 * cluster nodes setup/state discovered.
328 *
329 * @param listener Observer object that is notified when cluster nodes
330 * state is changed.
331 */
332 void add_state_listener(ClusterStateListenerInterface *listener) override = 0;
333
334 /**
335 * @brief Unregister observer previously registered with add_state_listener()
336 *
337 * @param listener Observer object that should be unregistered.
338 */
339 void remove_state_listener(ClusterStateListenerInterface *listener) override =
340 0;
341
342 /**
343 * @brief Register observer that is notified when the state of listening
344 * socket acceptors should be updated on the next metadata refresh.
345 *
346 * @param listener Observer object that is notified when replicaset nodes
347 * state is changed.
348 */
349 virtual void add_acceptor_handler_listener(
350 AcceptorUpdateHandlerInterface *listener) = 0;
351
352 /**
353 * @brief Unregister observer previously registered with
354 * add_acceptor_handler_listener()
355 *
356 * @param listener Observer object that should be unregistered.
357 */
358 virtual void remove_acceptor_handler_listener(
359 AcceptorUpdateHandlerInterface *listener) = 0;
360
361 /**
362 * Register observer that is notified when the metadata refresh is triggered.
363 *
364 * @param listener Observer object that is notified on metadata refresh.
365 */
366 virtual void add_md_refresh_listener(
368
369 /**
370 * @brief Unregister observer previously registered with
371 * add_md_refresh_listener()
372 *
373 * @param listener Observer object that should be unregistered.
374 */
375 virtual void remove_md_refresh_listener(
377
378 /** @brief Get authentication data (password hash and privileges) for the
379 * given user.
380 *
381 * @param username - name of the user for which the authentidation data
382 * is requested
383 * @return true and password hash with privileges - authentication data
384 * requested for the given user.
385 * @return false and empty data set - username is not found or authentication
386 * data expired.
387 */
388 virtual std::pair<bool, std::pair<std::string, rapidjson::Document>>
389 get_rest_user_auth_data(const std::string &username) const = 0;
390
391 /**
392 * @brief Enable fetching authentication metadata when using metadata_cache
393 * http authentication backend.
394 */
395 virtual void enable_fetch_auth_metadata() = 0;
396
397 /**
398 * Force cache update in refresh loop.
399 */
400 virtual void force_cache_update() = 0;
401
402 /**
403 * Check values of auth_cache_ttl and auth_cache_refresh_interval timers.
404 *
405 * @throw std::invalid_argument for each of the following scenarios:
406 * 1. auth_cache_ttl < ttl
407 * 2. auth_cache_refresh_interval < ttl
408 * 3. auth_cache_refresh_interval > auth_cache_ttl
409 */
410 virtual void check_auth_metadata_timers() const = 0;
411
412 /**
413 * Toggle socket acceptors state update on next metadata refresh.
414 */
415 virtual void handle_sockets_acceptors_on_md_refresh() = 0;
416
418 // disable copy as it isn't needed right now. Feel free to enable
419 // must be explicitly defined though.
420 explicit MetadataCacheAPIBase(const MetadataCacheAPIBase &) = delete;
421 MetadataCacheAPIBase &operator=(const MetadataCacheAPIBase &) = delete;
422 ~MetadataCacheAPIBase() override = default;
423
427 std::chrono::system_clock::time_point last_refresh_succeeded;
428 std::chrono::system_clock::time_point last_refresh_failed;
429
432 };
433
436
437 virtual std::chrono::milliseconds ttl() const = 0;
438
439 using metadata_factory_t = std::function<std::shared_ptr<MetaData>(
440 mysqlrouter::ClusterType cluster_type,
442 const mysqlrouter::SSLOptions &ssl_options,
443 const bool use_cluster_notifications, unsigned view_id)>;
444
446};
447
448// This provides a factory method that returns a pluggable instance
449// to the underlying transport layer implementation. The transport
450// layer provides the means from which the metadata is
451// fetched.
452
453std::shared_ptr<MetaData> metadata_factory_get_instance(
454 const mysqlrouter::ClusterType cluster_type,
456 const mysqlrouter::SSLOptions &ssl_options, const bool use_gr_notifications,
457 const unsigned view_id);
458
460 public:
461 static MetadataCacheAPIBase *instance();
462
463 void cache_init(const mysqlrouter::ClusterType cluster_type,
464 const unsigned router_id, const std::string &clusterset_id,
465 const metadata_servers_list_t &metadata_servers,
466 const MetadataCacheTTLConfig &ttl_config,
467 const mysqlrouter::SSLOptions &ssl_options,
468 const mysqlrouter::TargetCluster &target_cluster,
469 const MetadataCacheMySQLSessionConfig &session_config,
470 const RouterAttributes &router_attributes,
471 size_t thread_stack_size, bool use_cluster_notifications,
472 const uint64_t view_id) override;
473
474 mysqlrouter::ClusterType cluster_type() const override;
475
476 void instance_name(const std::string &inst_name) override;
477 std::string instance_name() const override;
478
479 mysqlrouter::TargetCluster target_cluster() const override;
480 std::chrono::milliseconds ttl() const override;
481
482 bool is_initialized() noexcept override { return is_initialized_; }
483 void cache_start() override;
484
485 void cache_stop() noexcept override;
486
487 cluster_nodes_list_t get_cluster_nodes() override;
488 ClusterTopology get_cluster_topology() override;
489
490 bool wait_primary_failover(const std::string &primary_server_uuid,
491 const std::chrono::seconds &timeout) override;
492
493 void add_state_listener(ClusterStateListenerInterface *listener) override;
494
495 void remove_state_listener(ClusterStateListenerInterface *listener) override;
496
497 void add_acceptor_handler_listener(
498 AcceptorUpdateHandlerInterface *listener) override;
499
500 void remove_acceptor_handler_listener(
501 AcceptorUpdateHandlerInterface *listener) override;
502
503 void add_md_refresh_listener(
504 MetadataRefreshListenerInterface *listener) override;
505
506 void remove_md_refresh_listener(
507 MetadataRefreshListenerInterface *listener) override;
508
509 RefreshStatus get_refresh_status() override;
510
511 std::pair<bool, std::pair<std::string, rapidjson::Document>>
512 get_rest_user_auth_data(const std::string &user) const override;
513
514 void enable_fetch_auth_metadata() override;
515 void force_cache_update() override;
516 void check_auth_metadata_timers() const override;
517
518 void handle_sockets_acceptors_on_md_refresh() override;
519
520 void set_instance_factory(metadata_factory_t cb) override {
521 instance_factory_ = std::move(cb);
522 }
523
524 bool fetch_whole_topology() const override;
525 void fetch_whole_topology(bool val) override;
526
527 private:
529
530 struct InstData {
531 std::string name;
532 };
534
535 std::atomic<bool> is_initialized_{false};
536 MetadataCacheAPI() = default;
539};
540
541} // namespace metadata_cache
542
543#endif // MYSQLROUTER_METADATA_CACHE_INCLUDED
Monitor pattern.
Definition: monitor.h:39
Abstract class that provides interface for listener on whether the listening sockets acceptors state ...
Definition: metadata_cache.h:115
virtual bool update_socket_acceptor_state(const metadata_cache::cluster_nodes_list_t &instances)=0
Callback function that is called when the state of the sockets acceptors is handled during the metada...
AcceptorUpdateHandlerInterface & operator=(AcceptorUpdateHandlerInterface &&)=default
AcceptorUpdateHandlerInterface & operator=(const AcceptorUpdateHandlerInterface &)=default
AcceptorUpdateHandlerInterface(AcceptorUpdateHandlerInterface &&)=default
AcceptorUpdateHandlerInterface(const AcceptorUpdateHandlerInterface &)=default
Abstract class that provides interface for listener on cluster status changes.
Definition: metadata_cache.h:86
ClusterStateListenerInterface & operator=(const ClusterStateListenerInterface &)=delete
ClusterStateListenerInterface(const ClusterStateListenerInterface &)=delete
virtual void notify_instances_changed(const ClusterTopology &cluster_topology, const bool md_servers_reachable, const uint64_t view_id)=0
Callback function that is called when state of cluster is changed.
Abstract class that provides interface for adding and removing observers on cluster status changes.
Definition: metadata_cache.h:177
ClusterStateNotifierInterface(const ClusterStateNotifierInterface &)=delete
ClusterStateNotifierInterface & operator=(const ClusterStateNotifierInterface &)=delete
virtual void add_state_listener(ClusterStateListenerInterface *listener)=0
Register observer that is notified when there is a change in the cluster nodes setup/state discovered...
virtual void remove_state_listener(ClusterStateListenerInterface *listener)=0
Unregister observer previously registered with add_state_listener()
Definition: metadata_cache.h:226
virtual std::string instance_name() const =0
virtual std::chrono::milliseconds ttl() const =0
virtual void instance_name(const std::string &inst_name)=0
virtual void cache_init(const mysqlrouter::ClusterType cluster_type, const unsigned router_id, const std::string &clusterset_id, const metadata_servers_list_t &metadata_servers, const MetadataCacheTTLConfig &ttl_config, const mysqlrouter::SSLOptions &ssl_options, const mysqlrouter::TargetCluster &target_cluster, const MetadataCacheMySQLSessionConfig &session_config, const RouterAttributes &router_attributes, size_t thread_stack_size=mysql_harness::kDefaultStackSizeInKiloBytes, bool use_cluster_notifications=false, const uint64_t view_id=0)=0
Initialize a MetadataCache object and start caching.
virtual bool is_initialized() noexcept=0
virtual mysqlrouter::TargetCluster target_cluster() const =0
virtual RefreshStatus get_refresh_status()=0
virtual void set_instance_factory(metadata_factory_t cb)=0
std::function< std::shared_ptr< MetaData >(mysqlrouter::ClusterType cluster_type, const metadata_cache::MetadataCacheMySQLSessionConfig &session_config, const mysqlrouter::SSLOptions &ssl_options, const bool use_cluster_notifications, unsigned view_id)> metadata_factory_t
Definition: metadata_cache.h:443
Definition: metadata_cache.h:459
bool is_initialized() noexcept override
Definition: metadata_cache.h:482
MetadataCacheAPI & operator=(const MetadataCacheAPI &)=delete
MetadataCacheAPI(const MetadataCacheAPI &)=delete
Abstract class that provides interface for listener on metadata refresh.
Definition: metadata_cache.h:143
MetadataRefreshListenerInterface & operator=(const MetadataRefreshListenerInterface &)=default
virtual void on_md_refresh(const bool instances_changed, const ClusterTopology &cluster_topology)=0
Callback that is going to be used on each metadata refresh.
MetadataRefreshListenerInterface & operator=(MetadataRefreshListenerInterface &&)=default
MetadataRefreshListenerInterface(const MetadataRefreshListenerInterface &)=default
MetadataRefreshListenerInterface(MetadataRefreshListenerInterface &&)=default
Class that represents all the exceptions that are thrown while fetching the metadata.
Definition: metadata_cache.h:74
metadata_error(const std::string &what_arg)
Definition: metadata_cache.h:76
static constexpr int kDefaultReadTimeout
Definition: mysql_session.h:157
static constexpr int kDefaultConnectTimeout
Definition: mysql_session.h:156
Definition: cluster_metadata.h:159
#define METADATA_CACHE_EXPORT
Definition: metadata_cache_export.h:15
Define rapidjson::SizeType to be std::uint64_t.
char * user
Definition: mysqladmin.cc:66
static bool timeout(bool(*wait_condition)())
Timeout function.
Definition: log0meb.cc:498
Definition: metadata_cache.h:53
constexpr const std::string_view kDefaultMetadataCluster
Definition: metadata_cache.h:63
constexpr const std::string_view kDefaultMetadataUser
Definition: metadata_cache.h:56
std::vector< metadata_server_t > metadata_servers_list_t
Definition: metadata_cache_datatypes.h:146
std::vector< ManagedInstance > cluster_nodes_list_t
Definition: metadata_cache_datatypes.h:142
constexpr const std::string_view kDefaultMetadataAddress
Definition: metadata_cache.h:55
constexpr const std::chrono::milliseconds kDefaultAuthCacheTTL
Definition: metadata_cache.h:58
constexpr const std::string_view kDefaultMetadataPassword
Definition: metadata_cache.h:57
constexpr const unsigned int kDefaultConnectTimeout
Definition: metadata_cache.h:64
constexpr const std::chrono::milliseconds kDefaultAuthCacheRefreshInterval
Definition: metadata_cache.h:60
constexpr const uint16_t kDefaultMetadataPort
Definition: metadata_cache.h:54
constexpr const unsigned int kDefaultReadTimeout
Definition: metadata_cache.h:66
std::shared_ptr< MetaData > metadata_factory_get_instance(const mysqlrouter::ClusterType cluster_type, const metadata_cache::MetadataCacheMySQLSessionConfig &session_config, const mysqlrouter::SSLOptions &ssl_options, const bool use_gr_notifications, const unsigned view_id)
Return an instance of cluster metadata.
Definition: metadata_factory.cc:48
static const size_t kDefaultStackSizeInKiloBytes
Definition: mysql_router_thread.h:44
Definition: base64.h:43
ClusterType
Definition: cluster_metadata.h:140
Definition: my_rapidjson_size_t.h:38
Definition: gcs_xcom_synode.h:64
Represents a cluster (a GR group or AR members) and its metadata servers.
Definition: metadata_cache_datatypes.h:183
std::string last_metadata_server_host
Definition: metadata_cache.h:430
uint64_t refresh_failed
Definition: metadata_cache.h:425
std::chrono::system_clock::time_point last_refresh_failed
Definition: metadata_cache.h:428
uint16_t last_metadata_server_port
Definition: metadata_cache.h:431
uint64_t refresh_succeeded
Definition: metadata_cache.h:426
std::chrono::system_clock::time_point last_refresh_succeeded
Definition: metadata_cache.h:427
Definition: metadata_cache.h:530
std::string name
Definition: metadata_cache.h:531
Metadata MySQL session configuration.
Definition: metadata_cache_datatypes.h:223
Metadata TTL configuration.
Definition: metadata_cache.h:213
std::chrono::milliseconds auth_cache_refresh_interval
Definition: metadata_cache.h:222
std::chrono::milliseconds ttl
Definition: metadata_cache.h:215
std::chrono::milliseconds auth_cache_ttl
Definition: metadata_cache.h:218
Definition: metadata_cache_datatypes.h:239
SSL connection related options.
Definition: datatypes.h:34
double seconds()
Definition: task.cc:310