From b27cb2c7e81e0de5d3ce4b8e2ec4a603c470d2dc Mon Sep 17 00:00:00 2001 From: Damien Stevenson Date: Wed, 18 Apr 2018 14:36:06 +1000 Subject: [PATCH 1/5] Token patch. --- cassandra/metadata.py | 7 ++----- tests/unit/test_metadata.py | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/cassandra/metadata.py b/cassandra/metadata.py index b8f5f11f13..21d4eea4c7 100644 --- a/cassandra/metadata.py +++ b/cassandra/metadata.py @@ -13,7 +13,7 @@ # limitations under the License. from binascii import unhexlify -from bisect import bisect_right +from bisect import bisect_left from collections import defaultdict, Mapping from functools import total_ordering from hashlib import md5 @@ -1486,10 +1486,7 @@ def get_replicas(self, keyspace, token): tokens_to_hosts = self.tokens_to_hosts_by_ks.get(keyspace, None) if tokens_to_hosts: - # token range ownership is exclusive on the LHS (the start token), so - # we use bisect_right, which, in the case of a tie/exact match, - # picks an insertion point to the right of the existing match - point = bisect_right(self.ring, token) + point = bisect_left(self.ring, token) if point == len(self.ring): return tokens_to_hosts[self.ring[0]] else: diff --git a/tests/unit/test_metadata.py b/tests/unit/test_metadata.py index 3cc810e89a..96a512792c 100644 --- a/tests/unit/test_metadata.py +++ b/tests/unit/test_metadata.py @@ -312,8 +312,7 @@ def _get_replicas(self, token_klass): token_map = TokenMap(token_klass, token_to_primary_replica, tokens, metadata) # tokens match node tokens exactly - for i, token in enumerate(tokens): - expected_host = hosts[(i + 1) % len(hosts)] + for token, expected_host in zip(tokens, hosts): replicas = token_map.get_replicas("ks", token) self.assertEqual(set(replicas), {expected_host}) From 39d178a511e661df75a6950705db7ce41cb2d0e0 Mon Sep 17 00:00:00 2001 From: Damien Stevenson Date: Thu, 19 Apr 2018 06:31:24 +1000 Subject: [PATCH 2/5] Included a comment describing the token range. --- cassandra/metadata.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cassandra/metadata.py b/cassandra/metadata.py index 21d4eea4c7..1d3e297269 100644 --- a/cassandra/metadata.py +++ b/cassandra/metadata.py @@ -1485,6 +1485,8 @@ def get_replicas(self, keyspace, token): self.rebuild_keyspace(keyspace, build_if_absent=True) tokens_to_hosts = self.tokens_to_hosts_by_ks.get(keyspace, None) + # The values in self.ring correspond to the end of the + # token range up to and including the value listed. if tokens_to_hosts: point = bisect_left(self.ring, token) if point == len(self.ring): From 5cc2e4545c221562c8a2a8451cfdc45a0d31e374 Mon Sep 17 00:00:00 2001 From: Damien Stevenson Date: Thu, 19 Apr 2018 06:43:59 +1000 Subject: [PATCH 3/5] Minor change to comment. --- cassandra/metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cassandra/metadata.py b/cassandra/metadata.py index 1d3e297269..6fb6a95ece 100644 --- a/cassandra/metadata.py +++ b/cassandra/metadata.py @@ -1485,9 +1485,9 @@ def get_replicas(self, keyspace, token): self.rebuild_keyspace(keyspace, build_if_absent=True) tokens_to_hosts = self.tokens_to_hosts_by_ks.get(keyspace, None) - # The values in self.ring correspond to the end of the - # token range up to and including the value listed. if tokens_to_hosts: + # The values in self.ring correspond to the end of the + # token range up to and including the value listed. point = bisect_left(self.ring, token) if point == len(self.ring): return tokens_to_hosts[self.ring[0]] From b74936c5c40c582281274d82dbabb8e61a900744 Mon Sep 17 00:00:00 2001 From: Jaume Marhuenda Date: Mon, 23 Apr 2018 10:48:10 -0400 Subject: [PATCH 4/5] Added changelog for PYTHON-978 --- CHANGELOG.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4ab927a5b2..790aea99a1 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,12 @@ +3.15.0 +====== +Bug Fixes +--------- +* Tokenmap.get_replicas returns the wrong value if token coincides with the end of the range (PYTHON-978) + 3.14.0 ====== +April 17, 2018 Features -------- From e51fe3c27011e743acf7f737e56f6c828d075004 Mon Sep 17 00:00:00 2001 From: Damien Stevenson Date: Thu, 26 Apr 2018 11:51:44 +1000 Subject: [PATCH 5/5] Fix for integration metadata test. --- tests/integration/standard/test_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/standard/test_metadata.py b/tests/integration/standard/test_metadata.py index 5057fc2fff..1a58438c9f 100644 --- a/tests/integration/standard/test_metadata.py +++ b/tests/integration/standard/test_metadata.py @@ -1172,8 +1172,8 @@ def test_token_map(self): for i, token in enumerate(ring): self.assertEqual(set(get_replicas('test3rf', token)), set(owners)) - self.assertEqual(set(get_replicas('test2rf', token)), set([owners[(i + 1) % 3], owners[(i + 2) % 3]])) - self.assertEqual(set(get_replicas('test1rf', token)), set([owners[(i + 1) % 3]])) + self.assertEqual(set(get_replicas('test2rf', token)), set([owners[i], owners[(i + 1) % 3]])) + self.assertEqual(set(get_replicas('test1rf', token)), set([owners[i]])) cluster.shutdown()