locator/tablets: Introduce tablet_map::for_each_sibling_tablets()

Adding interface to iterate through sibling tablets for a given table,
one pair at a time.

Initially I thought of having for_each_sibling_tablet do nothing for single
tablet tables. But later I bumped into complications when wiring it into
load balancer for building candidate list, since single-tablet tables
have to be special cased.

Signed-off-by: Raphael S. Carvalho <raphaelsc@scylladb.com>
This commit is contained in:
Raphael S. Carvalho
2024-09-10 20:46:23 -03:00
parent 47c8237de0
commit 3082ff992c
2 changed files with 28 additions and 0 deletions

View File

@@ -406,6 +406,24 @@ future<> tablet_map::for_each_tablet(seastar::noncopyable_function<future<>(tabl
}
}
future<> tablet_map::for_each_sibling_tablets(seastar::noncopyable_function<future<>(tablet_desc, std::optional<tablet_desc>)> func) const {
auto make_desc = [this] (tablet_id tid) {
return tablet_desc{tid, &get_tablet_info(tid), get_tablet_transition_info(tid)};
};
if (_tablets.size() == 1) {
co_return co_await func(make_desc(first_tablet()), std::nullopt);
}
for (std::optional<tablet_id> tid = first_tablet(); tid; tid = next_tablet(*tid)) {
auto tid1 = tid;
auto tid2 = tid = next_tablet(*tid);
if (!tid2) {
// Cannot happen with power-of-two invariant.
throw std::logic_error(format("Cannot retrieve sibling tablet with tablet count {}", tablet_count()));
}
co_await func(make_desc(*tid1), make_desc(*tid2));
}
}
void tablet_map::clear_transitions() {
_transitions.clear();
}

View File

@@ -348,6 +348,12 @@ struct repair_scheduler_config {
using load_stats_ptr = lw_shared_ptr<const load_stats>;
struct tablet_desc {
tablet_id tid;
const tablet_info* info; // cannot be null.
const tablet_transition_info* transition; // null if there's no transition.
};
/// Stores information about tablets of a single table.
///
/// The map contains a constant number of tablets, tablet_count().
@@ -453,6 +459,10 @@ public:
/// Calls a given function for each tablet in the map in token ownership order.
future<> for_each_tablet(seastar::noncopyable_function<future<>(tablet_id, const tablet_info&)> func) const;
/// Calls a given function for each sibling tablet in the map in token ownership order.
/// If tablet count == 1, then there will be only one call and 2nd tablet_desc is disengaged.
future<> for_each_sibling_tablets(seastar::noncopyable_function<future<>(tablet_desc, std::optional<tablet_desc>)> func) const;
const auto& transitions() const {
return _transitions;
}