Add replace_token functionality for vnodes. Patch by brandonwilliams reviewed by jasobrown for CASSANDRA-5337
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/ba6396a2 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/ba6396a2 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/ba6396a2 Branch: refs/heads/trunk Commit: ba6396a20c642108447c0c9820e2585ed6f6adb0 Parents: f79a2d3 Author: Brandon Williams <brandonwilli...@apache.org> Authored: Mon Jul 15 15:52:45 2013 -0500 Committer: Brandon Williams <brandonwilli...@apache.org> Committed: Mon Jul 15 15:52:45 2013 -0500 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/config/DatabaseDescriptor.java | 16 ++++++++++++ .../cassandra/service/StorageService.java | 27 ++++++++++++++++---- 3 files changed, 39 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/ba6396a2/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 5cec576..ee277aa 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 1.2.7 + * Add replace_node functionality for vnodes (CASSANDRA-5337) * Add timeout events to query traces (CASSANDRA-5520) * make starting native protocol server idempotent (CASSANDRA-5728) * Fix loading key cache when a saved entry is no longer valid (CASSANDRA-5706) http://git-wip-us.apache.org/repos/asf/cassandra/blob/ba6396a2/src/java/org/apache/cassandra/config/DatabaseDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 941249f..91ae675 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -715,6 +715,22 @@ public class DatabaseDescriptor return tokensFromString(System.getProperty("cassandra.replace_token", null)); } + public static UUID getReplaceNode() + { + try + { + return UUID.fromString(System.getProperty("cassandra.replace_node", null)); + } catch (NullPointerException e) + { + return null; + } + } + + public static boolean isReplacing() + { + return 0 != getReplaceTokens().size() || getReplaceNode() != null + } + public static String getClusterName() { return conf.cluster_name; http://git-wip-us.apache.org/repos/asf/cassandra/blob/ba6396a2/src/java/org/apache/cassandra/service/StorageService.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 34ecec8..e556306 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -574,7 +574,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE appStates.put(ApplicationState.NET_VERSION, valueFactory.networkVersion()); appStates.put(ApplicationState.HOST_ID, valueFactory.hostId(SystemTable.getLocalHostId())); appStates.put(ApplicationState.RPC_ADDRESS, valueFactory.rpcaddress(DatabaseDescriptor.getRpcAddress())); - if (0 != DatabaseDescriptor.getReplaceTokens().size()) + if (DatabaseDescriptor.isReplacing()) appStates.put(ApplicationState.STATUS, valueFactory.hibernate(true)); appStates.put(ApplicationState.RELEASE_VERSION, valueFactory.releaseVersion()); Gossiper.instance.register(this); @@ -655,7 +655,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE if (logger.isDebugEnabled()) logger.debug("... got ring + schema info"); - if (DatabaseDescriptor.getReplaceTokens().size() == 0) + if (DatabaseDescriptor.isReplacing()) { if (tokenMetadata.isMember(FBUtilities.getBroadcastAddress())) { @@ -667,6 +667,8 @@ public class StorageService extends NotificationBroadcasterSupport implements IE } else { + if (DatabaseDescriptor.getReplaceTokens().size() != 0 && DatabaseDescriptor.getReplaceNode() != null) + throw new UnsupportedOperationException("You cannot specify both replace_token and replace_node, choose one or the other"); try { // Sleeping additionally to make sure that the server actually is not alive @@ -678,8 +680,19 @@ public class StorageService extends NotificationBroadcasterSupport implements IE throw new AssertionError(e); } tokens = new ArrayList<Token>(); - for (String token : DatabaseDescriptor.getReplaceTokens()) - tokens.add(StorageService.getPartitioner().getTokenFactory().fromString(token)); + if (DatabaseDescriptor.getReplaceTokens().size() !=0) + { + for (String token : DatabaseDescriptor.getReplaceTokens()) + tokens.add(StorageService.getPartitioner().getTokenFactory().fromString(token)); + } + else + { + assert DatabaseDescriptor.getReplaceNode() != null; + InetAddress endpoint = tokenMetadata.getEndpointForHostId(DatabaseDescriptor.getReplaceNode()); + if (endpoint == null) + throw new UnsupportedOperationException("Cannot replace host id " + DatabaseDescriptor.getReplaceNode() + " because it does not exist!"); + tokens = tokenMetadata.getTokens(endpoint); + } // check for operator errors... for (Token token : tokens) @@ -691,6 +704,10 @@ public class StorageService extends NotificationBroadcasterSupport implements IE throw new UnsupportedOperationException("Cannnot replace a token for a Live node... "); current.add(existing); } + else + { + throw new UnsupportedOperationException("Cannot replace token " + token + " which does not exist!"); + } } setMode(Mode.JOINING, "Replacing a node with token: " + tokens, true); @@ -903,7 +920,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE { isBootstrapMode = true; SystemTable.updateTokens(tokens); // DON'T use setToken, that makes us part of the ring locally which is incorrect until we are done bootstrapping - if (0 == DatabaseDescriptor.getReplaceTokens().size()) + if (DatabaseDescriptor.isReplacing()) { // if not an existing token then bootstrap // order is important here, the gossiper can fire in between adding these two states. It's ok to send TOKENS without STATUS, but *not* vice versa.