Repository: cassandra Updated Branches: refs/heads/cassandra-2.0 cd2c43884 -> d21c0c932 refs/heads/cassandra-2.1 47a787a91 -> 85f67aa9c refs/heads/trunk 8aea1617e -> d697ba6f5
Compare scores of full replica ordering in DES. Patch by Tyler Hobbs, reviewed by brandonwilliams for CASSANDRA-6883 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d21c0c93 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d21c0c93 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d21c0c93 Branch: refs/heads/cassandra-2.0 Commit: d21c0c932c7d962feb958159578cf2cfb471a648 Parents: cd2c438 Author: Brandon Williams <[email protected]> Authored: Tue Feb 25 10:40:58 2014 -0600 Committer: Brandon Williams <[email protected]> Committed: Tue Feb 25 10:42:02 2014 -0600 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../locator/DynamicEndpointSnitch.java | 25 +++-- .../locator/DynamicEndpointSnitchTest.java | 108 ++++++++----------- 3 files changed, 61 insertions(+), 73 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/d21c0c93/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index f3a854c..ee138ce 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.0.6 + * Compare scores of full replica ordering in DES (CASSANDRA-6883) * fix CME in SessionInfo updateProgress affecting netstats (CASSANDRA-6577) * Allow repairing between specific replicas (CASSANDRA-6440) * Allow per-dc enabling of hints (CASSANDRA-6157) http://git-wip-us.apache.org/repos/asf/cassandra/blob/d21c0c93/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java index e9d55d4..00c3618 100644 --- a/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java +++ b/src/java/org/apache/cassandra/locator/DynamicEndpointSnitch.java @@ -156,16 +156,27 @@ public class DynamicEndpointSnitch extends AbstractEndpointSnitch implements ILa { if (addresses.size() < 2) return; + subsnitch.sortByProximity(address, addresses); - Double first = scores.get(addresses.get(0)); - if (first == null) - return; - for (InetAddress addr : addresses) + ArrayList<Double> subsnitchOrderedScores = new ArrayList<>(addresses.size()); + for (InetAddress inet : addresses) { - Double next = scores.get(addr); - if (next == null) + Double score = scores.get(inet); + if (score == null) return; - if ((first - next) / first > BADNESS_THRESHOLD) + subsnitchOrderedScores.add(score); + } + + // Sort the scores and then compare them (positionally) to the scores in the subsnitch order. + // If any of the subsnitch-ordered scores exceed the optimal/sorted score by BADNESS_THRESHOLD, use + // the score-sorted ordering instead of the subsnitch ordering. + ArrayList<Double> sortedScores = new ArrayList<>(subsnitchOrderedScores); + Collections.sort(sortedScores); + + Iterator<Double> sortedScoreIterator = sortedScores.iterator(); + for (Double subsnitchScore : subsnitchOrderedScores) + { + if (subsnitchScore > (sortedScoreIterator.next() * (1.0 + BADNESS_THRESHOLD))) { sortByProximityWithScore(address, addresses); return; http://git-wip-us.apache.org/repos/asf/cassandra/blob/d21c0c93/test/unit/org/apache/cassandra/locator/DynamicEndpointSnitchTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/locator/DynamicEndpointSnitchTest.java b/test/unit/org/apache/cassandra/locator/DynamicEndpointSnitchTest.java index dca87a2..e23bcfa 100644 --- a/test/unit/org/apache/cassandra/locator/DynamicEndpointSnitchTest.java +++ b/test/unit/org/apache/cassandra/locator/DynamicEndpointSnitchTest.java @@ -21,7 +21,8 @@ package org.apache.cassandra.locator; import java.io.IOException; import java.net.InetAddress; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.service.StorageService; @@ -29,89 +30,64 @@ import org.junit.Test; import org.apache.cassandra.utils.FBUtilities; +import static org.junit.Assert.assertEquals; + public class DynamicEndpointSnitchTest { + + private static void setScores(DynamicEndpointSnitch dsnitch, int rounds, List<InetAddress> hosts, Integer... scores) throws InterruptedException + { + for (int round = 0; round < rounds; round++) + { + for (int i = 0; i < hosts.size(); i++) + dsnitch.receiveTiming(hosts.get(i), scores[i]); + } + Thread.sleep(150); + } + @Test public void testSnitch() throws InterruptedException, IOException, ConfigurationException { // do this because SS needs to be initialized before DES can work properly. StorageService.instance.initClient(0); - int sleeptime = 150; SimpleSnitch ss = new SimpleSnitch(); DynamicEndpointSnitch dsnitch = new DynamicEndpointSnitch(ss, String.valueOf(ss.hashCode())); InetAddress self = FBUtilities.getBroadcastAddress(); - ArrayList<InetAddress> order = new ArrayList<InetAddress>(); - InetAddress host1 = InetAddress.getByName("127.0.0.4"); - InetAddress host2 = InetAddress.getByName("127.0.0.2"); - InetAddress host3 = InetAddress.getByName("127.0.0.3"); + InetAddress host1 = InetAddress.getByName("127.0.0.2"); + InetAddress host2 = InetAddress.getByName("127.0.0.3"); + InetAddress host3 = InetAddress.getByName("127.0.0.4"); + List<InetAddress> hosts = Arrays.asList(host1, host2, host3); // first, make all hosts equal - for (int i = 0; i < 5; i++) - { - dsnitch.receiveTiming(host1, 1L); - dsnitch.receiveTiming(host2, 1L); - dsnitch.receiveTiming(host3, 1L); - } - - Thread.sleep(sleeptime); - - order.add(host1); - order.add(host2); - order.add(host3); - assert dsnitch.getSortedListByProximity(self, order).equals(order); + setScores(dsnitch, 1, hosts, 10, 10, 10); + List<InetAddress> order = Arrays.asList(host1, host2, host3); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); // make host1 a little worse - dsnitch.receiveTiming(host1, 2L); - dsnitch.receiveTiming(host2, 1L); - dsnitch.receiveTiming(host3, 1L); - Thread.sleep(sleeptime); - - order.clear(); - order.add(host2); - order.add(host3); - order.add(host1); - assert dsnitch.getSortedListByProximity(self, order).equals(order); + setScores(dsnitch, 1, hosts, 20, 10, 10); + order = Arrays.asList(host2, host3, host1); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); // make host2 as bad as host1 - dsnitch.receiveTiming(host2, 2L); - dsnitch.receiveTiming(host1, 1L); - dsnitch.receiveTiming(host3, 1L); - Thread.sleep(sleeptime); - - order.clear(); - order.add(host3); - order.add(host1); - order.add(host2); - assert dsnitch.getSortedListByProximity(self, order).equals(order); + setScores(dsnitch, 2, hosts, 15, 20, 10); + order = Arrays.asList(host3, host1, host2); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); // make host3 the worst - for (int i = 0; i < 2; i++) - { - dsnitch.receiveTiming(host1, 1L); - dsnitch.receiveTiming(host2, 1L); - dsnitch.receiveTiming(host3, 2L); - } - Thread.sleep(sleeptime); - - order.clear(); - order.add(host1); - order.add(host2); - order.add(host3); - assert dsnitch.getSortedListByProximity(self, order).equals(order); + setScores(dsnitch, 3, hosts, 10, 10, 30); + order = Arrays.asList(host1, host2, host3); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); // make host3 equal to the others - for (int i = 0; i < 2; i++) - { - dsnitch.receiveTiming(host1, 1L); - dsnitch.receiveTiming(host2, 1L); - dsnitch.receiveTiming(host3, 1L); - } - Thread.sleep(sleeptime); - - order.clear(); - order.add(host1); - order.add(host2); - order.add(host3); - assert dsnitch.getSortedListByProximity(self, order).equals(order); + setScores(dsnitch, 5, hosts, 10, 10, 10); + order = Arrays.asList(host1, host2, host3); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); + + /// Tests CASSANDRA-6683 improvements + // make the scores differ enough from the ideal order that we sort by score; under the old + // dynamic snitch behavior (where we only compared neighbors), these wouldn't get sorted + setScores(dsnitch, 20, hosts, 10, 70, 20); + order = Arrays.asList(host1, host3, host2); + assertEquals(order, dsnitch.getSortedListByProximity(self, Arrays.asList(host1, host2, host3))); } -} +} \ No newline at end of file
