mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-02 14:15:46 +00:00
Whether a server can vote in a Raft configuration is not part of the address. `server_address` was used in many context where `can_vote` is irrelevant. Split the struct: `server_address` now contains only `id` and `server_info` as it did before `can_vote` was introduced. Instead we have a `config_member` struct that contains a `server_address` and the `can_vote` field. Also remove an "unsafe" constructor from `server_address` where `id` was provided but `server_info` was not. The constructor was used for tests where `server_info` is irrelevant, but it's important not to forget about the info in production code. The constructor was used for two purposes: - Invoking set operations such as `contains`. To solve this we use C++20 transparent hash and comparator functions, which allow invoking `contains` and similar functions by providing a different key type (in this case `raft::server_id` in set of addresses, for example). - constructing addresses without `info`s in tests. For this we provide helper functions in the test helpers module and use them.
102 lines
2.9 KiB
C++
102 lines
2.9 KiB
C++
/*
|
|
* Copyright (C) 2021-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
#define BOOST_TEST_MODULE raft
|
|
#include "test/raft/helpers.hh"
|
|
#include "service/raft/discovery.hh"
|
|
|
|
using namespace raft;
|
|
|
|
using discovery_network = std::unordered_map<server_id, service::discovery*>;
|
|
|
|
using service::discovery;
|
|
|
|
void
|
|
run_discovery_impl(discovery_network& network) {
|
|
while (true) {
|
|
for (auto e : network) {
|
|
discovery& from = *e.second;
|
|
auto output = from.tick();
|
|
if (std::holds_alternative<discovery::i_am_leader>(output)) {
|
|
return;
|
|
} else if (std::holds_alternative<discovery::pause>(output)) {
|
|
continue;
|
|
}
|
|
auto& msgs = std::get<discovery::request_list>(output);
|
|
for (auto&& m : msgs) {
|
|
auto it = network.find(m.first.id);
|
|
if (it == network.end()) {
|
|
// The node is not available, drop the message
|
|
continue;
|
|
}
|
|
discovery& to = *(it->second);
|
|
if (auto peer_list = to.request(m.second)) {
|
|
from.response(m.first, std::move(*peer_list));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename... Args>
|
|
void run_discovery(Args&&... args) {
|
|
discovery_network network;
|
|
auto add_node = [&network](discovery& node) -> void {
|
|
network.emplace(node.id(), &node);
|
|
};
|
|
(add_node(args), ...);
|
|
run_discovery_impl(network);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_basic) {
|
|
|
|
server_address addr1 = {id(), {}};
|
|
|
|
// Must supply an Internet address for self
|
|
BOOST_CHECK_THROW(discovery(addr1, {}), std::logic_error);
|
|
server_address addr2 = {id(), "192.168.1.2"};
|
|
BOOST_CHECK_NO_THROW(discovery(addr2, {}));
|
|
// Must supply an Internet address for each peer
|
|
BOOST_CHECK_THROW(discovery(addr2, {addr1}), std::logic_error);
|
|
// OK to include self into peers
|
|
BOOST_CHECK_NO_THROW(discovery(addr2, {addr2}));
|
|
// With a single peer, discovery immediately finds a leader
|
|
discovery d(addr2, {});
|
|
BOOST_CHECK(d.is_leader());
|
|
d = discovery(addr2, {addr2});
|
|
BOOST_CHECK(d.is_leader());
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(test_discovery) {
|
|
|
|
server_address addr1 = {id(), "192.168.1.1"};
|
|
server_address addr2 = {id(), "192.168.1.2"};
|
|
|
|
discovery d1(addr1, {addr2});
|
|
discovery d2(addr2, {addr1});
|
|
run_discovery(d1, d2);
|
|
|
|
BOOST_CHECK(d1.is_leader() ^ d2.is_leader());
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_discovery_fullmesh) {
|
|
|
|
server_address addr1 = {id(), "127.0.0.13"};
|
|
server_address addr2 = {id(), "127.0.0.19"};
|
|
server_address addr3 = {id(), "127.0.0.21"};
|
|
|
|
auto seeds = std::vector<server_address>({addr1, addr2, addr3});
|
|
|
|
discovery d1(addr1, seeds);
|
|
discovery d2(addr2, seeds);
|
|
discovery d3(addr3, seeds);
|
|
run_discovery(d1, d2, d3);
|
|
|
|
BOOST_CHECK(d1.is_leader() ^ d2.is_leader() ^ d3.is_leader());
|
|
}
|