From 6882e6ca508d0655172f7dcd3ef728a42cbe49d5 Mon Sep 17 00:00:00 2001 From: Tomasz Grabiec Date: Wed, 22 Jul 2015 10:12:58 +0200 Subject: [PATCH] storage_proxy: Fix range splitting when split point is exlcluded by lower bound If we had a range (x; ...] then x is excluded, but token iterator was initialized with x. The splitting loop would exit prematurely because it would detect that the token is outside the range. The fix is to teach ring_range() to recognize this and always give tokens which are not smaller than the range's lower bound. --- locator/token_metadata.cc | 21 +++++++++++++++++++++ locator/token_metadata.hh | 4 ++++ service/storage_proxy.cc | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/locator/token_metadata.cc b/locator/token_metadata.cc index d78b78cf61..6ed022d60c 100644 --- a/locator/token_metadata.cc +++ b/locator/token_metadata.cc @@ -198,6 +198,27 @@ void token_metadata::add_bootstrap_token(token t, inet_address endpoint) { add_bootstrap_tokens(tokens, endpoint); } +boost::iterator_range +token_metadata::ring_range( + const std::experimental::optional& start, + bool include_min) +{ + auto r = ring_range(start ? start->value().token() : dht::minimum_token(), include_min); + + if (!r.empty()) { + // We should skip the first token if it's excluded by the range. + if (start + && !start->is_inclusive() + && !start->value().has_key() + && start->value().token() == *r.begin()) + { + r.pop_front(); + } + } + + return r; +} + void token_metadata::add_bootstrap_tokens(std::unordered_set tokens, inet_address endpoint) { for (auto t : tokens) { auto old_endpoint = _bootstrap_tokens.find(t); diff --git a/locator/token_metadata.hh b/locator/token_metadata.hh index 2a6269e5e6..714847f342 100644 --- a/locator/token_metadata.hh +++ b/locator/token_metadata.hh @@ -29,6 +29,7 @@ #include "utils/UUID.hh" #include #include +#include "query-request.hh" // forward declaration since database.hh includes this file class keyspace; @@ -228,6 +229,9 @@ public: return boost::make_iterator_range(begin, end); } + boost::iterator_range ring_range( + const std::experimental::optional& start, bool include_min = false); + topology& get_topology() { return _topology; } diff --git a/service/storage_proxy.cc b/service/storage_proxy.cc index 33b275e99d..81f234b9f0 100644 --- a/service/storage_proxy.cc +++ b/service/storage_proxy.cc @@ -2457,7 +2457,7 @@ storage_proxy::get_restricted_ranges(keyspace& ks, const schema& s, query::parti std::vector ranges; // divide the queryRange into pieces delimited by the ring and minimum tokens - auto ring_iter = tm.ring_range(start_token(range), true); + auto ring_iter = tm.ring_range(range.start(), true); query::partition_range remainder = std::move(range); for (const dht::token& upper_bound_token : ring_iter) {