MySQL 9.3.0
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
rate_control_for.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_AUTHENTICATION_HELPER_RATE_CONTROL_FOR_H_
27#define ROUTER_SRC_MYSQL_REST_SERVICE_SRC_MRS_AUTHENTICATION_HELPER_RATE_CONTROL_FOR_H_
28
29#include <chrono>
30#include <map>
31#include <mutex>
32#include <optional>
33
34namespace mrs {
35namespace authentication {
36
38
39struct AcceptInfo {
40 public:
42
45};
46
47template <typename ControlType, uint64_t measure_time_in_seconds = 60>
49 public:
50 using clock = std::chrono::steady_clock;
51 using time_point = clock::time_point;
54
55 struct ControlEntry {
56 uint64_t number_of_requests{0};
58 std::optional<time_point> blocked_at;
60
63 started_counting = clock::now();
64 blocked_at.reset();
65 }
66 };
67
68 public:
69 RateControlFor(std::optional<uint64_t> block_after_rate, seconds block_for,
70 std::optional<milliseconds> minimum_time_between_requests)
71 : block_for_{std::chrono::duration_cast<milliseconds>(block_for)},
72 block_after_{block_after_rate},
73 minimum_time_between_requests_{minimum_time_between_requests} {}
74
76
78 auto lock = std::unique_lock<std::mutex>(entries_mutex_);
79 entries_ = other.entries_;
80 block_for_ = other.block_for_;
83 return *this;
84 }
85
86 void clear() {
87 auto lock = std::unique_lock<std::mutex>(entries_mutex_);
88
89 for (auto it = entries_.begin(); it != entries_.end();) {
90 ControlEntry &entry = it->second;
91 if (duration_now(entry.started_counting) >= seconds(1)) {
92 it = entries_.erase(it);
93 continue;
94 }
95
96 if (duration_now(entry.blocked_at) >= seconds(1)) {
97 it = entries_.erase(it);
98 continue;
99 }
100
101 ++it;
102 }
103 }
104
105 bool allow(const ControlType &ct, AcceptInfo *info = nullptr) {
106 if (!block_after_ && !minimum_time_between_requests_) return true;
107 auto lock = std::unique_lock<std::mutex>(entries_mutex_);
108
109 auto it = entries_.find(ct);
110 if (it == entries_.end()) {
111 entries_.emplace(
112 std::make_pair(ct, ControlEntry{1, clock::now(), {}, clock::now()}));
113 return true;
114 }
115
116 ControlEntry &entry = it->second;
117
118 auto result = allow_impl(entry, info);
119
120 entry.access_time = clock::now();
121
122 return result;
123 }
124
125 size_t size() const { return entries_.size(); }
126
127 private:
129 if (!allow_check_blocked(entry, info)) return false;
130
131 return allow_check_too_fast(entry, info);
132 }
133
135 if (!minimum_time_between_requests_) return true;
136
137 auto time_between_requests = (clock::now() - entry.access_time);
138
139 if (time_between_requests < minimum_time_between_requests_.value()) {
140 if (info) {
144 }
145 return false;
146 }
147
148 return true;
149 }
150
152 if (!block_after_) return true;
153
154 if (entry.blocked_at) {
155 if (duration_now(entry.blocked_at.value()) >= block_for_) {
156 entry.reset_blocking();
157 return true;
158 }
159
160 if (info) {
163 block_for_ - std::chrono::duration_cast<milliseconds>(
164 clock::now() - entry.blocked_at.value());
165 }
166
167 return false;
168 }
169
170 if (duration_now(entry.started_counting) >=
171 seconds(measure_time_in_seconds)) {
172 entry.reset_blocking();
173 return true;
174 }
175
176 if (++entry.number_of_requests > block_after_) {
177 entry.blocked_at = clock::now();
178 if (info) {
181 }
182 return false;
183 }
184
185 return true;
186 }
187
188 static milliseconds duration_now(const std::optional<time_point> &value) {
189 if (!value) return milliseconds{0};
190 return duration_now(value.value());
191 }
192
194 return std::chrono::duration_cast<milliseconds>(clock::now() - value);
195 }
196
197 std::mutex entries_mutex_;
198 std::map<ControlType, ControlEntry> entries_;
200 std::optional<uint64_t> block_after_{};
201 std::optional<milliseconds> minimum_time_between_requests_;
202};
203
204} // namespace authentication
205} // namespace mrs
206
207#endif // ROUTER_SRC_MYSQL_REST_SERVICE_SRC_MRS_AUTHENTICATION_HELPER_RATE_CONTROL_FOR_H_
Definition: rate_control_for.h:48
bool allow_check_blocked(ControlEntry &entry, AcceptInfo *info)
Definition: rate_control_for.h:151
std::chrono::steady_clock clock
Definition: rate_control_for.h:50
bool allow_impl(ControlEntry &entry, AcceptInfo *info)
Definition: rate_control_for.h:128
std::chrono::seconds seconds
Definition: rate_control_for.h:53
static milliseconds duration_now(const std::optional< time_point > &value)
Definition: rate_control_for.h:188
std::optional< uint64_t > block_after_
Definition: rate_control_for.h:200
milliseconds block_for_
Definition: rate_control_for.h:199
clock::time_point time_point
Definition: rate_control_for.h:51
std::mutex entries_mutex_
Definition: rate_control_for.h:197
bool allow(const ControlType &ct, AcceptInfo *info=nullptr)
Definition: rate_control_for.h:105
std::chrono::milliseconds milliseconds
Definition: rate_control_for.h:52
static milliseconds duration_now(const time_point &value)
Definition: rate_control_for.h:193
RateControlFor & operator=(const RateControlFor &other)
Definition: rate_control_for.h:77
bool allow_check_too_fast(ControlEntry &entry, AcceptInfo *info)
Definition: rate_control_for.h:134
void clear()
Definition: rate_control_for.h:86
RateControlFor()
Definition: rate_control_for.h:75
size_t size() const
Definition: rate_control_for.h:125
std::optional< milliseconds > minimum_time_between_requests_
Definition: rate_control_for.h:201
std::map< ControlType, ControlEntry > entries_
Definition: rate_control_for.h:198
RateControlFor(std::optional< uint64_t > block_after_rate, seconds block_for, std::optional< milliseconds > minimum_time_between_requests)
Definition: rate_control_for.h:69
Provides atomic access in shared-exclusive modes.
Definition: shared_spin_lock.h:79
std::chrono::seconds seconds
Definition: authorize_manager.cc:69
BlockReason
Definition: rate_control_for.h:37
std::chrono::milliseconds milliseconds
Definition: authorize_manager.cc:68
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
Definition: authorize_manager.h:48
Definition: gcs_xcom_synode.h:64
struct result result
Definition: result.h:34
Definition: completion_hash.h:35
Definition: rate_control_for.h:39
milliseconds next_request_allowed_after
Definition: rate_control_for.h:44
BlockReason reason
Definition: rate_control_for.h:43
std::chrono::milliseconds milliseconds
Definition: rate_control_for.h:41
Definition: rate_control_for.h:55
std::optional< time_point > blocked_at
Definition: rate_control_for.h:58
time_point access_time
Definition: rate_control_for.h:59
void reset_blocking()
Definition: rate_control_for.h:61
time_point started_counting
Definition: rate_control_for.h:57
uint64_t number_of_requests
Definition: rate_control_for.h:56
Definition: result.h:30