topology: Add printer wrapper for node* and formatter for it

Currently to print node information there's a debug_format(node*) helper
function that returns back an sstring object. Here's the formatter
that's more flexible and convenient, and a node_printer wrapper, since
formatters cannot format non-void pointers.

Signed-off-by: Pavel Emelyanov <xemul@scylladb.com>
This commit is contained in:
Pavel Emelyanov
2024-02-08 12:32:53 +03:00
parent aa0293f411
commit da53854b66

View File

@@ -16,6 +16,24 @@
#include "locator/production_snitch_base.hh"
#include "utils/stall_free.hh"
struct node_printer {
const locator::node* v;
node_printer(const locator::node* n) noexcept : v(n) {}
};
template <>
struct fmt::formatter<node_printer> {
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
auto format(const node_printer& np, fmt::format_context& ctx) const {
const locator::node* node = np.v;
auto out = fmt::format_to(ctx.out(), "node={}", fmt::ptr(node));
if (node) {
out = fmt::format_to(out, " {:v}", *node);
}
return out;
}
};
namespace locator {
static logging::logger tlogger("topology");
@@ -124,14 +142,6 @@ future<topology> topology::clone_gently() const {
co_return ret;
}
std::string topology::debug_format(const node* node) {
if (!node) {
return format("node={}", fmt::ptr(node));
}
return format("node={} idx={} host_id={} endpoint={} dc={} rack={} state={} shards={} this_node={}", fmt::ptr(node),
node->idx(), node->host_id(), node->endpoint(), node->dc_rack().dc, node->dc_rack().rack, node::to_string(node->get_state()), node->get_shard_count(), bool(node->is_this_node()));
}
const node* topology::add_node(host_id id, const inet_address& ep, const endpoint_dc_rack& dr, node::state state, shard_id shard_count) {
if (dr.dc.empty() || dr.rack.empty()) {
on_internal_error(tlogger, "Node must have valid dc and rack");
@@ -154,13 +164,13 @@ const node* topology::add_node(node_holder nptr) {
if (nptr->topology() != this) {
if (nptr->topology()) {
on_fatal_internal_error(tlogger, format("topology[{}]: {} belongs to different topology={}", fmt::ptr(this), debug_format(node), fmt::ptr(node->topology())));
on_fatal_internal_error(tlogger, format("topology[{}]: {} belongs to different topology={}", fmt::ptr(this), node_printer(node), fmt::ptr(node->topology())));
}
nptr->set_topology(this);
}
if (node->idx() > 0) {
on_internal_error(tlogger, format("topology[{}]: {}: has assigned idx", fmt::ptr(this), debug_format(node)));
on_internal_error(tlogger, format("topology[{}]: {}: has assigned idx", fmt::ptr(this), nptr));
}
// Note that _nodes contains also the this_node()
@@ -170,7 +180,7 @@ const node* topology::add_node(node_holder nptr) {
try {
if (is_configured_this_node(*node)) {
if (_this_node) {
on_internal_error(tlogger, format("topology[{}]: {}: local node already mapped to {}", fmt::ptr(this), debug_format(node), debug_format(this_node())));
on_internal_error(tlogger, format("topology[{}]: {}: local node already mapped to {}", fmt::ptr(this), node_printer(node), node_printer(this_node())));
}
locator::node& n = *_nodes.back();
n._is_this_node = node::this_node::yes;
@@ -180,7 +190,7 @@ const node* topology::add_node(node_holder nptr) {
}
if (tlogger.is_enabled(log_level::debug)) {
tlogger.debug("topology[{}]: add_node: {}, at {}", fmt::ptr(this), debug_format(node), current_backtrace());
tlogger.debug("topology[{}]: add_node: {}, at {}", fmt::ptr(this), nptr, current_backtrace());
}
index_node(node);
@@ -193,7 +203,7 @@ const node* topology::add_node(node_holder nptr) {
const node* topology::update_node(node* node, std::optional<host_id> opt_id, std::optional<inet_address> opt_ep, std::optional<endpoint_dc_rack> opt_dr, std::optional<node::state> opt_st, std::optional<shard_id> opt_shard_count) {
if (tlogger.is_enabled(log_level::debug)) {
tlogger.debug("topology[{}]: update_node: {}: to: host_id={} endpoint={} dc={} rack={} state={}, at {}", fmt::ptr(this), debug_format(node),
tlogger.debug("topology[{}]: update_node: {}: to: host_id={} endpoint={} dc={} rack={} state={}, at {}", fmt::ptr(this), node_printer(node),
opt_id ? format("{}", *opt_id) : "unchanged",
opt_ep ? format("{}", *opt_ep) : "unchanged",
opt_dr ? format("{}", opt_dr->dc) : "unchanged",
@@ -207,13 +217,13 @@ const node* topology::update_node(node* node, std::optional<host_id> opt_id, std
if (opt_id) {
if (*opt_id != node->host_id()) {
if (!*opt_id) {
on_internal_error(tlogger, format("Updating node host_id to null is disallowed: {}: new host_id={}", debug_format(node), *opt_id));
on_internal_error(tlogger, format("Updating node host_id to null is disallowed: {}: new host_id={}", node_printer(node), *opt_id));
}
if (node->is_this_node() && node->host_id()) {
on_internal_error(tlogger, format("This node host_id is already set: {}: new host_id={}", debug_format(node), *opt_id));
on_internal_error(tlogger, format("This node host_id is already set: {}: new host_id={}", node_printer(node), *opt_id));
}
if (_nodes_by_host_id.contains(*opt_id)) {
on_internal_error(tlogger, format("Cannot update node host_id: {}: new host_id already exists: {}", debug_format(node), debug_format(_nodes_by_host_id[*opt_id])));
on_internal_error(tlogger, format("Cannot update node host_id: {}: new host_id already exists: {}", node_printer(node), node_printer(_nodes_by_host_id[*opt_id])));
}
changed = true;
} else {
@@ -223,7 +233,7 @@ const node* topology::update_node(node* node, std::optional<host_id> opt_id, std
if (opt_ep) {
if (*opt_ep != node->endpoint()) {
if (*opt_ep == inet_address{}) {
on_internal_error(tlogger, format("Updating node endpoint to null is disallowed: {}: new endpoint={}", debug_format(node), *opt_ep));
on_internal_error(tlogger, format("Updating node endpoint to null is disallowed: {}: new endpoint={}", node_printer(node), *opt_ep));
}
changed = true;
} else {
@@ -282,7 +292,7 @@ const node* topology::update_node(node* node, std::optional<host_id> opt_id, std
bool topology::remove_node(host_id id) {
auto node = find_node(id);
tlogger.debug("topology[{}]: remove_node: host_id={}: {}", fmt::ptr(this), id, debug_format(node));
tlogger.debug("topology[{}]: remove_node: host_id={}: {}", fmt::ptr(this), id, node_printer(node));
if (node) {
remove_node(node);
return true;
@@ -296,11 +306,11 @@ void topology::remove_node(const node* node) {
void topology::index_node(const node* node) {
if (tlogger.is_enabled(log_level::trace)) {
tlogger.trace("topology[{}]: index_node: {}, at {}", fmt::ptr(this), debug_format(node), current_backtrace());
tlogger.trace("topology[{}]: index_node: {}, at {}", fmt::ptr(this), node_printer(node), current_backtrace());
}
if (node->idx() < 0) {
on_internal_error(tlogger, format("topology[{}]: {}: must already have a valid idx", fmt::ptr(this), debug_format(node)));
on_internal_error(tlogger, format("topology[{}]: {}: must already have a valid idx", fmt::ptr(this), node_printer(node)));
}
// FIXME: for now we allow adding nodes with null host_id, for the following cases:
@@ -310,7 +320,7 @@ void topology::index_node(const node* node) {
if (node->host_id()) {
auto [nit, inserted_host_id] = _nodes_by_host_id.emplace(node->host_id(), node);
if (!inserted_host_id) {
on_internal_error(tlogger, format("topology[{}]: {}: node already exists", fmt::ptr(this), debug_format(node)));
on_internal_error(tlogger, format("topology[{}]: {}: node already exists", fmt::ptr(this), node_printer(node)));
}
}
if (node->endpoint() != inet_address{}) {
@@ -327,7 +337,7 @@ void topology::index_node(const node* node) {
if (node->host_id()) {
_nodes_by_host_id.erase(node->host_id());
}
on_internal_error(tlogger, format("topology[{}]: {}: node endpoint already mapped to {}", fmt::ptr(this), debug_format(node), debug_format(eit->second)));
on_internal_error(tlogger, format("topology[{}]: {}: node endpoint already mapped to {}", fmt::ptr(this), node_printer(node), node_printer(eit->second)));
}
}
if (node->get_state() != node::state::left) {
@@ -351,7 +361,7 @@ void topology::index_node(const node* node) {
void topology::unindex_node(const node* node) {
if (tlogger.is_enabled(log_level::trace)) {
tlogger.trace("topology[{}]: unindex_node: {}, at {}", fmt::ptr(this), debug_format(node), current_backtrace());
tlogger.trace("topology[{}]: unindex_node: {}, at {}", fmt::ptr(this), node_printer(node), current_backtrace());
}
const auto& dc = node->dc_rack().dc;
@@ -397,7 +407,7 @@ void topology::unindex_node(const node* node) {
node_holder topology::pop_node(const node* node) {
if (tlogger.is_enabled(log_level::trace)) {
tlogger.trace("topology[{}]: pop_node: {}, at {}", fmt::ptr(this), debug_format(node), current_backtrace());
tlogger.trace("topology[{}]: pop_node: {}, at {}", fmt::ptr(this), node_printer(node), current_backtrace());
}
unindex_node(node);
@@ -473,7 +483,7 @@ const node* topology::add_or_update_endpoint(host_id id, std::optional<inet_addr
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));
tlogger.debug("topology[{}]: remove_endpoint: host_id={}: {}", fmt::ptr(this), host_id, node_printer(node));
if (node) {
remove_node(node);
return true;
@@ -483,13 +493,13 @@ bool topology::remove_endpoint(locator::host_id host_id)
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));
tlogger.trace("topology[{}]: has_node: host_id={}: {}", fmt::ptr(this), id, node_printer(node));
return bool(node);
}
bool topology::has_node(inet_address ep) const noexcept {
auto node = find_node(ep);
tlogger.trace("topology[{}]: has_node: endpoint={}: node={}", fmt::ptr(this), ep, debug_format(node));
tlogger.trace("topology[{}]: has_node: endpoint={}: node={}", fmt::ptr(this), ep, node_printer(node));
return bool(node);
}
@@ -564,7 +574,7 @@ std::ostream& operator<<(std::ostream& out, const locator::topology& t) {
<< ", rack: " << t._cfg.local_dc_rack.rack
<< ", nodes:\n";
for (auto&& node : t._nodes) {
out << " " << locator::topology::debug_format(&*node) << "\n";
out << " " << fmt::format("{}", node_printer(node.get())) << "\n";
}
return out << "}";
}