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

asf-gitbox-commits pushed a commit to branch cassandra-6.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit bb784f465a7299f449e15c056076182bbec3f8e5
Author: Marcus Eriksson <[email protected]>
AuthorDate: Wed Mar 25 16:43:52 2026 +0100

    During major upgrade, if a node has replacement arguments it attempts to 
bootstrap even if already bootstrapped
    
    Patch by marcuse; reviewed by Sam Tunnicliffe for CASSANDRA-21634
---
 CHANGES.txt                                        |  1 +
 .../apache/cassandra/service/StorageService.java   |  2 +-
 src/java/org/apache/cassandra/tcm/Startup.java     |  2 +-
 .../upgrade/ClusterMetadataUpgradeReplaceTest.java | 56 ++++++++++++++++++++++
 4 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index c9a8a07948..dcb7243657 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 6.0-alpha3
+ * During major upgrade, if a node has replacement arguments it attempts to 
bootstrap even if already bootstrapped (CASSANDRA-21634)
  * Node with empty data directory is allowed to rejoin the ring on the second 
start after the first start is correctly rejected (CASSANDRA-21633)
  * Megamorphic call in ClusteringPrefix.Deserializer.deserializeOne slows down 
reads (CASSANDRA-21587)
  * Throw InvalidRequestException instead of crashing on malformed IN marker 
values (CASSANDRA-21648)
diff --git a/src/java/org/apache/cassandra/service/StorageService.java 
b/src/java/org/apache/cassandra/service/StorageService.java
index a897cba85e..8a118044fa 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -819,7 +819,7 @@ public class StorageService extends 
NotificationBroadcasterSupport implements IE
             BootstrapAndReplace.checkUnsafeReplace(shouldBootstrap());
         }
 
-        if (isReplacingSameAddress())
+        if (isReplacing() && isReplacingSameAddress())
         {
             
BootstrapAndReplace.gossipStateToHibernate(ClusterMetadata.current(), 
ClusterMetadata.currentNullable().myNodeId());
             
Gossiper.instance.start(SystemKeyspace.incrementAndGetGeneration(), false);
diff --git a/src/java/org/apache/cassandra/tcm/Startup.java 
b/src/java/org/apache/cassandra/tcm/Startup.java
index 0f450c5819..a808193151 100644
--- a/src/java/org/apache/cassandra/tcm/Startup.java
+++ b/src/java/org/apache/cassandra/tcm/Startup.java
@@ -686,7 +686,7 @@ import static 
org.apache.cassandra.utils.FBUtilities.getBroadcastAddressAndPort;
                     break;
                 }
             case JOINED:
-                if (StorageService.isReplacingSameAddress())
+                if (StorageService.instance.isReplacing() && 
StorageService.isReplacingSameAddress())
                 {
                     if (DatabaseDescriptor.getAccordTransactionsEnabled())
                     {
diff --git 
a/test/distributed/org/apache/cassandra/distributed/upgrade/ClusterMetadataUpgradeReplaceTest.java
 
b/test/distributed/org/apache/cassandra/distributed/upgrade/ClusterMetadataUpgradeReplaceTest.java
new file mode 100644
index 0000000000..e51fe1efe2
--- /dev/null
+++ 
b/test/distributed/org/apache/cassandra/distributed/upgrade/ClusterMetadataUpgradeReplaceTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.distributed.upgrade;
+
+import org.junit.Test;
+
+import org.apache.cassandra.config.CassandraRelevantProperties;
+import org.apache.cassandra.distributed.Constants;
+import org.apache.cassandra.distributed.api.Feature;
+import org.apache.cassandra.distributed.shared.Versions;
+import org.apache.cassandra.distributed.shared.WithProperties;
+
+public class ClusterMetadataUpgradeReplaceTest extends UpgradeTestBase
+{
+    @Test
+    public void upgradeReplaceFirstBootTest() throws Throwable
+    {
+        new TestCase()
+        .nodes(3)
+        .nodesToUpgrade(1, 2)
+        .withConfig((cfg) -> cfg.with(Feature.NETWORK, Feature.GOSSIP)
+                                .set(Constants.KEY_DTEST_FULL_STARTUP, true))
+        .upgradesToCurrentFrom(v50)
+        .setup((cluster) -> {
+            cluster.schemaChange(withKeyspace("ALTER KEYSPACE %s WITH 
replication = {'class': 'SimpleStrategy', 'replication_factor':2}"));
+            cluster.schemaChange("CREATE TABLE " + KEYSPACE + ".tbl (pk int, 
ck int, v int, PRIMARY KEY (pk, ck))");
+        })
+        .runAfterClusterUpgrade((cluster) -> {
+            cluster.get(3).shutdown().get();
+            cluster.get(3).setVersion(Versions.find().getLatest(CURRENT));
+            String address = 
cluster.get(3).config().getString("broadcast_address");
+            try (WithProperties x = new 
WithProperties().set(CassandraRelevantProperties.REPLACE_ADDRESS_FIRST_BOOT, 
address))
+            {
+                cluster.get(3).startup();
+            }
+
+            cluster.get(1).nodetoolResult("cms", 
"initialize").asserts().success();
+        }).run();
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to