You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ma...@apache.org on 2022/11/18 07:06:13 UTC

[cassandra] branch trunk updated: Add flag to exclude nodes from local DC when running nodetool rebuild

This is an automated email from the ASF dual-hosted git repository.

marcuse pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 145dbd1f08 Add flag to exclude nodes from local DC when running nodetool rebuild
145dbd1f08 is described below

commit 145dbd1f0875ae4c54392125e09ed05153c0dd8f
Author: Saranya Krishnakumar <sa...@apple.com>
AuthorDate: Wed Oct 19 16:58:41 2022 -0700

    Add flag to exclude nodes from local DC when running nodetool rebuild
    
    Patch by Saranya Krishnakumar; reviewed by Dinesh Joshi, Marcus Eriksson, Yifan Cai for CASSANDRA-17870
---
 CHANGES.txt                                        |  1 +
 .../org/apache/cassandra/dht/RangeStreamer.java    | 27 ++++++++++++++++++++++
 .../apache/cassandra/service/StorageService.java   | 16 ++++++++++++-
 .../cassandra/service/StorageServiceMBean.java     | 14 +++++++++++
 src/java/org/apache/cassandra/tools/NodeProbe.java |  4 ++--
 .../apache/cassandra/tools/nodetool/Rebuild.java   |  9 ++++++--
 .../cassandra/service/StorageServiceTest.java      | 15 ++++++++++++
 7 files changed, 81 insertions(+), 5 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index eed3363cd4..fd4903ef48 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.2
+ * Add flag to exclude nodes from local DC when running nodetool rebuild (CASSANDRA-17870)
  * Adding endpoint verification option to client_encryption_options (CASSANDRA-18034)
  * Replace 'wcwidth.py' with pypi module (CASSANDRA-17287)
  * Add nodetool forcecompact to remove tombstoned or ttl'd data ignoring GC grace for given table and partition keys (CASSANDRA-17711)
diff --git a/src/java/org/apache/cassandra/dht/RangeStreamer.java b/src/java/org/apache/cassandra/dht/RangeStreamer.java
index 08d834459a..9b7833b90a 100644
--- a/src/java/org/apache/cassandra/dht/RangeStreamer.java
+++ b/src/java/org/apache/cassandra/dht/RangeStreamer.java
@@ -203,6 +203,33 @@ public class RangeStreamer
         }
     }
 
+    /**
+    * Source filter which excludes nodes from local DC.
+    */
+    public static class ExcludeLocalDatacenterFilter implements SourceFilter
+    {
+        private final IEndpointSnitch snitch;
+        private final String localDc;
+
+        public ExcludeLocalDatacenterFilter(IEndpointSnitch snitch)
+        {
+            this.snitch = snitch;
+            this.localDc = snitch.getLocalDatacenter();
+        }
+
+        @Override
+        public boolean apply(Replica replica)
+        {
+            return !snitch.getDatacenter(replica).equals(localDc);
+        }
+
+        @Override
+        public String message(Replica replica)
+        {
+            return "Filtered " + replica + " out because it belongs to the local datacenter";
+        }
+    }
+
     /**
      * Source filter which excludes the current node from source calculations
      */
diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java
index da130c60a0..7dab8745f3 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -1280,10 +1280,15 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
 
     public void rebuild(String sourceDc)
     {
-        rebuild(sourceDc, null, null, null);
+        rebuild(sourceDc, null, null, null, false);
     }
 
     public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources)
+    {
+        rebuild(sourceDc, keyspace, tokens, specificSources, false);
+    }
+
+    public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources, boolean excludeLocalDatacenterNodes)
     {
         // check ongoing rebuild
         if (!isRebuilding.compareAndSet(false, true))
@@ -1291,6 +1296,12 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
             throw new IllegalStateException("Node is still rebuilding. Check nodetool netstats.");
         }
 
+        // fail if source DC is local and --exclude-local-dc is set
+        if (sourceDc != null && sourceDc.equals(DatabaseDescriptor.getLocalDataCenter()) && excludeLocalDatacenterNodes)
+        {
+            throw new IllegalArgumentException("Cannot set source data center to be local data center, when excludeLocalDataCenter flag is set");
+        }
+
         try
         {
             // check the arguments
@@ -1317,6 +1328,9 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
             if (sourceDc != null)
                 streamer.addSourceFilter(new RangeStreamer.SingleDatacenterFilter(DatabaseDescriptor.getEndpointSnitch(), sourceDc));
 
+            if (excludeLocalDatacenterNodes)
+                streamer.addSourceFilter(new RangeStreamer.ExcludeLocalDatacenterFilter(DatabaseDescriptor.getEndpointSnitch()));
+
             if (keyspace == null)
             {
                 for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces().names())
diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
index c92ea72bd6..43208b1308 100644
--- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
@@ -782,9 +782,23 @@ public interface StorageServiceMBean extends NotificationEmitter
      * @param keyspace Name of the keyspace which to rebuild or null to rebuild all keyspaces.
      * @param tokens Range of tokens to rebuild or null to rebuild all token ranges. In the format of:
      *               "(start_token_1,end_token_1],(start_token_2,end_token_2],...(start_token_n,end_token_n]"
+     * @param specificSources list of sources that can be used for rebuilding. Must be other nodes in the cluster.
+     *                        The format of the string is comma separated values.
      */
     public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources);
 
