dht: Introduce get_uniform_tokens()

This commit is contained in:
Tomasz Grabiec
2026-01-29 02:19:23 +01:00
parent 4b984212ba
commit 2e1d41c206
3 changed files with 32 additions and 0 deletions

View File

@@ -257,4 +257,17 @@ token last_token_of_compaction_group(unsigned most_significant_bits, size_t grou
return bias(n);
}
utils::chunked_vector<dht::raw_token> get_uniform_tokens(size_t count) {
utils::chunked_vector<dht::raw_token> tokens;
tokens.reserve(count);
for (size_t i = 1; i <= count; ++i) {
uint64_t n = (uint128_t(i) * std::numeric_limits<uint64_t>::max()) / count;
tokens.push_back(raw_token{bias(n)});
assert(tokens.back().value != std::numeric_limits<int64_t>::min()); // See token::normalize()
}
return tokens;
}
} // namespace dht

View File

@@ -358,6 +358,10 @@ inline constexpr token bias(uint64_t n) {
size_t compaction_group_of(unsigned most_significant_bits, const token& t);
token last_token_of_compaction_group(unsigned most_significant_bits, size_t group);
// Generates 'count' tokens uniformly distributed in the token ring. Sorted.
// All values are in the range [first_token(), last_token()]
utils::chunked_vector<dht::raw_token> get_uniform_tokens(size_t count);
struct token_comparator {
// Return values are those of a trichotomic comparison.
constexpr std::strong_ordering operator()(const token& t1, const token& t2) const noexcept {

View File

@@ -4885,6 +4885,21 @@ SEASTAR_TEST_CASE(test_load_stats_migrate_tablet_size) {
return make_ready_future<>();
}
// We want to generate the same uniform boundaries if tablet count is a power-of-two as
// we did before implementing support for arbitrary token boundaries.
// So that when advertising a "power of two" layout, e.g in the snapshot descriptor,
// it means the same thing for all scylla versions.
SEASTAR_THREAD_TEST_CASE(test_get_uniform_tokens_is_compatible_with_dht_last_token_of_compaction_group) {
for (auto log2count : {0ul, 1ul, 2ul, 3ul, 10ul}) {
auto tokens = dht::get_uniform_tokens(1ul << log2count);
for (size_t i = 0; i < tokens.size(); i++) {
testlog.debug("i {}, token {}", i, tokens[i]);
BOOST_REQUIRE_EQUAL(tokens[i], dht::last_token_of_compaction_group(log2count, i));
thread::maybe_yield();
}
}
}
SEASTAR_TEST_CASE(test_tablet_id_and_range_side) {
static constexpr size_t tablet_count = 128;
locator::tablet_map tmap(tablet_count);