Skip to content

Commit 4ebb3c3

Browse files
Andrzej Religabjornmu
authored andcommitted
Bug#35157953 MySQL Router stops accepting connections - 8.0.32
This patch: - adds more logging info to help debug the issue - replaces use of ENOENT with custom error code for scenario when the Router discovers there are no destinations available Change-Id: I544973fdd01d1c8012abc353c5d1214444b1a43d
1 parent b5cc47e commit 4ebb3c3

12 files changed

+86
-12
lines changed

router/src/routing/src/classic_connect.cc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@ ConnectProcessor::init_destination() {
153153
} else {
154154
if (!last_ec_) {
155155
// no backends
156-
last_ec_ = make_error_code(std::errc::no_such_file_or_directory);
156+
log_debug("init_destination(): the destinations list is empty");
157+
last_ec_ = make_error_code(DestinationsErrc::kNoDestinations);
157158
}
158159

159160
stage(Stage::Error);
@@ -194,6 +195,9 @@ stdx::expected<Processor::Result, std::error_code> ConnectProcessor::resolve() {
194195
destination->hostname(), std::to_string(destination->port()));
195196

196197
if (!resolve_res) {
198+
log_debug("resolve(%s,%d) failed: %s:%s", destination->hostname().c_str(),
199+
destination->port(), resolve_res.error().category().name(),
200+
resolve_res.error().message().c_str());
197201
destination->connect_status(resolve_res.error());
198202

199203
stage(Stage::NextDestination);
@@ -463,6 +467,10 @@ stdx::expected<Processor::Result, std::error_code> ConnectProcessor::connect() {
463467

464468
return Result::SendableToServer;
465469
} else {
470+
log_debug("connect(%s, %d) failed: %s:%s",
471+
server_endpoint_.address().to_string().c_str(),
472+
server_endpoint_.port(), connect_res.error().category().name(),
473+
connect_res.error().message().c_str());
466474
connection()->connect_error_code(ec);
467475

468476
stage(Stage::ConnectFinish);
@@ -651,7 +659,10 @@ stdx::expected<Processor::Result, std::error_code> ConnectProcessor::error() {
651659

652660
connection()->connect_error_code(ec);
653661

654-
if (ec == std::errc::no_such_file_or_directory) {
662+
log_debug("ConnectProcessor::error(): %s:%s", ec.category().name(),
663+
ec.message().c_str());
664+
665+
if (ec == DestinationsErrc::kNoDestinations) {
655666
log_error("no backend available to connect to");
656667
} else {
657668
log_fatal_error_code("connecting to backend failed", ec);
@@ -664,7 +675,7 @@ stdx::expected<Processor::Result, std::error_code> ConnectProcessor::error() {
664675
//
665676
// don't retry as router may run into an infinite loop.
666677
ConnectionPoolComponent::get_instance().clear();
667-
} else if (ec == std::errc::no_such_file_or_directory &&
678+
} else if (ec == DestinationsErrc::kNoDestinations &&
668679
connection()->get_destination_id().empty()) {
669680
// if there are no destinations for a fresh connect, close the
670681
// acceptor-ports

router/src/routing/src/classic_connect.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@ class ConnectProcessor : public Processor {
4242
io_ctx_{conn->socket_splicer()->client_conn().connection()->io_ctx()},
4343
destinations_{conn->current_destinations()},
4444
destinations_it_{destinations_.begin()},
45-
on_error_(std::move(on_error)) {}
45+
on_error_(std::move(on_error)) {
46+
// this is needed to shut down accepting port with next-available strategy
47+
// despite there are destinations available
48+
if (conn->destinations()->get_strategy() ==
49+
routing::RoutingStrategy::kNextAvailable) {
50+
last_ec_ = make_error_code(DestinationsErrc::kNoDestinations);
51+
}
52+
}
4653

4754
using server_protocol_type = net::ip::tcp;
4855

@@ -94,8 +101,7 @@ class ConnectProcessor : public Processor {
94101
net::ip::tcp::resolver::results_type endpoints_;
95102
net::ip::tcp::resolver::results_type::iterator endpoints_it_;
96103

97-
std::error_code last_ec_{
98-
make_error_code(std::errc::no_such_file_or_directory)};
104+
std::error_code last_ec_{make_error_code(DestinationsErrc::kNotSet)};
99105

100106
std::function<void(const classic_protocol::message::server::Error &err)>
101107
on_error_;

router/src/routing/src/connection.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ stdx::expected<void, std::error_code> ConnectorBase::init_destination() {
4747
// no backends
4848
log_warning("%d: no connectable destinations :(", __LINE__);
4949
return stdx::make_unexpected(
50-
make_error_code(std::errc::no_such_file_or_directory));
50+
make_error_code(DestinationsErrc::kNoDestinations));
5151
}
5252
}
5353

router/src/routing/src/connection.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,7 @@ class ConnectorBase {
219219
net::ip::tcp::resolver::results_type endpoints_;
220220
net::ip::tcp::resolver::results_type::iterator endpoints_it_;
221221

222-
std::error_code last_ec_{
223-
make_error_code(std::errc::no_such_file_or_directory)};
222+
std::error_code last_ec_{make_error_code(DestinationsErrc::kNotSet)};
224223

225224
Function func_{Function::kInitDestination};
226225

router/src/routing/src/dest_first_available.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ class DestFirstAvailable final : public RouteDestination {
4040
// mark index as invalid
4141
void mark_ndx_invalid(size_t ndx) noexcept { valid_ndx_ = ndx + 1; }
4242

43+
routing::RoutingStrategy get_strategy() override {
44+
return routing::RoutingStrategy::kFirstAvailable;
45+
}
46+
4347
private:
4448
size_t valid_ndx_{};
4549
};

router/src/routing/src/dest_metadata_cache.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,12 @@ std::optional<Destinations> DestMetadataCacheGroup::refresh_destinations(
502502
auto const *primary_member = dynamic_cast<MetadataCacheDestination *>(
503503
previous_dests.begin()->get());
504504

505-
if (primary_member->last_error_code() ==
506-
make_error_condition(std::errc::timed_out)) {
505+
const auto err = primary_member->last_error_code();
506+
log_debug("refresh_destinations(): %s:%s", err.category().name(),
507+
err.message().c_str());
508+
509+
if (err == make_error_condition(std::errc::timed_out) ||
510+
err == make_error_condition(std::errc::no_such_file_or_directory)) {
507511
return std::nullopt;
508512
}
509513

router/src/routing/src/dest_metadata_cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class DestMetadataCacheGroup final
113113
cache_api()->handle_sockets_acceptors_on_md_refresh();
114114
}
115115

116+
routing::RoutingStrategy get_strategy() override { return routing_strategy_; }
117+
116118
private:
117119
/** @brief The Metadata Cache to use
118120
*

router/src/routing/src/dest_next_available.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class DestNextAvailable final : public RouteDestination {
4444
}
4545
}
4646

47+
routing::RoutingStrategy get_strategy() override {
48+
return routing::RoutingStrategy::kNextAvailable;
49+
}
50+
4751
private:
4852
size_t valid_ndx_{};
4953
};

router/src/routing/src/dest_round_robin.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class DestRoundRobin : public RouteDestination {
5252

5353
Destinations destinations() override;
5454

55+
routing::RoutingStrategy get_strategy() override {
56+
return routing::RoutingStrategy::kRoundRobin;
57+
}
58+
5559
protected:
5660
// MUST take the RouteDestination Mutex
5761
size_t start_pos_{};

router/src/routing/src/destination.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,27 @@ std::optional<Destinations> RouteDestination::refresh_destinations(
157157
const Destinations &) {
158158
return std::nullopt;
159159
}
160+
161+
const std::error_category &destinations_error_category() noexcept {
162+
class destinations_category_impl : public std::error_category {
163+
public:
164+
const char *name() const noexcept override { return "destinations"; }
165+
std::string message(int ev) const override {
166+
switch (static_cast<DestinationsErrc>(ev)) {
167+
case DestinationsErrc::kNotSet:
168+
return "not set";
169+
case DestinationsErrc::kNoDestinations:
170+
return "no destinations";
171+
default:
172+
return "(unrecognized error)";
173+
}
174+
}
175+
};
176+
177+
static destinations_category_impl instance;
178+
return instance;
179+
}
180+
181+
std::error_code make_error_code(DestinationsErrc e) {
182+
return {static_cast<int>(e), destinations_error_category()};
183+
}

router/src/routing/src/destination.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ class RouteDestination : public DestinationNodesStateNotifier {
206206
RouteDestination &operator=(const RouteDestination &other) = delete;
207207
RouteDestination &operator=(RouteDestination &&other) = delete;
208208

209+
/** @brief Return our routing strategy
210+
*/
211+
virtual routing::RoutingStrategy get_strategy() = 0;
212+
209213
/** @brief Adds a destination
210214
*
211215
* Adds a destination using the given address and port number.
@@ -318,4 +322,16 @@ class RouteDestination : public DestinationNodesStateNotifier {
318322
Protocol::Type protocol_;
319323
};
320324

325+
enum class DestinationsErrc {
326+
kNotSet = 1,
327+
kNoDestinations = 2,
328+
};
329+
330+
namespace std {
331+
template <>
332+
struct is_error_code_enum<DestinationsErrc> : true_type {};
333+
} // namespace std
334+
335+
std::error_code make_error_code(DestinationsErrc);
336+
321337
#endif // ROUTING_DESTINATION_INCLUDED

router/src/routing/src/x_connection.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ void MysqlRoutingXConnection::connect() {
805805
// close the server side.
806806
this->connector().socket().close();
807807

808-
if (ec == std::errc::no_such_file_or_directory) {
808+
if (ec == DestinationsErrc::kNoDestinations) {
809809
MySQLRoutingComponent::get_instance()
810810
.api(context().get_id())
811811
.stop_socket_acceptors();

0 commit comments

Comments
 (0)