+    /**
+    * Same as {@link #rebuild(String)}, but only for specified keyspace and ranges. It excludes local data center nodes
+    *
+    * @param sourceDc Name of DC from which to select sources for streaming or null to pick any node
+    * @param keyspace Name of the keyspace which to rebuild or null to rebuild all keyspaces.
+    * @param tokens Range of tokens to rebuild or null to rebuild all token ranges. In the format of:
+    *               "(start_token_1,end_token_1],(start_token_2,end_token_2],...(start_token_n,end_token_n]"
+    * @param specificSources list of sources that can be used for rebuilding. Mostly other nodes in the cluster.
+    * @param excludeLocalDatacenterNodes Flag to indicate whether local data center nodes should be excluded as sources for streaming.
+    */
+    public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources, boolean excludeLocalDatacenterNodes);
+
     /** Starts a bulk load and blocks until it completes. */
     public void bulkLoad(String directory);
 
diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java b/src/java/org/apache/cassandra/tools/NodeProbe.java
index e296d39723..22ec00b5df 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -1589,9 +1589,9 @@ public class NodeProbe implements AutoCloseable
         return withPort ? ssProxy.describeRingWithPortJMX(keyspaceName) : ssProxy.describeRingJMX(keyspaceName);
     }
 
-    public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources)
+    public void rebuild(String sourceDc, String keyspace, String tokens, String specificSources, boolean excludeLocalDatacenterNodes)
     {
-        ssProxy.rebuild(sourceDc, keyspace, tokens, specificSources);
+        ssProxy.rebuild(sourceDc, keyspace, tokens, specificSources, excludeLocalDatacenterNodes);
     }
 
     public List<String> sampleKeyRange()
diff --git a/src/java/org/apache/cassandra/tools/nodetool/Rebuild.java b/src/java/org/apache/cassandra/tools/nodetool/Rebuild.java
index a16e8f22f1..ed4e97c0f7 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/Rebuild.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/Rebuild.java
@@ -28,7 +28,7 @@ import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
 public class Rebuild extends NodeToolCmd
 {
     @Arguments(usage = "<src-dc-name>",
-               description = "Name of DC from which to select sources for streaming. By default, pick any DC")
+               description = "Name of DC from which to select sources for streaming. By default, pick any DC (except local DC when --exclude-local-dc is set)")
     private String sourceDataCenterName = null;
 
     @Option(title = "specific_keyspace",
@@ -46,6 +46,11 @@ public class Rebuild extends NodeToolCmd
             description = "Use -s to specify hosts that this node should stream from when -ts is used. Multiple hosts should be separated using commas (e.g. 127.0.0.1,127.0.0.2,...)")
     private String specificSources = null;
 
+    @Option(title = "exclude_local_dc",
+            name = {"--exclude-local-dc"},
+            description = "Use --exclude-local-dc to exclude nodes in local data center as source for streaming.")
+    private boolean excludeLocalDatacenterNodes = false;
+
     @Override
     public void execute(NodeProbe probe)
     {
@@ -55,6 +60,6 @@ public class Rebuild extends NodeToolCmd
             throw new IllegalArgumentException("Cannot specify tokens without keyspace.");
         }
 
-        probe.rebuild(sourceDataCenterName, keyspace, tokens, specificSources);
+        probe.rebuild(sourceDataCenterName, keyspace, tokens, specificSources, excludeLocalDatacenterNodes);
     }
 }
diff --git a/test/unit/org/apache/cassandra/service/StorageServiceTest.java b/test/unit/org/apache/cassandra/service/StorageServiceTest.java
index cfc8908722..b379793214 100644
--- a/test/unit/org/apache/cassandra/service/StorageServiceTest.java
+++ b/test/unit/org/apache/cassandra/service/StorageServiceTest.java
@@ -306,4 +306,19 @@ public class StorageServiceTest
             storageService.setBatchSizeWarnThresholdInKiB(previousBatchSizeWarnThreshold);
         }
     }
+
+    @Test
+    public void testLocalDatacenterNodesExcludedDuringRebuild()
+    {
+        StorageService service = StorageService.instance;
+        try
+        {
+            service.rebuild(DatabaseDescriptor.getLocalDataCenter(), "StorageServiceTest", null, null, true);
+            fail();
+        }
+        catch (IllegalArgumentException e)
+        {
+            Assert.assertEquals("Cannot set source data center to be local data center, when excludeLocalDataCenter flag is set", e.getMessage());
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org