MySQL 9.3.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
gtid_manager.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2023, 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_SRC_MRS_GTID_MANAGER_H_
27#define ROUTER_SRC_MYSQL_REST_SERVICE_SRC_MRS_GTID_MANAGER_H_
28
29#include <chrono>
30#include <map>
31#include <mutex>
32#include <numeric>
33#include <shared_mutex>
34#include <vector>
35
37#include "helper/json/text_to.h"
38#include "helper/to_string.h"
40
43
45
46namespace mrs {
47
49
51 public:
52 using clock = std::chrono::steady_clock;
53 using duration = clock::duration;
57
59 public:
60 bool needs_refresh{false};
61 clock::time_point last_update;
62 std::map<Uid, GtidSet> all_sets;
63 std::shared_mutex mutex_gtid_access_;
64 uint64_t initial_size_{0};
65 bool requested_initialization_{false};
66 bool requested_update_{false};
67
68 bool get_gtidset_by_gtid_uid(const Uid &uid, GtidSet **set) {
69 auto it = all_sets.find(uid);
70 if (it == all_sets.end()) return false;
71
72 *set = &(*it).second;
73
74 return true;
75 }
76
77 uint64_t calculate_gtid_items() const {
78 return std::accumulate(
79 all_sets.begin(), all_sets.end(), 0,
80 [](auto v, auto &kv) { return v + kv.second.size(); });
81 }
82 };
83
84 public:
86
87 void configure(const std::string &json_config) {
88 auto cnf = parse_json_options(json_config);
89 enable_ = cnf.enable.value_or(true);
90 refresh_timeout_ = cnf.d.value_or(std::chrono::minutes(1));
91 refresh_after_ = cnf.refresh_after;
93 using std::to_string;
94
95 // log_debug("GtidManager - configured with:");
96 // log_debug("GtidManager::enable_: %s", to_string(enable_).c_str());
97 // log_debug("GtidManager::timeout_: %s",
98 // to_string(refresh_timeout_.count()).c_str());
99 // log_debug("GtidManager::after_: %s",
100 // to_string(refresh_after_).c_str());
101 }
102
104 const Gtid &gtid) {
105 if (!enable_) return GtidAction::k_not_found;
106 // log_debug("GtidManager - is_executed_on_server %s - %s",
107 // addr.str().c_str(),
108 // gtid.to_string().c_str());
109 GtidSet *set;
110 auto ctxt = get_context(addr);
111
112 if (!ctxt->requested_initialization_) {
113 ctxt->requested_initialization_ = true;
114 return GtidAction::k_needs_update;
115 }
116
117 if (!ctxt->requested_update_) {
118 if (needs_update(ctxt.get())) {
119 ctxt->requested_update_ = true;
120 return GtidAction::k_needs_update;
121 }
122 }
123
124 auto l = std::shared_lock<std::shared_mutex>(ctxt->mutex_gtid_access_);
125
126 if (!ctxt->get_gtidset_by_gtid_uid(gtid.get_uid(), &set))
127 return GtidAction::k_not_found;
128
129 return set->contains(gtid) ? GtidAction::k_is_on_server
130 : GtidAction::k_not_found;
131 }
132
133 void remember(const mysql_harness::Destination &addr, const Gtid &gtid) {
134 if (!enable_) return;
135
136 // log_debug("GtidManager - remember (%s - %s)", addr.str().c_str(),
137 // gtid.to_string().c_str());
138
139 GtidSet *set;
140 auto ctxt = get_context(addr);
141 auto l = std::unique_lock<std::shared_mutex>(ctxt->mutex_gtid_access_);
142
143 if (!ctxt->get_gtidset_by_gtid_uid(gtid.get_uid(), &set)) {
144 set = &ctxt->all_sets[gtid.get_uid()];
145 set->set(gtid);
146 return;
147 }
148
149 if (!set->try_merge(gtid)) set->insert(gtid);
150 }
151
153 if (!enable_) return false;
154
155 auto ctxt = get_context(addr);
156 return needs_update(ctxt.get());
157 }
158
160 const std::vector<GtidSet> &sets) {
161 if (!enable_) return;
162
163 // log_debug("GtidManager - reinitialize %s", addr.str().c_str());
164
165 auto ctxt = get_context(addr);
166 auto l = std::unique_lock<std::shared_mutex>(ctxt->mutex_gtid_access_);
167
168 ctxt->all_sets.clear();
169 for (auto &set : sets) {
170 ctxt->all_sets[set.get_uid()] = set;
171 }
172
173 ctxt->needs_refresh = false;
174 ctxt->last_update = std::chrono::steady_clock::now();
175 ctxt->initial_size_ = ctxt->calculate_gtid_items();
176 ctxt->requested_update_ = false;
177
178 // Overwriting, the initialization could be done, without requesting.
179 ctxt->requested_initialization_ = true;
180 }
181
182 private:
184 public:
185 std::optional<bool> enable;
186 std::optional<duration> d;
187 std::optional<uint64_t> refresh_after;
188 };
189
191 : public helper::json::RapidReaderHandlerToStruct<GtidOptions> {
192 public:
193 template <typename ValueType, bool default_value = false>
194 bool to_bool(const ValueType &value) {
195 const static std::map<std::string, bool> allowed_values{
196 {"true", true}, {"false", false}, {"1", true}, {"0", false}};
197 auto it = allowed_values.find(value);
198 if (it != allowed_values.end()) {
199 return it->second;
200 }
201
202 return default_value;
203 }
204
205 template <typename ValueType>
206 uint64_t to_uint(const ValueType &value) {
207 return std::stoull(value.c_str());
208 }
209
210 template <typename ValueType>
211 void handle_object_value(const std::string &key, const ValueType &vt) {
212 using std::to_string;
213 if (key == "gtid.cache.enable") {
214 result_.enable = to_bool(vt);
215 } else if (key == "gtid.cache.refreshRate") {
216 result_.d = std::chrono::seconds{to_uint(vt)};
217 } else if (key == "gtid.cache.refreshWhenIncreasesBy") {
218 result_.refresh_after = to_uint(vt);
219 }
220 }
221
222 template <typename ValueType>
223 void handle_value(const ValueType &vt) {
224 const auto &key = get_current_key();
225 if (is_object_path()) {
226 handle_object_value(key, vt);
227 }
228 }
229
230 bool String(const Ch *v, rapidjson::SizeType v_len, bool) override {
231 handle_value(std::string{v, v_len});
232 return true;
233 }
234
235 bool RawNumber(const Ch *v, rapidjson::SizeType v_len, bool) override {
236 handle_value(std::string{v, v_len});
237 return true;
238 }
239
240 bool Bool(bool v) override {
241 const static std::string k_true{"true"}, k_false{"false"};
242 handle_value(v ? k_true : k_false);
243 return true;
244 }
245 };
246
248 return helper::json::text_to_handler<ParseGtidOptions>(options);
249 }
250
252 if (refresh_after_.has_value()) {
253 if (refresh_after_.value() <
254 (ctxt->calculate_gtid_items() - ctxt->initial_size_))
255 return true;
256 }
257
258 if (!refresh_timeout_.count()) return false;
259
260 return refresh_timeout_ < (clock::now() - ctxt->last_update);
261 }
262
263 std::shared_ptr<AddressContext> get_context(
264 const mysql_harness::Destination &addr) {
265 std::shared_ptr<AddressContext> result;
266 auto l = std::unique_lock(mutex_address_container_);
267
268 auto it = address_context_.find(addr);
269 if (it != address_context_.end()) {
270 result = it->second;
271 } else {
272 result = std::make_shared<AddressContext>();
273 result->last_update = clock::now();
274 address_context_[addr] = result;
275 }
276
277 return result;
278 }
279
280 bool enable_{true};
281 duration refresh_timeout_{};
282 std::optional<uint64_t> refresh_after_{};
284 std::map<mysql_harness::Destination, std::shared_ptr<AddressContext>>
286};
287
288} // namespace mrs
289
290#endif // ROUTER_SRC_MYSQL_REST_SERVICE_SRC_MRS_GTID_MANAGER_H_
This class is a adapter for Reader from RapidJson.
Definition: rapid_json_to_struct.h:51
typename Parent::Ch Ch
Definition: rapid_json_to_struct.h:60
Definition: gtid_manager.h:58
std::shared_mutex mutex_gtid_access_
Definition: gtid_manager.h:63
std::map< Uid, GtidSet > all_sets
Definition: gtid_manager.h:62
clock::time_point last_update
Definition: gtid_manager.h:61
bool get_gtidset_by_gtid_uid(const Uid &uid, GtidSet **set)
Definition: gtid_manager.h:68
uint64_t initial_size_
Definition: gtid_manager.h:64
uint64_t calculate_gtid_items() const
Definition: gtid_manager.h:77
Definition: gtid_manager.h:183
std::optional< uint64_t > refresh_after
Definition: gtid_manager.h:187
std::optional< bool > enable
Definition: gtid_manager.h:185
std::optional< duration > d
Definition: gtid_manager.h:186
Definition: gtid_manager.h:191
bool RawNumber(const Ch *v, rapidjson::SizeType v_len, bool) override
enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
Definition: gtid_manager.h:235
bool Bool(bool v) override
Definition: gtid_manager.h:240
bool to_bool(const ValueType &value)
Definition: gtid_manager.h:194
void handle_value(const ValueType &vt)
Definition: gtid_manager.h:223
bool String(const Ch *v, rapidjson::SizeType v_len, bool) override
Definition: gtid_manager.h:230
void handle_object_value(const std::string &key, const ValueType &vt)
Definition: gtid_manager.h:211
uint64_t to_uint(const ValueType &value)
Definition: gtid_manager.h:206
Definition: gtid_manager.h:50
std::mutex mutex_address_container_
Definition: gtid_manager.h:283
GtidAction is_executed_on_server(const mysql_harness::Destination &addr, const Gtid &gtid)
Definition: gtid_manager.h:103
void reinitialize(const mysql_harness::Destination &addr, const std::vector< GtidSet > &sets)
Definition: gtid_manager.h:159
std::map< mysql_harness::Destination, std::shared_ptr< AddressContext > > address_context_
Definition: gtid_manager.h:285
GtidOptions parse_json_options(const std::string &options)
Definition: gtid_manager.h:247
std::shared_ptr< AddressContext > get_context(const mysql_harness::Destination &addr)
Definition: gtid_manager.h:263
void remember(const mysql_harness::Destination &addr, const Gtid &gtid)
Definition: gtid_manager.h:133
bool needs_update(AddressContext *ctxt)
Definition: gtid_manager.h:251
std::chrono::steady_clock clock
Definition: gtid_manager.h:52
bool needs_update(const mysql_harness::Destination &addr)
Definition: gtid_manager.h:152
clock::duration duration
Definition: gtid_manager.h:53
GtidManager()
Definition: gtid_manager.h:85
void configure(const std::string &json_config)
Definition: gtid_manager.h:87
Definition: gtid.h:454
Definition: gtid.h:435
Definition: gtid.h:45
const GTIDuuid & get_uid() const
Definition: gtid.h:421
Definition: destination.h:95
uint to_uint(enum_sp_type val)
Definition: sql_lex.h:250
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:323
borrowable::session_track::Gtid< true > Gtid
Definition: classic_protocol_session_track.h:290
CacheOptions parse_json_options(const std::string &options)
Definition: mysql_cache_manager.cc:96
std::optional< bool > to_bool(const std::string &value)
Definition: jvalue.cc:38
std::string to_string(const DummyType &)
Definition: to_string.h:38
const std::string k_true
Definition: to_string.h:34
const std::string k_false
Definition: to_string.h:35
std::chrono::minutes minutes
Definition: authorize_manager.cc:70
std::chrono::seconds seconds
Definition: authorize_manager.cc:69
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
inner::GTIDuuid GTIDuuid
Definition: gtid.h:433
Definition: authorize_manager.h:48
GtidAction
Definition: gtid_manager.h:48
Definition: options.cc:57
typedef::std::uint64_t SizeType
Definition: my_rapidjson_size_t.h:39
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2884
struct result result
Definition: result.h:34
required string key
Definition: replication_asynchronous_connection_failover.proto:60
Definition: result.h:30