Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 23d722ee3 -> e2ee20458


Do not enable native transport if bootstrap is pending

patch by Jaydeepkumar Chovatia; reviewed by Kurt Greaves for CASSANDRA-14525


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/a6196a3a
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a6196a3a
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a6196a3a

Branch: refs/heads/cassandra-3.0
Commit: a6196a3a79b67dc6577747e591456328e57c314f
Parents: 505a03c
Author: jaydeepkumar1984 <chovatia.jayd...@gmail.com>
Authored: Thu Jun 14 21:52:20 2018 -0700
Committer: Jay Zhuang <jay.zhu...@yahoo.com>
Committed: Sun Dec 30 21:35:08 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cassandra/service/CassandraDaemon.java      | 24 +++++
 .../cassandra/service/StorageService.java       | 94 +++++++++++++++++---
 .../cassandra/service/StorageServiceMBean.java  |  7 ++
 .../org/apache/cassandra/tools/NodeProbe.java   |  5 ++
 .../apache/cassandra/tools/nodetool/Join.java   |  1 +
 6 files changed, 119 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 58309fa..16695c8 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,7 @@
 
 
 2.2.13
+ * Don't enable client transports when bootstrap is pending (CASSANDRA-14525)
  * Fix bug that prevented compaction of SSTables after full repairs 
(CASSANDRA-14423)
  * Incorrect counting of pending messages in OutboundTcpConnection 
(CASSANDRA-11551)
  * Fix compaction failure caused by reading un-flushed data (CASSANDRA-12743)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/src/java/org/apache/cassandra/service/CassandraDaemon.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java 
