Author: gdusbabek Date: Wed Jul 14 12:10:50 2010 New Revision: 964020 URL: http://svn.apache.org/viewvc?rev=964020&view=rev Log: fail bootstrap if all nodes are bootstrapping. patch by gdusbabek, reviewed by jbellis. CASSANDRA-1011
Modified: cassandra/trunk/src/java/org/apache/cassandra/dht/BootStrapper.java cassandra/trunk/test/unit/org/apache/cassandra/dht/BootStrapperTest.java Modified: cassandra/trunk/src/java/org/apache/cassandra/dht/BootStrapper.java URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/dht/BootStrapper.java?rev=964020&r1=964019&r2=964020&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/dht/BootStrapper.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/dht/BootStrapper.java Wed Jul 14 12:10:50 2010 @@ -138,6 +138,9 @@ public class BootStrapper InetAddress maxEndpoint = endpoints.get(endpoints.size() - 1); assert !maxEndpoint.equals(FBUtilities.getLocalAddress()); + if (metadata.pendingRangeChanges(maxEndpoint) > 0) + throw new RuntimeException("Every node is a bootstrap source! Please specify an initial token manually or wait for an existing bootstrap operation to finish."); + return maxEndpoint; } Modified: cassandra/trunk/test/unit/org/apache/cassandra/dht/BootStrapperTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/dht/BootStrapperTest.java?rev=964020&r1=964019&r2=964020&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/dht/BootStrapperTest.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/dht/BootStrapperTest.java Wed Jul 14 12:10:50 2010 @@ -48,6 +48,63 @@ public class BootStrapperTest extends Cl // fetch a bootstrap token from the local node assert BootStrapper.getBootstrapTokenFrom(FBUtilities.getLocalAddress()) != null; } + + @Test + public void testMulitipleAutomaticBootstraps() throws IOException + { + StorageService ss = StorageService.instance; + generateFakeEndpoints(5); + InetAddress[] addrs = new InetAddress[] + { + InetAddress.getByName("127.0.0.2"), + InetAddress.getByName("127.0.0.3"), + InetAddress.getByName("127.0.0.4"), + InetAddress.getByName("127.0.0.5"), + }; + InetAddress[] bootstrapAddrs = new InetAddress[] + { + InetAddress.getByName("127.0.0.12"), + InetAddress.getByName("127.0.0.13"), + InetAddress.getByName("127.0.0.14"), + InetAddress.getByName("127.0.0.15"), + }; + Map<InetAddress, Double> load = new HashMap<InetAddress, Double>(); + for (int i = 0; i < addrs.length; i++) + load.put(addrs[i], (double)i+2); + + // give every node a bootstrap source. + for (int i = 3; i >=0; i--) + { + InetAddress bootstrapSource = BootStrapper.getBootstrapSource(ss.getTokenMetadata(), load); + assert bootstrapSource != null; + assert bootstrapSource.equals(addrs[i]) : String.format("expected %s but got %s for %d", addrs[i], bootstrapSource, i); + assert !ss.getTokenMetadata().getBootstrapTokens().containsValue(bootstrapSource); + + Range range = ss.getPrimaryRangeForEndpoint(bootstrapSource); + Token token = StorageService.getPartitioner().midpoint(range.left, range.right); + assert range.contains(token); + ss.onChange(bootstrapAddrs[i], StorageService.MOVE_STATE, new ApplicationState(StorageService.STATE_BOOTSTRAPPING + StorageService.Delimiter + StorageService.getPartitioner().getTokenFactory().toString(token))); + } + + // any further attempt to bootsrtap should fail since every node in the cluster is splitting. + try + { + BootStrapper.getBootstrapSource(ss.getTokenMetadata(), load); + throw new AssertionError("This bootstrap should have failed."); + } + catch (RuntimeException ex) + { + // success! + } + + // indicate that one of the nodes is done. see if the node it was bootstrapping from is still available. + Range range = ss.getPrimaryRangeForEndpoint(addrs[2]); + Token token = StorageService.getPartitioner().midpoint(range.left, range.right); + ss.onChange(bootstrapAddrs[2], StorageService.MOVE_STATE, new ApplicationState(StorageService.STATE_NORMAL + StorageService.Delimiter + StorageService.getPartitioner().getTokenFactory().toString(token))); + load.put(bootstrapAddrs[2], 0d); + InetAddress addr = BootStrapper.getBootstrapSource(ss.getTokenMetadata(), load); + assert addr != null && addr.equals(addrs[2]); + } @Test public void testGuessToken() throws IOException