From 63f64f3303e52201bd96322dade765f72c4c01e4 Mon Sep 17 00:00:00 2001 From: Petr Gusev Date: Wed, 4 Oct 2023 10:39:57 +0400 Subject: [PATCH] token_metadata: make it a template with NodeId=inet_address/host_id NodeId is used in all internal token_metadata data structures, that previously used inet_address. We choose topology::key_kind based on the value of the template parameter. generic_token_metadata::update_topology overload with host_id parameter is added to make update_topology_change_info work, it now uses NodeId as a parameter type. topology::remove_endpoint(host_id) is added to make generic_token_metadata::remove_endpoint(NodeId) work. pending_endpoints_for and endpoints_for_reading are just removed - they are not used and not implemented. The declarations were left by mistake from a refactoring in which these methods were moved to erm. generic_token_metadata_base is extracted to contain declarations, common to both token_metadata versions. Templates are explicitly instantiated inside token_metadata.cc, since implementation part is also a template and it's not exposed to the header. There are no other behavioral changes in this commit, just syntax fixes to make token_metadata a template. --- api/api_init.hh | 10 +- cdc/log.hh | 6 +- cql3/statements/create_keyspace_statement.hh | 5 +- cql3/statements/ks_prop_defs.hh | 9 +- db/view/view_update_checks.hh | 6 +- locator/token_metadata.cc | 487 ++++++++++++------- locator/token_metadata.hh | 103 ++-- locator/token_metadata_fwd.hh | 8 +- locator/topology.cc | 11 + locator/topology.hh | 3 + node_ops/node_ops_ctl.hh | 6 +- 11 files changed, 420 insertions(+), 234 deletions(-) diff --git a/api/api_init.hh b/api/api_init.hh index c86c57925f..cff8089a8f 100644 --- a/api/api_init.hh +++ b/api/api_init.hh @@ -10,6 +10,7 @@ #include #include +#include "locator/host_id.hh" #include "replica/database_fwd.hh" #include "tasks/task_manager.hh" #include "seastarx.hh" @@ -32,9 +33,16 @@ namespace streaming { class stream_manager; } +namespace gms { + class inet_address; +} + namespace locator { -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; class shared_token_metadata; class snitch_ptr; diff --git a/cdc/log.hh b/cdc/log.hh index 0af27cd5e6..d81f98ea2f 100644 --- a/cdc/log.hh +++ b/cdc/log.hh @@ -29,13 +29,17 @@ #include "timestamp.hh" #include "tracing/trace_state.hh" #include "utils/UUID.hh" +#include "locator/host_id.hh" class schema; using schema_ptr = seastar::lw_shared_ptr; namespace locator { -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; } // namespace locator diff --git a/cql3/statements/create_keyspace_statement.hh b/cql3/statements/create_keyspace_statement.hh index 02946325a2..2aff726ad5 100644 --- a/cql3/statements/create_keyspace_statement.hh +++ b/cql3/statements/create_keyspace_statement.hh @@ -17,7 +17,10 @@ namespace locator { -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; }; diff --git a/cql3/statements/ks_prop_defs.hh b/cql3/statements/ks_prop_defs.hh index 32bc4bec63..11182df218 100644 --- a/cql3/statements/ks_prop_defs.hh +++ b/cql3/statements/ks_prop_defs.hh @@ -12,6 +12,7 @@ #include "cql3/statements/property_definitions.hh" #include "data_dictionary/storage_options.hh" +#include "locator/host_id.hh" #include #include @@ -20,9 +21,15 @@ namespace data_dictionary { class keyspace_metadata; } +namespace gms { + class inet_address; +} namespace locator { - class token_metadata; + template + class generic_token_metadata; + using token_metadata = generic_token_metadata; + using token_metadata2 = generic_token_metadata; class shared_token_metadata; struct snitch_ptr; class abstract_replication_strategy; diff --git a/db/view/view_update_checks.hh b/db/view/view_update_checks.hh index 77b7113c0d..ccb3eacafa 100644 --- a/db/view/view_update_checks.hh +++ b/db/view/view_update_checks.hh @@ -10,6 +10,7 @@ #include #include "streaming/stream_reason.hh" +#include "locator/host_id.hh" #include "seastarx.hh" namespace replica { @@ -23,7 +24,10 @@ class system_distributed_keyspace; } namespace locator { -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; } namespace db::view { diff --git a/locator/token_metadata.cc b/locator/token_metadata.cc index d0996a1f6f..a9d1639bfe 100644 --- a/locator/token_metadata.cc +++ b/locator/token_metadata.cc @@ -27,6 +27,12 @@ namespace locator { static logging::logger tlogger("token_metadata"); +template +inline static constexpr const topology::key_kind kind_for_node_id_type + = std::is_same_v + ? topology::key_kind::inet_address + : topology::key_kind::host_id; + template static void remove_by_value(C& container, V value) { for (auto it = container.begin(); it != container.end();) { @@ -38,9 +44,8 @@ static void remove_by_value(C& container, V value) { } } +template class token_metadata_impl final { -public: - using inet_address = gms::inet_address; private: /** * Maintains token to endpoint map of every node in the cluster. @@ -48,17 +53,17 @@ private: * multiple tokens. Hence, the BiMultiValMap collection. */ // FIXME: have to be BiMultiValMap - std::unordered_map _token_to_endpoint_map; + std::unordered_map _token_to_endpoint_map; // Track the unique set of nodes in _token_to_endpoint_map - std::unordered_set _normal_token_owners; + std::unordered_set _normal_token_owners; - std::unordered_map _bootstrap_tokens; - std::unordered_set _leaving_endpoints; + std::unordered_map _bootstrap_tokens; + std::unordered_set _leaving_endpoints; // The map between the existing node to be replaced and the replacing node - std::unordered_map _replacing_endpoints; + std::unordered_map _replacing_endpoints; - std::optional _topology_change_info; + std::optional> _topology_change_info; std::vector _sorted_tokens; @@ -94,26 +99,26 @@ private: struct shallow_copy {}; public: token_metadata_impl(shallow_copy, const token_metadata_impl& o) noexcept - : _topology(topology::config{}, topology::key_kind::inet_address) + : _topology(topology::config{}, kind_for_node_id_type) {} - token_metadata_impl(token_metadata::config cfg) noexcept : _topology(std::move(cfg.topo_cfg), topology::key_kind::inet_address) {}; + token_metadata_impl(token_metadata::config cfg) noexcept : _topology(std::move(cfg.topo_cfg), kind_for_node_id_type) {}; token_metadata_impl(const token_metadata_impl&) = delete; // it's too huge for direct copy, use clone_async() token_metadata_impl(token_metadata_impl&&) noexcept = default; const std::vector& sorted_tokens() const; - future<> update_normal_tokens(std::unordered_set tokens, inet_address endpoint); + future<> update_normal_tokens(std::unordered_set tokens, NodeId endpoint); const token& first_token(const token& start) const; size_t first_token_index(const token& start) const; - std::optional get_endpoint(const token& token) const; - std::vector get_tokens(const inet_address& addr) const; - const std::unordered_map& get_token_to_endpoint() const { + std::optional get_endpoint(const token& token) const; + std::vector get_tokens(const NodeId& addr) const; + const std::unordered_map& get_token_to_endpoint() const { return _token_to_endpoint_map; } - const std::unordered_set& get_leaving_endpoints() const { + const std::unordered_set& get_leaving_endpoints() const { return _leaving_endpoints; } - const std::unordered_map& get_bootstrap_tokens() const { + const std::unordered_map& get_bootstrap_tokens() const { return _bootstrap_tokens; } @@ -121,6 +126,10 @@ public: _topology.add_or_update_endpoint(ep, std::nullopt, std::move(opt_dr), std::move(opt_st), std::move(shard_count)); } + void update_topology(host_id ep, std::optional opt_dr, std::optional opt_st, std::optional shard_count = std::nullopt) { + _topology.add_or_update_endpoint(std::nullopt, ep, std::move(opt_dr), std::move(opt_st), std::move(shard_count)); + } + /** * Creates an iterable range of the sorted tokens starting at the token next * after the given one. @@ -129,9 +138,9 @@ public: * * @return The requested range (see the description above) */ - boost::iterator_range ring_range(const token& start) const; + boost::iterator_range::tokens_iterator> ring_range(const token& start) const; - boost::iterator_range ring_range(dht::ring_position_view pos) const; + boost::iterator_range::tokens_iterator> ring_range(dht::ring_position_view pos) const; topology& get_topology() { return _topology; @@ -164,30 +173,30 @@ public: /** @return a copy of the endpoint-to-id map for read-only operations */ std::unordered_map get_endpoint_to_host_id_map_for_reading() const; - void add_bootstrap_token(token t, inet_address endpoint); + void add_bootstrap_token(token t, NodeId endpoint); - void add_bootstrap_tokens(std::unordered_set tokens, inet_address endpoint); + void add_bootstrap_tokens(std::unordered_set tokens, NodeId endpoint); void remove_bootstrap_tokens(std::unordered_set tokens); - void add_leaving_endpoint(inet_address endpoint); - void del_leaving_endpoint(inet_address endpoint); + void add_leaving_endpoint(NodeId endpoint); + void del_leaving_endpoint(NodeId endpoint); public: - void remove_endpoint(inet_address endpoint); + void remove_endpoint(NodeId endpoint); - bool is_normal_token_owner(inet_address endpoint) const; + bool is_normal_token_owner(NodeId endpoint) const; - bool is_leaving(inet_address endpoint) const; + bool is_leaving(NodeId endpoint) const; // Is this node being replaced by another node - bool is_being_replaced(inet_address endpoint) const; + bool is_being_replaced(NodeId endpoint) const; // Is any node being replaced by another node bool is_any_node_being_replaced() const; - void add_replacing_endpoint(inet_address existing_node, inet_address replacing_node); + void add_replacing_endpoint(NodeId existing_node, NodeId replacing_node); - void del_replacing_endpoint(inet_address existing_node); + void del_replacing_endpoint(NodeId existing_node); public: /** @@ -236,8 +245,8 @@ public: static range interval_to_range(boost::icl::interval::interval_type i); public: - future<> update_topology_change_info(dc_rack_fn& get_dc_rack); - const std::optional& get_topology_change_info() const { + future<> update_topology_change_info(dc_rack_fn& get_dc_rack); + const std::optional>& get_topology_change_info() const { return _topology_change_info; } public: @@ -248,7 +257,7 @@ public: // node that is still joining the cluster, e.g., a node that is still // streaming data before it finishes the bootstrap process and turns into // NORMAL status. - const std::unordered_set& get_all_endpoints() const noexcept { + const std::unordered_set& get_all_endpoints() const noexcept { return _normal_token_owners; } @@ -258,11 +267,6 @@ public: private: future<> update_normal_token_owners(); public: - // returns empty vector if keyspace_name not found. - inet_address_vector_topology_change pending_endpoints_for(const token& token, const sstring& keyspace_name) const; - - std::optional endpoints_for_reading(const token& token, const sstring& keyspace_name) const; - void set_read_new(token_metadata::read_new_t read_new) { _read_new = read_new; } @@ -272,7 +276,7 @@ public: * @return a (stable copy, won't be modified) Token to Endpoint map for all the normal and bootstrapping nodes * in the cluster. */ - std::map get_normal_and_bootstrapping_token_to_endpoint_map() const; + std::map get_normal_and_bootstrapping_token_to_endpoint_map() const; long get_ring_version() const { return _ring_version; @@ -289,11 +293,11 @@ public: void set_version(token_metadata::version_t version) { if (version <= 0) { on_internal_error(tlogger, - format("token_metadata_impl::set_version: invalid new version {}", version)); + format("token_metadata_impl::set_version: invalid new version {}", version)); } if (version < _version) { on_internal_error(tlogger, - format("token_metadata_impl::set_version: new version can't be smaller than the previous one, " + format("token_metadata_impl::set_version: new version can't be smaller than the previous one, " "new version {}, previous version {}", version, _version)); } _version = version; @@ -302,26 +306,31 @@ public: _version_tracker = std::move(tracker); } - friend class token_metadata; + friend class generic_token_metadata; }; -thread_local long token_metadata_impl::_static_ring_version; +template +thread_local long token_metadata_impl::_static_ring_version; -token_metadata::tokens_iterator::tokens_iterator(const token& start, const token_metadata_impl* token_metadata) +template +generic_token_metadata::tokens_iterator::tokens_iterator(const token& start, const token_metadata_impl* token_metadata) : _token_metadata(token_metadata) { _cur_it = _token_metadata->sorted_tokens().begin() + _token_metadata->first_token_index(start); _remaining = _token_metadata->sorted_tokens().size(); } -bool token_metadata::tokens_iterator::operator==(const tokens_iterator& it) const { +template +bool generic_token_metadata::tokens_iterator::operator==(const tokens_iterator& it) const { return _remaining == it._remaining; } -const token& token_metadata::tokens_iterator::operator*() const { +template +const token& generic_token_metadata::tokens_iterator::operator*() const { return *_cur_it; } -token_metadata::tokens_iterator& token_metadata::tokens_iterator::operator++() { +template +typename generic_token_metadata::tokens_iterator& generic_token_metadata::tokens_iterator::operator++() { ++_cur_it; if (_cur_it == _token_metadata->sorted_tokens().end()) { _cur_it = _token_metadata->sorted_tokens().begin(); @@ -330,19 +339,22 @@ token_metadata::tokens_iterator& token_metadata::tokens_iterator::operator++() { return *this; } -host_id token_metadata::get_my_id() const { +template +host_id generic_token_metadata::get_my_id() const { return get_topology().get_config().this_host_id; } +template inline -boost::iterator_range -token_metadata_impl::ring_range(const token& start) const { - auto begin = token_metadata::tokens_iterator(start, this); - auto end = token_metadata::tokens_iterator(); +boost::iterator_range::tokens_iterator> +token_metadata_impl::ring_range(const token& start) const { + auto begin = typename generic_token_metadata::tokens_iterator(start, this); + auto end = typename generic_token_metadata::tokens_iterator(); return boost::make_iterator_range(begin, end); } -future> token_metadata_impl::clone_async() const noexcept { +template +future>> token_metadata_impl::clone_async() const noexcept { auto ret = co_await clone_only_token_map(); ret->_bootstrap_tokens.reserve(_bootstrap_tokens.size()); for (const auto& p : _bootstrap_tokens) { @@ -356,7 +368,8 @@ future> token_metadata_impl::clone_async() co_return ret; } -future> token_metadata_impl::clone_only_token_map(bool clone_sorted_tokens) const noexcept { +template +future>> token_metadata_impl::clone_only_token_map(bool clone_sorted_tokens) const noexcept { auto ret = std::make_unique(shallow_copy{}, *this); ret->_token_to_endpoint_map.reserve(_token_to_endpoint_map.size()); for (const auto& p : _token_to_endpoint_map) { @@ -374,7 +387,8 @@ future> token_metadata_impl::clone_only_tok co_return ret; } -future<> token_metadata_impl::clear_gently() noexcept { +template +future<> token_metadata_impl::clear_gently() noexcept { co_await utils::clear_gently(_token_to_endpoint_map); co_await utils::clear_gently(_normal_token_owners); co_await utils::clear_gently(_bootstrap_tokens); @@ -386,7 +400,8 @@ future<> token_metadata_impl::clear_gently() noexcept { co_return; } -void token_metadata_impl::sort_tokens() { +template +void token_metadata_impl::sort_tokens() { std::vector sorted; sorted.reserve(_token_to_endpoint_map.size()); @@ -399,23 +414,28 @@ void token_metadata_impl::sort_tokens() { _sorted_tokens = std::move(sorted); } -const tablet_metadata& token_metadata::tablets() const { +template +const tablet_metadata& generic_token_metadata::tablets() const { return _impl->tablets(); } -tablet_metadata& token_metadata::tablets() { +template +tablet_metadata& generic_token_metadata::tablets() { return _impl->tablets(); } -void token_metadata::set_tablets(tablet_metadata tm) { +template +void generic_token_metadata::set_tablets(tablet_metadata tm) { _impl->set_tablets(std::move(tm)); } -const std::vector& token_metadata_impl::sorted_tokens() const { +template +const std::vector& token_metadata_impl::sorted_tokens() const { return _sorted_tokens; } -std::vector token_metadata_impl::get_tokens(const inet_address& addr) const { +template +std::vector token_metadata_impl::get_tokens(const NodeId& addr) const { std::vector res; for (auto&& i : _token_to_endpoint_map) { if (i.second == addr) { @@ -426,12 +446,13 @@ std::vector token_metadata_impl::get_tokens(const inet_address& addr) con return res; } -future<> token_metadata_impl::update_normal_tokens(std::unordered_set tokens, inet_address endpoint) { +template +future<> token_metadata_impl::update_normal_tokens(std::unordered_set tokens, NodeId endpoint) { if (tokens.empty()) { co_return; } - if (!_topology.has_endpoint(endpoint)) { + if (!_topology.has_node(endpoint)) { on_internal_error(tlogger, format("token_metadata_impl: {} must be a member of topology to update normal tokens", endpoint)); } @@ -465,7 +486,7 @@ future<> token_metadata_impl::update_normal_tokens(std::unordered_set tok for (const token& t : tokens) { co_await coroutine::maybe_yield(); - auto prev = _token_to_endpoint_map.insert(std::pair(t, endpoint)); + auto prev = _token_to_endpoint_map.insert(std::pair(t, endpoint)); should_sort_tokens |= prev.second; // new token inserted -> sort if (prev.first->second != endpoint) { tlogger.debug("Token {} changing ownership from {} to {}", t, prev.first->second, endpoint); @@ -483,7 +504,8 @@ future<> token_metadata_impl::update_normal_tokens(std::unordered_set tok co_return; } -size_t token_metadata_impl::first_token_index(const token& start) const { +template +size_t token_metadata_impl::first_token_index(const token& start) const { if (_sorted_tokens.empty()) { auto msg = format("sorted_tokens is empty in first_token_index!"); tlogger.error("{}", msg); @@ -497,11 +519,13 @@ size_t token_metadata_impl::first_token_index(const token& start) const { } } -const token& token_metadata_impl::first_token(const token& start) const { +template +const token& token_metadata_impl::first_token(const token& start) const { return _sorted_tokens[first_token_index(start)]; } -std::optional token_metadata_impl::get_endpoint(const token& token) const { +template +std::optional token_metadata_impl::get_endpoint(const token& token) const { auto it = _token_to_endpoint_map.find(token); if (it == _token_to_endpoint_map.end()) { return std::nullopt; @@ -510,7 +534,8 @@ std::optional token_metadata_impl::get_endpoint(const token& token } } -void token_metadata_impl::debug_show() const { +template +void token_metadata_impl::debug_show() const { auto reporter = std::make_shared>(); reporter->set_callback ([reporter, this] { fmt::print("Endpoint -> Token\n"); @@ -525,11 +550,13 @@ void token_metadata_impl::debug_show() const { reporter->arm_periodic(std::chrono::seconds(1)); } -void token_metadata_impl::update_host_id(const host_id& host_id, inet_address endpoint) { +template +void token_metadata_impl::update_host_id(const host_id& host_id, inet_address endpoint) { _topology.add_or_update_endpoint(endpoint, host_id); } -host_id token_metadata_impl::get_host_id(inet_address endpoint) const { +template +host_id token_metadata_impl::get_host_id(inet_address endpoint) const { if (const auto* node = _topology.find_node(endpoint)) [[likely]] { return node->host_id(); } else { @@ -537,7 +564,8 @@ host_id token_metadata_impl::get_host_id(inet_address endpoint) const { } } -std::optional token_metadata_impl::get_host_id_if_known(inet_address endpoint) const { +template +std::optional token_metadata_impl::get_host_id_if_known(inet_address endpoint) const { if (const auto* node = _topology.find_node(endpoint)) [[likely]] { return node->host_id(); } else { @@ -545,7 +573,8 @@ std::optional token_metadata_impl::get_host_id_if_known(inet_address en } } -std::optional token_metadata_impl::get_endpoint_for_host_id(host_id host_id) const { +template +std::optional token_metadata_impl::get_endpoint_for_host_id(host_id host_id) const { if (const auto* node = _topology.find_node(host_id)) [[likely]] { return node->endpoint(); } else { @@ -553,7 +582,8 @@ std::optional token_metadata_impl::get_endpoint_for_host_id(host_i } } -std::unordered_map token_metadata_impl::get_endpoint_to_host_id_map_for_reading() const { +template +std::unordered_map token_metadata_impl::get_endpoint_to_host_id_map_for_reading() const { const auto& nodes = _topology.get_nodes_by_endpoint(); std::unordered_map map; map.reserve(nodes.size()); @@ -571,21 +601,25 @@ std::unordered_map token_metadata_impl::get_endpoint_to_h return map; } -bool token_metadata_impl::is_normal_token_owner(inet_address endpoint) const { +template +bool token_metadata_impl::is_normal_token_owner(NodeId endpoint) const { return _normal_token_owners.contains(endpoint); } -void token_metadata_impl::add_bootstrap_token(token t, inet_address endpoint) { +template +void token_metadata_impl::add_bootstrap_token(token t, NodeId endpoint) { std::unordered_set tokens{t}; add_bootstrap_tokens(tokens, endpoint); } -boost::iterator_range -token_metadata_impl::ring_range(const dht::ring_position_view start) const { +template +boost::iterator_range::tokens_iterator> +token_metadata_impl::ring_range(const dht::ring_position_view start) const { return ring_range(start.token()); } -void token_metadata_impl::add_bootstrap_tokens(std::unordered_set tokens, inet_address endpoint) { +template +void token_metadata_impl::add_bootstrap_tokens(std::unordered_set tokens, NodeId endpoint) { for (auto t : tokens) { auto old_endpoint = _bootstrap_tokens.find(t); if (old_endpoint != _bootstrap_tokens.end() && (*old_endpoint).second != endpoint) { @@ -600,14 +634,15 @@ void token_metadata_impl::add_bootstrap_tokens(std::unordered_set tokens, } } - std::erase_if(_bootstrap_tokens, [endpoint] (const std::pair& n) { return n.second == endpoint; }); + std::erase_if(_bootstrap_tokens, [endpoint] (const std::pair& n) { return n.second == endpoint; }); for (auto t : tokens) { _bootstrap_tokens[t] = endpoint; } } -void token_metadata_impl::remove_bootstrap_tokens(std::unordered_set tokens) { +template +void token_metadata_impl::remove_bootstrap_tokens(std::unordered_set tokens) { if (tokens.empty()) { tlogger.warn("tokens is empty in remove_bootstrap_tokens!"); return; @@ -617,19 +652,23 @@ void token_metadata_impl::remove_bootstrap_tokens(std::unordered_set toke } } -bool token_metadata_impl::is_leaving(inet_address endpoint) const { +template +bool token_metadata_impl::is_leaving(NodeId endpoint) const { return _leaving_endpoints.contains(endpoint); } -bool token_metadata_impl::is_being_replaced(inet_address endpoint) const { +template +bool token_metadata_impl::is_being_replaced(NodeId endpoint) const { return _replacing_endpoints.contains(endpoint); } -bool token_metadata_impl::is_any_node_being_replaced() const { +template +bool token_metadata_impl::is_any_node_being_replaced() const { return !_replacing_endpoints.empty(); } -void token_metadata_impl::remove_endpoint(inet_address endpoint) { +template +void token_metadata_impl::remove_endpoint(NodeId endpoint) { remove_by_value(_bootstrap_tokens, endpoint); remove_by_value(_token_to_endpoint_map, endpoint); _normal_token_owners.erase(endpoint); @@ -639,7 +678,8 @@ void token_metadata_impl::remove_endpoint(inet_address endpoint) { invalidate_cached_rings(); } -token token_metadata_impl::get_predecessor(token t) const { +template +token token_metadata_impl::get_predecessor(token t) const { auto& tokens = sorted_tokens(); auto it = std::lower_bound(tokens.begin(), tokens.end(), t); if (it == tokens.end() || *it != t) { @@ -655,7 +695,8 @@ token token_metadata_impl::get_predecessor(token t) const { } } -dht::token_range_vector token_metadata_impl::get_primary_ranges_for(std::unordered_set tokens) const { +template +dht::token_range_vector token_metadata_impl::get_primary_ranges_for(std::unordered_set tokens) const { dht::token_range_vector ranges; ranges.reserve(tokens.size() + 1); // one of the ranges will wrap for (auto right : tokens) { @@ -668,12 +709,14 @@ dht::token_range_vector token_metadata_impl::get_primary_ranges_for(std::unorder return ranges; } -dht::token_range_vector token_metadata_impl::get_primary_ranges_for(token right) const { +template +dht::token_range_vector token_metadata_impl::get_primary_ranges_for(token right) const { return get_primary_ranges_for(std::unordered_set{right}); } +template boost::icl::interval::interval_type -token_metadata_impl::range_to_interval(range r) { +token_metadata_impl::range_to_interval(range r) { bool start_inclusive = false; bool end_inclusive = false; token start = dht::minimum_token(); @@ -700,8 +743,9 @@ token_metadata_impl::range_to_interval(range r) { } } +template range -token_metadata_impl::interval_to_range(boost::icl::interval::interval_type i) { +token_metadata_impl::interval_to_range(boost::icl::interval::interval_type i) { bool start_inclusive; bool end_inclusive; auto bounds = i.bounds().bits(); @@ -723,7 +767,8 @@ token_metadata_impl::interval_to_range(boost::icl::interval::interval_typ return range({{i.lower(), start_inclusive}}, {{i.upper(), end_inclusive}}); } -future<> token_metadata_impl::update_topology_change_info(dc_rack_fn& get_dc_rack) { +template +future<> token_metadata_impl::update_topology_change_info(dc_rack_fn& get_dc_rack) { if (_bootstrap_tokens.empty() && _leaving_endpoints.empty() && _replacing_endpoints.empty()) { co_await utils::clear_gently(_topology_change_info); _topology_change_info.reset(); @@ -736,7 +781,7 @@ future<> token_metadata_impl::update_topology_change_info(dc_rack_fn> new_normal_tokens; + std::unordered_map> new_normal_tokens; if (!_replacing_endpoints.empty()) { for (const auto& [token, inet_address]: _token_to_endpoint_map) { const auto it = _replacing_endpoints.find(inet_address); @@ -796,19 +841,21 @@ future<> token_metadata_impl::update_topology_change_info(dc_rack_fn>(std::move(target_token_metadata)), + base_token_metadata ? make_lw_shared>(std::move(base_token_metadata)): nullptr, std::move(all_tokens), _read_new); co_await utils::clear_gently(prev_value); } -size_t token_metadata_impl::count_normal_token_owners() const { +template +size_t token_metadata_impl::count_normal_token_owners() const { return _normal_token_owners.size(); } -future<> token_metadata_impl::update_normal_token_owners() { - std::unordered_set eps; +template +future<> token_metadata_impl::update_normal_token_owners() { + std::unordered_set eps; for (auto [t, ep]: _token_to_endpoint_map) { eps.insert(ep); co_await coroutine::maybe_yield(); @@ -816,21 +863,25 @@ future<> token_metadata_impl::update_normal_token_owners() { _normal_token_owners = std::move(eps); } -void token_metadata_impl::add_leaving_endpoint(inet_address endpoint) { +template +void token_metadata_impl::add_leaving_endpoint(NodeId endpoint) { _leaving_endpoints.emplace(endpoint); } -void token_metadata_impl::del_leaving_endpoint(inet_address endpoint) { +template +void token_metadata_impl::del_leaving_endpoint(NodeId endpoint) { _leaving_endpoints.erase(endpoint); } -void token_metadata_impl::add_replacing_endpoint(inet_address existing_node, inet_address replacing_node) { +template +void token_metadata_impl::add_replacing_endpoint(NodeId existing_node, NodeId replacing_node) { tlogger.info("Added node {} as pending replacing endpoint which replaces existing node {}", replacing_node, existing_node); _replacing_endpoints[existing_node] = replacing_node; } -void token_metadata_impl::del_replacing_endpoint(inet_address existing_node) { +template +void token_metadata_impl::del_replacing_endpoint(NodeId existing_node) { if (_replacing_endpoints.contains(existing_node)) { tlogger.info("Removed node {} as pending replacing endpoint which replaces existing node {}", _replacing_endpoints[existing_node], existing_node); @@ -838,14 +889,16 @@ void token_metadata_impl::del_replacing_endpoint(inet_address existing_node) { _replacing_endpoints.erase(existing_node); } -std::map token_metadata_impl::get_normal_and_bootstrapping_token_to_endpoint_map() const { - std::map ret(_token_to_endpoint_map.begin(), _token_to_endpoint_map.end()); +template +std::map token_metadata_impl::get_normal_and_bootstrapping_token_to_endpoint_map() const { + std::map ret(_token_to_endpoint_map.begin(), _token_to_endpoint_map.end()); ret.insert(_bootstrap_tokens.begin(), _bootstrap_tokens.end()); return ret; } -topology_change_info::topology_change_info(token_metadata_ptr target_token_metadata_, - token_metadata_ptr base_token_metadata_, +template +topology_change_info::topology_change_info(lw_shared_ptr> target_token_metadata_, + lw_shared_ptr> base_token_metadata_, std::vector all_tokens_, token_metadata::read_new_t read_new_) : target_token_metadata(std::move(target_token_metadata_)) @@ -855,84 +908,101 @@ topology_change_info::topology_change_info(token_metadata_ptr target_token_metad { } -future<> topology_change_info::clear_gently() { +template +future<> topology_change_info::clear_gently() { co_await utils::clear_gently(target_token_metadata); co_await utils::clear_gently(base_token_metadata); co_await utils::clear_gently(all_tokens); } -token_metadata::token_metadata(std::unique_ptr impl) +template +generic_token_metadata::generic_token_metadata(std::unique_ptr> impl) : _impl(std::move(impl)) { } -token_metadata::token_metadata(config cfg) - : _impl(std::make_unique(std::move(cfg))) { +template +generic_token_metadata::generic_token_metadata(config cfg) + : _impl(std::make_unique>(std::move(cfg))) { } -token_metadata::~token_metadata() = default; +template +generic_token_metadata::~generic_token_metadata() = default; +template +generic_token_metadata::generic_token_metadata(generic_token_metadata&&) noexcept = default; -token_metadata::token_metadata(token_metadata&&) noexcept = default; - -token_metadata& token_metadata::token_metadata::operator=(token_metadata&&) noexcept = default; +template +generic_token_metadata& generic_token_metadata::generic_token_metadata::operator=(generic_token_metadata&&) noexcept = default; +template const std::vector& -token_metadata::sorted_tokens() const { +generic_token_metadata::sorted_tokens() const { return _impl->sorted_tokens(); } +template future<> -token_metadata::update_normal_tokens(std::unordered_set tokens, inet_address endpoint) { +generic_token_metadata::update_normal_tokens(std::unordered_set tokens, NodeId endpoint) { return _impl->update_normal_tokens(std::move(tokens), endpoint); } +template const token& -token_metadata::first_token(const token& start) const { +generic_token_metadata::first_token(const token& start) const { return _impl->first_token(start); } +template size_t -token_metadata::first_token_index(const token& start) const { +generic_token_metadata::first_token_index(const token& start) const { return _impl->first_token_index(start); } -std::optional -token_metadata::get_endpoint(const token& token) const { +template +std::optional +generic_token_metadata::get_endpoint(const token& token) const { return _impl->get_endpoint(token); } +template std::vector -token_metadata::get_tokens(const inet_address& addr) const { +generic_token_metadata::get_tokens(const NodeId& addr) const { return _impl->get_tokens(addr); } -const std::unordered_map& -token_metadata::get_token_to_endpoint() const { +template +const std::unordered_map& +generic_token_metadata::get_token_to_endpoint() const { return _impl->get_token_to_endpoint(); } -const std::unordered_set& -token_metadata::get_leaving_endpoints() const { +template +const std::unordered_set& +generic_token_metadata::get_leaving_endpoints() const { return _impl->get_leaving_endpoints(); } -const std::unordered_map& -token_metadata::get_bootstrap_tokens() const { +template +const std::unordered_map& +generic_token_metadata::get_bootstrap_tokens() const { return _impl->get_bootstrap_tokens(); } +template void -token_metadata::update_topology(inet_address ep, std::optional opt_dr, std::optional opt_st, std::optional shard_count) { +generic_token_metadata::update_topology(NodeId ep, std::optional opt_dr, std::optional opt_st, std::optional shard_count) { _impl->update_topology(ep, std::move(opt_dr), std::move(opt_st), std::move(shard_count)); } -boost::iterator_range -token_metadata::ring_range(const token& start) const { +template +boost::iterator_range::tokens_iterator> +generic_token_metadata::ring_range(const token& start) const { return _impl->ring_range(start); } -boost::iterator_range -token_metadata::ring_range(dht::ring_position_view start) const { +template +boost::iterator_range::tokens_iterator> +generic_token_metadata::ring_range(dht::ring_position_view start) const { return _impl->ring_range(start); } @@ -965,210 +1035,251 @@ std::unique_ptr make_splitter(token_metadata_ptr return std::make_unique(std::move(tmptr)); } +template topology& -token_metadata::get_topology() { +generic_token_metadata::get_topology() { return _impl->get_topology(); } +template const topology& -token_metadata::get_topology() const { +generic_token_metadata::get_topology() const { return _impl->get_topology(); } +template void -token_metadata::debug_show() const { +generic_token_metadata::debug_show() const { _impl->debug_show(); } +template void -token_metadata::update_host_id(const host_id& host_id, inet_address endpoint) { +generic_token_metadata::update_host_id(const host_id& host_id, inet_address endpoint) { _impl->update_host_id(host_id, endpoint); } +template host_id -token_metadata::get_host_id(inet_address endpoint) const { +generic_token_metadata::get_host_id(inet_address endpoint) const { return _impl->get_host_id(endpoint); } +template std::optional -token_metadata::get_host_id_if_known(inet_address endpoint) const { +generic_token_metadata::get_host_id_if_known(inet_address endpoint) const { return _impl->get_host_id_if_known(endpoint); } -std::optional -token_metadata::get_endpoint_for_host_id(host_id host_id) const { +template +std::optional::inet_address> +generic_token_metadata::get_endpoint_for_host_id(host_id host_id) const { return _impl->get_endpoint_for_host_id(host_id); } -host_id_or_endpoint token_metadata::parse_host_id_and_endpoint(const sstring& host_id_string) const { +template +host_id_or_endpoint generic_token_metadata::parse_host_id_and_endpoint(const sstring& host_id_string) const { auto res = host_id_or_endpoint(host_id_string); res.resolve(*this); return res; } +template std::unordered_map -token_metadata::get_endpoint_to_host_id_map_for_reading() const { +generic_token_metadata::get_endpoint_to_host_id_map_for_reading() const { return _impl->get_endpoint_to_host_id_map_for_reading(); } +template void -token_metadata::add_bootstrap_token(token t, inet_address endpoint) { +generic_token_metadata::add_bootstrap_token(token t, NodeId endpoint) { _impl->add_bootstrap_token(t, endpoint); } +template void -token_metadata::add_bootstrap_tokens(std::unordered_set tokens, inet_address endpoint) { +generic_token_metadata::add_bootstrap_tokens(std::unordered_set tokens, NodeId endpoint) { _impl->add_bootstrap_tokens(std::move(tokens), endpoint); } +template void -token_metadata::remove_bootstrap_tokens(std::unordered_set tokens) { +generic_token_metadata::remove_bootstrap_tokens(std::unordered_set tokens) { _impl->remove_bootstrap_tokens(std::move(tokens)); } +template void -token_metadata::add_leaving_endpoint(inet_address endpoint) { +generic_token_metadata::add_leaving_endpoint(NodeId endpoint) { _impl->add_leaving_endpoint(endpoint); } +template void -token_metadata::del_leaving_endpoint(inet_address endpoint) { +generic_token_metadata::del_leaving_endpoint(NodeId endpoint) { _impl->del_leaving_endpoint(endpoint); } +template void -token_metadata::remove_endpoint(inet_address endpoint) { +generic_token_metadata::remove_endpoint(NodeId endpoint) { _impl->remove_endpoint(endpoint); _impl->sort_tokens(); } +template bool -token_metadata::is_normal_token_owner(inet_address endpoint) const { +generic_token_metadata::is_normal_token_owner(NodeId endpoint) const { return _impl->is_normal_token_owner(endpoint); } +template bool -token_metadata::is_leaving(inet_address endpoint) const { +generic_token_metadata::is_leaving(NodeId endpoint) const { return _impl->is_leaving(endpoint); } +template bool -token_metadata::is_being_replaced(inet_address endpoint) const { +generic_token_metadata::is_being_replaced(NodeId endpoint) const { return _impl->is_being_replaced(endpoint); } +template bool -token_metadata::is_any_node_being_replaced() const { +generic_token_metadata::is_any_node_being_replaced() const { return _impl->is_any_node_being_replaced(); } -void token_metadata::add_replacing_endpoint(inet_address existing_node, inet_address replacing_node) { +template +void generic_token_metadata::add_replacing_endpoint(NodeId existing_node, NodeId replacing_node) { _impl->add_replacing_endpoint(existing_node, replacing_node); } -void token_metadata::del_replacing_endpoint(inet_address existing_node) { +template +void generic_token_metadata::del_replacing_endpoint(NodeId existing_node) { _impl->del_replacing_endpoint(existing_node); } -future token_metadata::clone_async() const noexcept { - return _impl->clone_async().then([] (std::unique_ptr impl) { - return make_ready_future(std::move(impl)); +template +future> generic_token_metadata::clone_async() const noexcept { + return _impl->clone_async().then([] (std::unique_ptr> impl) { + return make_ready_future(std::move(impl)); }); } -future -token_metadata::clone_only_token_map() const noexcept { - return _impl->clone_only_token_map().then([] (std::unique_ptr impl) { - return token_metadata(std::move(impl)); +template +future> +generic_token_metadata::clone_only_token_map() const noexcept { + return _impl->clone_only_token_map().then([] (std::unique_ptr> impl) { + return generic_token_metadata(std::move(impl)); }); } -future -token_metadata::clone_after_all_left() const noexcept { - return _impl->clone_after_all_left().then([] (std::unique_ptr impl) { - return token_metadata(std::move(impl)); +template +future> +generic_token_metadata::clone_after_all_left() const noexcept { + return _impl->clone_after_all_left().then([] (std::unique_ptr> impl) { + return generic_token_metadata(std::move(impl)); }); } -future<> token_metadata::clear_gently() noexcept { +template +future<> generic_token_metadata::clear_gently() noexcept { return _impl->clear_gently(); } +template dht::token_range_vector -token_metadata::get_primary_ranges_for(std::unordered_set tokens) const { +generic_token_metadata::get_primary_ranges_for(std::unordered_set tokens) const { return _impl->get_primary_ranges_for(std::move(tokens)); } +template dht::token_range_vector -token_metadata::get_primary_ranges_for(token right) const { +generic_token_metadata::get_primary_ranges_for(token right) const { return _impl->get_primary_ranges_for(right); } +template boost::icl::interval::interval_type -token_metadata::range_to_interval(range r) { - return token_metadata_impl::range_to_interval(std::move(r)); +generic_token_metadata::range_to_interval(range r) { + return token_metadata_impl::range_to_interval(std::move(r)); } +template range -token_metadata::interval_to_range(boost::icl::interval::interval_type i) { - return token_metadata_impl::interval_to_range(std::move(i)); +generic_token_metadata::interval_to_range(boost::icl::interval::interval_type i) { + return token_metadata_impl::interval_to_range(std::move(i)); } +template future<> -token_metadata::update_topology_change_info(dc_rack_fn& get_dc_rack) { +generic_token_metadata::update_topology_change_info(dc_rack_fn& get_dc_rack) { return _impl->update_topology_change_info(get_dc_rack); } -const std::optional& -token_metadata::get_topology_change_info() const { +template +const std::optional>& +generic_token_metadata::get_topology_change_info() const { return _impl->get_topology_change_info(); } +template token -token_metadata::get_predecessor(token t) const { +generic_token_metadata::get_predecessor(token t) const { return _impl->get_predecessor(t); } -const std::unordered_set& -token_metadata::get_all_endpoints() const { +template +const std::unordered_set& +generic_token_metadata::get_all_endpoints() const { return _impl->get_all_endpoints(); } +template size_t -token_metadata::count_normal_token_owners() const { +generic_token_metadata::count_normal_token_owners() const { return _impl->count_normal_token_owners(); } +template void -token_metadata::set_read_new(read_new_t read_new) { +generic_token_metadata::set_read_new(read_new_t read_new) { _impl->set_read_new(read_new); } -std::map -token_metadata::get_normal_and_bootstrapping_token_to_endpoint_map() const { +template +std::map +generic_token_metadata::get_normal_and_bootstrapping_token_to_endpoint_map() const { return _impl->get_normal_and_bootstrapping_token_to_endpoint_map(); } +template long -token_metadata::get_ring_version() const { +generic_token_metadata::get_ring_version() const { return _impl->get_ring_version(); } +template void -token_metadata::invalidate_cached_rings() { +generic_token_metadata::invalidate_cached_rings() { _impl->invalidate_cached_rings(); } +template auto -token_metadata::get_version() const -> version_t { +generic_token_metadata::get_version() const -> version_t { return _impl->get_version(); } +template void -token_metadata::set_version(version_t version) { +generic_token_metadata::set_version(version_t version) { _impl->set_version(version); } +template void -token_metadata::set_version_tracker(version_tracker_t tracker) { +generic_token_metadata::set_version_tracker(version_tracker_t tracker) { _impl->set_version_tracker(std::move(tracker)); } @@ -1190,7 +1301,7 @@ void shared_token_metadata::set(mutable_token_metadata_ptr tmptr) noexcept { void shared_token_metadata::update_fence_version(token_metadata::version_t version) { if (const auto current_version = _shared->get_version(); version > current_version) { - // The token_metadata::version under no circumstance can go backwards. + // The generic_token_metadata::version under no circumstance can go backwards. // Even in case of topology change coordinator moving to another node // this condition must hold, that is why we treat its violation // as an internal error. @@ -1277,7 +1388,8 @@ host_id_or_endpoint::host_id_or_endpoint(const sstring& s, param_type restrict) } } -void host_id_or_endpoint::resolve(const token_metadata& tm) { +template +void host_id_or_endpoint::resolve(const generic_token_metadata& tm) { if (id) { auto endpoint_opt = tm.get_endpoint_for_host_id(id); if (!endpoint_opt) { @@ -1293,4 +1405,9 @@ void host_id_or_endpoint::resolve(const token_metadata& tm) { } } +template class generic_token_metadata; +template class generic_token_metadata; +template void host_id_or_endpoint::resolve(const token_metadata& tm); +template void host_id_or_endpoint::resolve(const token_metadata2& tm); + } // namespace locator diff --git a/locator/token_metadata.hh b/locator/token_metadata.hh index 841b68fd37..8b5b4310f6 100644 --- a/locator/token_metadata.hh +++ b/locator/token_metadata.hh @@ -43,7 +43,10 @@ class abstract_replication_strategy; using token = dht::token; -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; class tablet_metadata; struct host_id_or_endpoint { @@ -68,14 +71,16 @@ struct host_id_or_endpoint { // Map the host_id to endpoint based on whichever of them is set, // using the token_metadata - void resolve(const token_metadata& tm); + template + void resolve(const generic_token_metadata& tm); }; +template class token_metadata_impl; +template struct topology_change_info; -class token_metadata final { - std::unique_ptr _impl; +class generic_token_metadata_base { public: struct config { topology::config topo_cfg; @@ -83,6 +88,11 @@ public: using inet_address = gms::inet_address; using version_t = service::topology::version_t; using version_tracker_t = utils::phased_barrier::operation; +}; + +template +class generic_token_metadata final: public generic_token_metadata_base { + std::unique_ptr> _impl; private: friend class token_metadata_ring_splitter; class tokens_iterator { @@ -94,24 +104,24 @@ private: using reference = token&; public: tokens_iterator() = default; - tokens_iterator(const token& start, const token_metadata_impl* token_metadata); + tokens_iterator(const token& start, const token_metadata_impl* token_metadata); bool operator==(const tokens_iterator& it) const; const token& operator*() const; tokens_iterator& operator++(); private: std::vector::const_iterator _cur_it; size_t _remaining = 0; - const token_metadata_impl* _token_metadata = nullptr; + const token_metadata_impl* _token_metadata = nullptr; - friend class token_metadata_impl; + friend class token_metadata_impl; }; public: - token_metadata(config cfg); - explicit token_metadata(std::unique_ptr impl); - token_metadata(token_metadata&&) noexcept; // Can't use "= default;" - hits some static_assert in unique_ptr - token_metadata& operator=(token_metadata&&) noexcept; - ~token_metadata(); + generic_token_metadata(config cfg); + explicit generic_token_metadata(std::unique_ptr> impl); + generic_token_metadata(generic_token_metadata&&) noexcept; // Can't use "= default;" - hits some static_assert in unique_ptr + generic_token_metadata& operator=(generic_token_metadata&&) noexcept; + ~generic_token_metadata(); const std::vector& sorted_tokens() const; const tablet_metadata& tablets() const; tablet_metadata& tablets(); @@ -121,19 +131,19 @@ public: // // Note: the function is not exception safe! // It must be called only on a temporary copy of the token_metadata - future<> update_normal_tokens(std::unordered_set tokens, inet_address endpoint); + future<> update_normal_tokens(std::unordered_set tokens, NodeId endpoint); const token& first_token(const token& start) const; size_t first_token_index(const token& start) const; - std::optional get_endpoint(const token& token) const; - std::vector get_tokens(const inet_address& addr) const; - const std::unordered_map& get_token_to_endpoint() const; - const std::unordered_set& get_leaving_endpoints() const; - const std::unordered_map& get_bootstrap_tokens() const; + std::optional get_endpoint(const token& token) const; + std::vector get_tokens(const NodeId& addr) const; + const std::unordered_map& get_token_to_endpoint() const; + const std::unordered_set& get_leaving_endpoints() const; + const std::unordered_map& get_bootstrap_tokens() const; /** * Update or add endpoint given its inet_address and endpoint_dc_rack. */ - void update_topology(inet_address ep, std::optional opt_dr, std::optional opt_st = std::nullopt, + void update_topology(NodeId ep, std::optional opt_dr, std::optional opt_st = std::nullopt, std::optional shard_count = std::nullopt); /** * Creates an iterable range of the sorted tokens starting at the token t @@ -182,39 +192,39 @@ public: /// Returns host_id of the local node. host_id get_my_id() const; - void add_bootstrap_token(token t, inet_address endpoint); + void add_bootstrap_token(token t, NodeId endpoint); - void add_bootstrap_tokens(std::unordered_set tokens, inet_address endpoint); + void add_bootstrap_tokens(std::unordered_set tokens, NodeId endpoint); void remove_bootstrap_tokens(std::unordered_set tokens); - void add_leaving_endpoint(inet_address endpoint); - void del_leaving_endpoint(inet_address endpoint); + void add_leaving_endpoint(NodeId endpoint); + void del_leaving_endpoint(NodeId endpoint); - void remove_endpoint(inet_address endpoint); + void remove_endpoint(NodeId endpoint); // Checks if the node is part of the token ring. If yes, the node is one of // the nodes that owns the tokens and inside the set _normal_token_owners. - bool is_normal_token_owner(inet_address endpoint) const; + bool is_normal_token_owner(NodeId endpoint) const; - bool is_leaving(inet_address endpoint) const; + bool is_leaving(NodeId endpoint) const; // Is this node being replaced by another node - bool is_being_replaced(inet_address endpoint) const; + bool is_being_replaced(NodeId endpoint) const; // Is any node being replaced by another node bool is_any_node_being_replaced() const; - void add_replacing_endpoint(inet_address existing_node, inet_address replacing_node); + void add_replacing_endpoint(NodeId existing_node, NodeId replacing_node); - void del_replacing_endpoint(inet_address existing_node); + void del_replacing_endpoint(NodeId existing_node); /** * Create a full copy of token_metadata using asynchronous continuations. * The caller must ensure that the cloned object will not change if * the function yields. */ - future clone_async() const noexcept; + future clone_async() const noexcept; /** * Create a copy of TokenMetadata with only tokenToEndpointMap. That is, pending ranges, @@ -222,7 +232,7 @@ public: * The caller must ensure that the cloned object will not change if * the function yields. */ - future clone_only_token_map() const noexcept; + future clone_only_token_map() const noexcept; /** * Create a copy of TokenMetadata with tokenToEndpointMap reflecting situation after all * current leave operations have finished. @@ -231,7 +241,7 @@ public: * * @return a future holding a new token metadata */ - future clone_after_all_left() const noexcept; + future clone_after_all_left() const noexcept; /** * Gently clear the token_metadata members. @@ -251,13 +261,13 @@ public: static boost::icl::interval::interval_type range_to_interval(range r); static range interval_to_range(boost::icl::interval::interval_type i); - future<> update_topology_change_info(dc_rack_fn& get_dc_rack); + future<> update_topology_change_info(dc_rack_fn& get_dc_rack); - const std::optional& get_topology_change_info() const; + const std::optional>& get_topology_change_info() const; token get_predecessor(token t) const; - const std::unordered_set& get_all_endpoints() const; + const std::unordered_set& get_all_endpoints() const; /* Returns the number of different endpoints that own tokens in the ring. * Bootstrapping tokens are not taken into account. */ @@ -275,7 +285,7 @@ public: * @return a (stable copy, won't be modified) Token to Endpoint map for all the normal and bootstrapping nodes * in the cluster. */ - std::map get_normal_and_bootstrapping_token_to_endpoint_map() const; + std::map get_normal_and_bootstrapping_token_to_endpoint_map() const; long get_ring_version() const; void invalidate_cached_rings(); @@ -283,20 +293,26 @@ public: version_t get_version() const; void set_version(version_t version); - friend class token_metadata_impl; + friend class token_metadata_impl; friend class shared_token_metadata; private: void set_version_tracker(version_tracker_t tracker); }; +extern template class generic_token_metadata; +extern template class generic_token_metadata; +extern template void host_id_or_endpoint::resolve(const token_metadata& tm); +extern template void host_id_or_endpoint::resolve(const token_metadata2& tm); + +template struct topology_change_info { - token_metadata_ptr target_token_metadata; - token_metadata_ptr base_token_metadata; + lw_shared_ptr> target_token_metadata; + lw_shared_ptr> base_token_metadata; std::vector all_tokens; token_metadata::read_new_t read_new; - topology_change_info(token_metadata_ptr target_token_metadata_, - token_metadata_ptr base_token_metadata_, + topology_change_info(lw_shared_ptr> target_token_metadata_, + lw_shared_ptr> base_token_metadata_, std::vector all_tokens_, token_metadata::read_new_t read_new_); future<> clear_gently(); @@ -310,6 +326,11 @@ mutable_token_metadata_ptr make_token_metadata_ptr(Args... args) { return make_lw_shared(std::forward(args)...); } +template +mutable_token_metadata2_ptr make_token_metadata2_ptr(Args... args) { + return make_lw_shared(std::forward(args)...); +} + class shared_token_metadata { mutable_token_metadata_ptr _shared; token_metadata_lock_func _lock_func; diff --git a/locator/token_metadata_fwd.hh b/locator/token_metadata_fwd.hh index 07f470bca7..5e67605e3b 100644 --- a/locator/token_metadata_fwd.hh +++ b/locator/token_metadata_fwd.hh @@ -11,9 +11,13 @@ namespace locator { -class token_metadata; - +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; using token_metadata_ptr = lw_shared_ptr; using mutable_token_metadata_ptr = lw_shared_ptr; +using token_metadata2 = generic_token_metadata; +using token_metadata2_ptr = lw_shared_ptr; +using mutable_token_metadata2_ptr = lw_shared_ptr; } // namespace locator diff --git a/locator/topology.cc b/locator/topology.cc index b23a6c238f..55e6631c46 100644 --- a/locator/topology.cc +++ b/locator/topology.cc @@ -491,6 +491,17 @@ bool topology::remove_endpoint(inet_address ep) return false; } +bool topology::remove_endpoint(locator::host_id host_id) +{ + auto node = find_node(host_id); + tlogger.debug("topology[{}]: remove_endpoint: host_id={}: {}", fmt::ptr(this), host_id, debug_format(node)); + if (node) { + remove_node(node); + return true; + } + return false; +} + bool topology::has_node(host_id id) const noexcept { auto node = find_node(id); tlogger.trace("topology[{}]: has_node: host_id={}: {}", fmt::ptr(this), id, debug_format(node)); diff --git a/locator/topology.hh b/locator/topology.hh index 5e87b66291..ad436af2bf 100644 --- a/locator/topology.hh +++ b/locator/topology.hh @@ -258,6 +258,8 @@ public: */ bool remove_endpoint(inet_address ep); + bool remove_endpoint(locator::host_id ep); + /** * Returns true iff contains given endpoint. */ @@ -422,6 +424,7 @@ private: return _nodes_by_endpoint; }; + template friend class token_metadata_impl; public: void test_compare_endpoints(const inet_address& address, const inet_address& a1, const inet_address& a2) const; diff --git a/node_ops/node_ops_ctl.hh b/node_ops/node_ops_ctl.hh index cc2d9dfdab..3d30136bc5 100644 --- a/node_ops/node_ops_ctl.hh +++ b/node_ops/node_ops_ctl.hh @@ -13,6 +13,7 @@ #include "locator/host_id.hh" #include "node_ops/id.hh" #include "schema/schema_fwd.hh" +#include "locator/host_id.hh" #include @@ -24,7 +25,10 @@ class storage_service; } namespace locator { -class token_metadata; +template +class generic_token_metadata; +using token_metadata = generic_token_metadata; +using token_metadata2 = generic_token_metadata; } class node_ops_info {