b/src/java/org/apache/cassandra/service/CassandraDaemon.java
index 18b568d..e250050 100644
--- a/src/java/org/apache/cassandra/service/CassandraDaemon.java
+++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java
@@ -440,6 +440,30 @@ public class CassandraDaemon
      */
     public void start()
     {
+        // We only start transports if bootstrap has completed and we're not 
in survey mode, OR if we are in
+        // survey mode and streaming has completed but we're not using auth.
+        // OR if we have not joined the ring yet.
+        if (StorageService.instance.hasJoined())
+        {
+            if (StorageService.instance.isSurveyMode())
+            {
+                if (StorageService.instance.isBootstrapMode() || 
DatabaseDescriptor.getAuthenticator().requireAuthentication())
+                {
+                    logger.info("Not starting client transports in 
write_survey mode as it's bootstrapping or " +
+                            "auth is enabled");
+                    return;
+                }
+            }
+            else
+            {
+                if (!SystemKeyspace.bootstrapComplete())
+                {
+                    logger.info("Not starting client transports as bootstrap 
has not completed");
+                    return;
+                }
+            }
+        }
+
         String nativeFlag = 
System.getProperty("cassandra.start_native_transport");
         if ((nativeFlag != null && Boolean.parseBoolean(nativeFlag)) || 
(nativeFlag == null && DatabaseDescriptor.startNativeTransport()))
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/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 2c9ac4d..03470b6 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -156,7 +156,8 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
     private volatile boolean isBootstrapMode;
 
     /* we bootstrap but do NOT join the ring unless told to do so */
-    private boolean isSurveyMode = 
Boolean.parseBoolean(System.getProperty("cassandra.write_survey", "false"));
+    private boolean isSurveyMode = Boolean.parseBoolean(System.getProperty
+            ("cassandra.write_survey", "false"));
     /* true if node is rebuilding and receiving data */
     private final AtomicBoolean isRebuilding = new AtomicBoolean();
 
@@ -193,6 +194,16 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
 
     private final AtomicBoolean doneAuthSetup = new AtomicBoolean(false);
 
+    public boolean isSurveyMode()
+    {
+        return isSurveyMode;
+    }
+
+    public boolean hasJoined()
+    {
+        return joined;
+    }
+
     /** This method updates the local token on disk  */
     public void setTokens(Collection<Token> tokens)
     {
@@ -326,6 +337,30 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         {
             throw new IllegalStateException("No configured daemon");
         }
+
+        // We only start transports if bootstrap has completed and we're not 
in survey mode, OR if we are in
+        // survey mode and streaming has completed but we're not using auth.
+        // OR if we have not joined the ring yet.
+        if (StorageService.instance.hasJoined())
+        {
+            if (StorageService.instance.isSurveyMode())
+            {
+                if (StorageService.instance.isBootstrapMode() || 
DatabaseDescriptor.getAuthenticator().requireAuthentication())
+                {
+                    throw new IllegalStateException("Not starting RPC server 
in write_survey mode as " +
+                            "it's bootstrapping or auth is enabled");
+                }
+            }
+            else
+            {
+                if (!SystemKeyspace.bootstrapComplete())
+                {
+                    throw new IllegalStateException("Node is not yet 
bootstrapped completely. Use nodetool to check bootstrap" +
+                            " state and resume. For more, see `nodetool help 
bootstrap`");
+                }
+            }
+        }
+        
         daemon.thriftServer.start();
     }
 
@@ -350,6 +385,22 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
 
     public void startNativeTransport()
     {
+        // We only start transports if bootstrap has completed and we're not 
in survey mode, OR if we are in
+        // survey mode and streaming has completed but we're not using auth.
+        // OR if we have not joined the ring yet.
+        if (hasJoined() &&
+                ((!isSurveyMode() && !SystemKeyspace.bootstrapComplete()) ||
+                (isSurveyMode() && isBootstrapMode())))
+        {
+            throw new IllegalStateException("Node is not yet bootstrapped 
completely. Use nodetool to check bootstrap" +
+                    " state and resume. For more, see `nodetool help 
bootstrap`");
+        }
+        if (hasJoined() && isSurveyMode() && 
!SystemKeyspace.bootstrapComplete() &&
+                DatabaseDescriptor.getAuthenticator().requireAuthentication())
+        {
+            throw new IllegalStateException("Not starting client transports as 
write_survey mode is enabled");
+        }
+
         if (daemon == null)
         {
             throw new IllegalStateException("No configured daemon");
@@ -925,7 +976,10 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         }
         else
         {
-            logger.info("Startup complete, but write survey mode is active, 
not becoming an active ring member. Use JMX (StorageService->joinRing()) to 
finalize ring joining.");
+            if (dataAvailable)
+                logger.info("Startup complete, but write survey mode is 
active, not becoming an active ring member. Use JMX 
(StorageService->joinRing()) to finalize ring joining.");
+            else
+                logger.warn("Some data streaming failed. Use nodetool to check 
bootstrap state and resume. For more, see `nodetool help bootstrap`. {}", 
SystemKeyspace.getBootstrapState());
         }
     }
 
@@ -959,9 +1013,24 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
         }
         else if (isSurveyMode)
         {
-            isSurveyMode = false;
-            logger.info("Leaving write survey mode and joining ring at 
operator request");
-            finishJoiningRing(SystemKeyspace.getSavedTokens());
+            // if isSurveyMode is on then verify isBootstrapMode
+            // node can join the ring even if isBootstrapMode is true which 
should not happen
+            if (!isBootstrapMode())
+            {
+                isSurveyMode = false;
+                logger.info("Leaving write survey mode and joining ring at 
operator request");
+                finishJoiningRing(SystemKeyspace.getSavedTokens());
+                daemon.start();
+            }
+            else
+            {
+                logger.warn("Can't join the ring because in write_survey mode 
and bootstrap hasn't completed");
+            }
+        }
+        else if (isBootstrapMode())
+        {
+            // bootstrap is not complete hence node cannot join the ring
+            logger.warn("Can't join the ring because bootstrap hasn't 
completed.");
         }
     }
 
@@ -1235,19 +1304,18 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
                 public void onSuccess(StreamState streamState)
                 {
                     isBootstrapMode = false;
-                    // start participating in the ring.
-                    // pretend we are in survey mode so we can use joinRing() 
here
-                    isSurveyMode = true;
-                    try
+                    if (isSurveyMode)
                     {
-                        progressSupport.progress("bootstrap", 
ProgressEvent.createNotification("Joining ring..."));
-                        joinRing();
+                        logger.info("Startup complete, but write survey mode 
is active, not becoming an active ring member. Use JMX 
(StorageService->joinRing()) to finalize ring joining.");
                     }
-                    catch (IOException ignore)
+                    else
                     {
-                        // joinRing with survey mode does not throw IOException
+                        isSurveyMode = false;
+                        progressSupport.progress("bootstrap", 
ProgressEvent.createNotification("Joining ring..."));
+                        finishJoiningRing(bootstrapTokens);
                     }
                     progressSupport.progress("bootstrap", new 
ProgressEvent(ProgressEventType.COMPLETE, 1, 1, "Resume bootstrap complete"));
+                    daemon.start();
                     logger.info("Resume complete");
                 }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java 
b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
index f336bcc..43d26c6 100644
--- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java
@@ -491,6 +491,13 @@ public int scrub(boolean disableSnapshot, boolean 
skipCorrupted, boolean checkDa
     public void joinRing() throws IOException;
     public boolean isJoined();
 
+    /** Check if currently bootstrapping.
+     * Note this becomes false before {@link 
org.apache.cassandra.db.SystemKeyspace#bootstrapComplete()} is called,
+     * as setting bootstrap to complete is called only when the node joins the 
ring.
+     * @return True prior to bootstrap streaming completing. False prior to 
start of bootstrap and post streaming.
+     */
+    public boolean isBootstrapMode();
+
     public void setStreamThroughputMbPerSec(int value);
     public int getStreamThroughputMbPerSec();
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/src/java/org/apache/cassandra/tools/NodeProbe.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java 
b/src/java/org/apache/cassandra/tools/NodeProbe.java
index 17bef02..a022595 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -574,6 +574,11 @@ public class NodeProbe implements AutoCloseable
         return ssProxy.isJoined();
     }
 
+    public boolean isBootstrapMode()
+    {
+        return ssProxy.isBootstrapMode();
+    }
+
     public void joinRing() throws IOException
     {
         ssProxy.joinRing();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/a6196a3a/src/java/org/apache/cassandra/tools/nodetool/Join.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/Join.java 
b/src/java/org/apache/cassandra/tools/nodetool/Join.java
index 5815591..a4a7cad 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/Join.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/Join.java
@@ -32,6 +32,7 @@ public class Join extends NodeToolCmd
     public void execute(NodeProbe probe)
     {
         checkState(!probe.isJoined(), "This node has already joined the 
ring.");
+        checkState(!probe.isBootstrapMode(), "Cannot join the ring until 
bootstrap completes");
 
         try
         {


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

Reply via email to