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.

Reply via email to