mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
effective_replication_map, abstract_replication_strategy: get_ranges: call on_internal_error in empty sorted_tokens case
Accessing tm.sorted_tokens().back() causes undefined behavior if tm.sorted_tokens is empty. Check that first and throw/abort using on_internal_error in this case. This will prevent the segfault but it doesn't fix the root cause which is getting here with empty token_metadata. That will be fixed by the following patch. Refs #9494 Signed-off-by: Benny Halevy <bhalevy@scylladb.com> Message-Id: <20211019075710.1626808-1-bhalevy@scylladb.com>
This commit is contained in:
@@ -156,8 +156,12 @@ dht::token_range_vector
|
||||
effective_replication_map::do_get_ranges(noncopyable_function<bool(inet_address_vector_replica_set)> should_add_range) const {
|
||||
dht::token_range_vector ret;
|
||||
const auto& tm = *_tmptr;
|
||||
auto prev_tok = tm.sorted_tokens().back();
|
||||
for (const auto& tok : tm.sorted_tokens()) {
|
||||
const auto& sorted_tokens = tm.sorted_tokens();
|
||||
if (sorted_tokens.empty()) {
|
||||
on_internal_error(rslogger, "Token metadata is empty");
|
||||
}
|
||||
auto prev_tok = sorted_tokens.back();
|
||||
for (const auto& tok : sorted_tokens) {
|
||||
if (should_add_range(get_natural_endpoints(tok))) {
|
||||
insert_token_range_to_sorted_container_while_unwrapping(prev_tok, tok, ret);
|
||||
}
|
||||
@@ -183,8 +187,12 @@ future<dht::token_range_vector>
|
||||
abstract_replication_strategy::get_ranges(inet_address ep, token_metadata_ptr tmptr) const {
|
||||
dht::token_range_vector ret;
|
||||
const auto& tm = *tmptr;
|
||||
auto prev_tok = tm.sorted_tokens().back();
|
||||
for (auto tok : tm.sorted_tokens()) {
|
||||
const auto& sorted_tokens = tm.sorted_tokens();
|
||||
if (sorted_tokens.empty()) {
|
||||
on_internal_error(rslogger, "Token metadata is empty");
|
||||
}
|
||||
auto prev_tok = sorted_tokens.back();
|
||||
for (auto tok : sorted_tokens) {
|
||||
for (inet_address a : co_await calculate_natural_endpoints(tok, tm)) {
|
||||
if (a == ep) {
|
||||
insert_token_range_to_sorted_container_while_unwrapping(prev_tok, tok, ret);
|
||||
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
replication_strategy_type get_type() const { return _my_type; }
|
||||
|
||||
// Use the token_metadata provided by the caller instead of _token_metadata
|
||||
// Note: must be called with initialized, non-empty token_metadata.
|
||||
future<dht::token_range_vector> get_ranges(inet_address ep, token_metadata_ptr tmptr) const;
|
||||
|
||||
public:
|
||||
@@ -175,6 +176,8 @@ public:
|
||||
// The list is sorted, and its elements are non overlapping and non wrap-around.
|
||||
// It the analogue of Origin's getAddressRanges().get(endpoint).
|
||||
// This function is not efficient, and not meant for the fast path.
|
||||
//
|
||||
// Note: must be called after token_metadata has been initialized.
|
||||
dht::token_range_vector get_ranges(inet_address ep) const;
|
||||
|
||||
// get_primary_ranges() returns the list of "primary ranges" for the given
|
||||
@@ -183,11 +186,15 @@ public:
|
||||
// returned calculate_natural_endpoints().
|
||||
// This function is the analogue of Origin's
|
||||
// StorageService.getPrimaryRangesForEndpoint().
|
||||
//
|
||||
// Note: must be called after token_metadata has been initialized.
|
||||
dht::token_range_vector get_primary_ranges(inet_address ep) const;
|
||||
|
||||
// get_primary_ranges_within_dc() is similar to get_primary_ranges()
|
||||
// except it assigns a primary node for each range within each dc,
|
||||
// instead of one node globally.
|
||||
//
|
||||
// Note: must be called after token_metadata has been initialized.
|
||||
dht::token_range_vector get_primary_ranges_within_dc(inet_address ep) const;
|
||||
|
||||
std::unordered_map<dht::token_range, inet_address_vector_replica_set>
|
||||
|
||||
Reference in New Issue
Block a user