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

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


The following commit(s) were added to refs/heads/cassandra-4.0 by this push:
     new 475c0035e6 [CASSANDRA-18999] Gossiper::hasMajorVersion3Nodes returns 
true when a cluster is upgrading patch version without Cassandra 3 nodes.
475c0035e6 is described below

commit 475c0035e6e04526eaf50805d33156ac9b828ab6
Author: Isaac Reath <ire...@bloomberg.net>
AuthorDate: Fri Jan 5 12:57:21 2024 -0500

    [CASSANDRA-18999] Gossiper::hasMajorVersion3Nodes returns true when a 
cluster is upgrading patch version without Cassandra 3 nodes.
    
    This commit fixes Gossiper::hasMajorVersion3Nodes so that it does not 
return true when all hosts have a known version, no hosts are on a version 
earlier than 4.0, and there is a 4.x minor version or patch version upgrade in 
progress. Additionally, this commit improves the clarity of 
Gossiper::hasMajorVersion3Nodes's name to indicate that it will return true 
when the cluster has 3.x nodes or if the cluster state is unknown, matching the 
description in the in-line comment.
    
    patch by Isaac Reath; reviewed by Paulo Motta and Stefan Miklosovic for 
CASSANDRA-18999
    
    Closes #2967
---
 CHANGES.txt                                        |  1 +
 src/java/org/apache/cassandra/gms/Gossiper.java    | 15 ++++---
 .../repair/SystemDistributedKeyspace.java          |  2 +-
 .../apache/cassandra/tracing/TraceKeyspace.java    |  4 +-
 test/unit/org/apache/cassandra/Util.java           |  2 +-
 .../org/apache/cassandra/gms/GossiperTest.java     | 50 +++++++++++++++++++++-
 6 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 0edb216735..d944415f76 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0.12
+ * Fix Gossiper::hasMajorVersion3Nodes to return false during minor upgrade 
(CASSANDRA-18999)
  * Revert unnecessary read lock acquisition when reading ring version in 
TokenMetadata introduced in CASSANDRA-16286 (CASSANDRA-19107)
  * Support max SSTable size in sorted CQLSSTableWriter (CASSANDRA-18941)
  * Fix nodetool repair_admin summarize-pending command to not throw exception 
(CASSANDRA-19014)
diff --git a/src/java/org/apache/cassandra/gms/Gossiper.java 
b/src/java/org/apache/cassandra/gms/Gossiper.java
index f88ee44edf..22595b299a 100644
--- a/src/java/org/apache/cassandra/gms/Gossiper.java
+++ b/src/java/org/apache/cassandra/gms/Gossiper.java
@@ -170,6 +170,7 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
      * This property and anything that checks it should be removed in 5.0
      */
     private volatile boolean upgradeInProgressPossible = true;
+    private volatile boolean hasNodeWithUnknownVersion = false;
 
     public void clearUnsafe()
     {
@@ -206,14 +207,14 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
         }
 
         // Check the release version of all the peers it heard of. Not 
necessary the peer that it has/had contacted with.
-        boolean allHostsHaveKnownVersion = true;
+        hasNodeWithUnknownVersion = false;
         for (InetAddressAndPort host : endpointStateMap.keySet())
         {
             CassandraVersion version = getReleaseVersion(host);
 
             //Raced with changes to gossip state, wait until next iteration
             if (version == null)
-                allHostsHaveKnownVersion = false;
+                hasNodeWithUnknownVersion = true;
             else if (version.compareTo(minVersion) < 0)
                 minVersion = version;
         }
@@ -221,7 +222,7 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
         if (minVersion.compareTo(SystemKeyspace.CURRENT_VERSION) < 0)
             return new ExpiringMemoizingSupplier.Memoized<>(minVersion);
 
-        if (!allHostsHaveKnownVersion)
+        if (hasNodeWithUnknownVersion)
             return new ExpiringMemoizingSupplier.NotMemoized<>(minVersion);
 
         upgradeInProgressPossible = false;
@@ -1466,7 +1467,7 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
 
             EndpointState localEpStatePtr = endpointStateMap.get(ep);
             EndpointState remoteState = entry.getValue();
-            if (!hasMajorVersion3Nodes())
+            if (!hasMajorVersion3OrUnknownNodes())
                 remoteState.removeMajorVersion3LegacyApplicationStates();
 
             /*
@@ -1554,7 +1555,7 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
         localState.addApplicationStates(updatedStates);
 
         // get rid of legacy fields once the cluster is not in mixed mode
-        if (!hasMajorVersion3Nodes())
+        if (!hasMajorVersion3OrUnknownNodes())
             localState.removeMajorVersion3LegacyApplicationStates();
 
         for (Entry<ApplicationState, VersionedValue> updatedEntry : 
updatedStates)
@@ -2270,12 +2271,12 @@ public class Gossiper implements 
IFailureDetectionEventListener, GossiperMBean
      * Returns {@code false} only if the information about the version of each 
node in the cluster is available and
      * ALL the nodes are on 4.0+ (regardless of the patch version).
      */
-    public boolean hasMajorVersion3Nodes()
+    public boolean hasMajorVersion3OrUnknownNodes()
     {
         return isUpgradingFromVersionLowerThan(CassandraVersion.CASSANDRA_4_0) 
|| // this is quite obvious
                // however if we discovered only nodes at current version so 
far (in particular only this node),
                // but still there are nodes with unknown version, we also want 
to report that the cluster may have nodes at 3.x
-               upgradeInProgressPossible && 
!isUpgradingFromVersionLowerThan(SystemKeyspace.CURRENT_VERSION.familyLowerBound.get());
+               hasNodeWithUnknownVersion;
     }
 
     /**
diff --git 
a/src/java/org/apache/cassandra/repair/SystemDistributedKeyspace.java 
b/src/java/org/apache/cassandra/repair/SystemDistributedKeyspace.java
index a3f877452f..0d28dead31 100644
--- a/src/java/org/apache/cassandra/repair/SystemDistributedKeyspace.java
+++ b/src/java/org/apache/cassandra/repair/SystemDistributedKeyspace.java
@@ -214,7 +214,7 @@ public final class SystemDistributedKeyspace
     {
         //Don't record repair history if an upgrade is in progress as version 
3 nodes generates errors
         //due to schema differences
-        boolean includeNewColumns = !Gossiper.instance.hasMajorVersion3Nodes();
+        boolean includeNewColumns = 
!Gossiper.instance.hasMajorVersion3OrUnknownNodes();
 
         InetAddressAndPort coordinator = 
FBUtilities.getBroadcastAddressAndPort();
         Set<String> participants = Sets.newHashSet();
diff --git a/src/java/org/apache/cassandra/tracing/TraceKeyspace.java 
b/src/java/org/apache/cassandra/tracing/TraceKeyspace.java
index c2e74d81d2..a9c38b77a1 100644
--- a/src/java/org/apache/cassandra/tracing/TraceKeyspace.java
+++ b/src/java/org/apache/cassandra/tracing/TraceKeyspace.java
@@ -118,7 +118,7 @@ public final class TraceKeyspace
         rb.ttl(ttl)
           .add("client", client)
           .add("coordinator", 
FBUtilities.getBroadcastAddressAndPort().address);
-        if (!Gossiper.instance.hasMajorVersion3Nodes())
+        if (!Gossiper.instance.hasMajorVersion3OrUnknownNodes())
             rb.add("coordinator_port", 
FBUtilities.getBroadcastAddressAndPort().port);
         rb.add("request", request)
           .add("started_at", new Date(startedAt))
@@ -145,7 +145,7 @@ public final class TraceKeyspace
 
         rowBuilder.add("activity", message)
                   .add("source", 
FBUtilities.getBroadcastAddressAndPort().address);
-        if (!Gossiper.instance.hasMajorVersion3Nodes())
+        if (!Gossiper.instance.hasMajorVersion3OrUnknownNodes())
             rowBuilder.add("source_port", 
FBUtilities.getBroadcastAddressAndPort().port);
         rowBuilder.add("thread", threadName);
 
diff --git a/test/unit/org/apache/cassandra/Util.java 
b/test/unit/org/apache/cassandra/Util.java
index 4b7b6eaec9..caeb88c35c 100644
--- a/test/unit/org/apache/cassandra/Util.java
+++ b/test/unit/org/apache/cassandra/Util.java
@@ -828,7 +828,7 @@ public class Util
 
     /**
      * Setups Gossiper to mimic the upgrade behaviour when {@link 
Gossiper#isUpgradingFromVersionLowerThan(CassandraVersion)}
-     * or {@link Gossiper#hasMajorVersion3Nodes()} is called.
+     * or {@link Gossiper#hasMajorVersion3OrUnknownNodes()} is called.
      */
     public static void setUpgradeFromVersion(String version)
     {
diff --git a/test/unit/org/apache/cassandra/gms/GossiperTest.java 
b/test/unit/org/apache/cassandra/gms/GossiperTest.java
index a48b5fb0b4..c0a2d453b3 100644
--- a/test/unit/org/apache/cassandra/gms/GossiperTest.java
+++ b/test/unit/org/apache/cassandra/gms/GossiperTest.java
@@ -133,7 +133,7 @@ public class GossiperTest
 
         
assertFalse(Gossiper.instance.upgradeFromVersionSupplier.get().value().compareTo(new
 CassandraVersion("3.0")) < 0);
         
assertTrue(Gossiper.instance.upgradeFromVersionSupplier.get().value().compareTo(new
 CassandraVersion("3.1")) < 0);
-        assertTrue(Gossiper.instance.hasMajorVersion3Nodes());
+        assertTrue(Gossiper.instance.hasMajorVersion3OrUnknownNodes());
 
         
Gossiper.instance.endpointStateMap.remove(InetAddressAndPort.getByName("127.0.0.3"));
         
Gossiper.instance.liveEndpoints.remove(InetAddressAndPort.getByName("127.0.0.3"));
@@ -141,7 +141,7 @@ public class GossiperTest
         
assertFalse(Gossiper.instance.upgradeFromVersionSupplier.get().value().compareTo(new
 CassandraVersion("3.0")) < 0);
         
assertFalse(Gossiper.instance.upgradeFromVersionSupplier.get().value().compareTo(new
 CassandraVersion("3.1")) < 0);
         
assertTrue(Gossiper.instance.upgradeFromVersionSupplier.get().value().compareTo(new
 CassandraVersion("3.12")) < 0);
-        assertTrue(Gossiper.instance.hasMajorVersion3Nodes());
+        assertTrue(Gossiper.instance.hasMajorVersion3OrUnknownNodes());
 
         
Gossiper.instance.endpointStateMap.remove(InetAddressAndPort.getByName("127.0.0.2"));
         
Gossiper.instance.liveEndpoints.remove(InetAddressAndPort.getByName("127.0.0.2"));
@@ -149,6 +149,52 @@ public class GossiperTest
         assertEquals(SystemKeyspace.CURRENT_VERSION, 
Gossiper.instance.upgradeFromVersionSupplier.get().value());
     }
 
+    @Test
+    public void 
testHasVersion3NodesShouldReturnFalseWhenNoVersion3NodesDetectedAndCassandra4UpgradeInProgress()
 throws Exception
+    {
+        Gossiper.instance.start(0);
+        Gossiper.instance.expireUpgradeFromVersion();
+
+        VersionedValue.VersionedValueFactory factory = new 
VersionedValue.VersionedValueFactory(null);
+        EndpointState es = new EndpointState((HeartBeatState) null);
+        es.addApplicationState(ApplicationState.RELEASE_VERSION, 
factory.releaseVersion(SystemKeyspace.CURRENT_VERSION.toString()));
+        
Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.1"),
 es);
+        
Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.1"));
+
+        es = new EndpointState((HeartBeatState) null);
+        String previousPatchVersion = 
String.valueOf(SystemKeyspace.CURRENT_VERSION.major) + '.' + 
(SystemKeyspace.CURRENT_VERSION.minor) + '.' + 
Math.max(SystemKeyspace.CURRENT_VERSION.patch - 1, 0);
+        es.addApplicationState(ApplicationState.RELEASE_VERSION, 
factory.releaseVersion(previousPatchVersion));
+        
Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.2"),
 es);
+        
Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.2"));
+        assertFalse(Gossiper.instance.hasMajorVersion3OrUnknownNodes());
+
+        
Gossiper.instance.endpointStateMap.remove(InetAddressAndPort.getByName("127.0.0.2"));
+        
Gossiper.instance.liveEndpoints.remove(InetAddressAndPort.getByName("127.0.0.2"));
+    }
+
+    @Test
+    public void 
testHasVersion3NodesShouldReturnTrueWhenNoVersion3NodesDetectedButNotAllVersionsKnown()
 throws Exception
+    {
+        Gossiper.instance.start(0);
+        Gossiper.instance.expireUpgradeFromVersion();
+
+        VersionedValue.VersionedValueFactory factory = new 
VersionedValue.VersionedValueFactory(null);
+        EndpointState es = new EndpointState((HeartBeatState) null);
+        es.addApplicationState(ApplicationState.RELEASE_VERSION, null);
+        
Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.3"),
 es);
+        
Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.3"));
+
+        es = new EndpointState((HeartBeatState) null);
+        String previousPatchVersion = 
String.valueOf(SystemKeyspace.CURRENT_VERSION.major) + '.' + 
(SystemKeyspace.CURRENT_VERSION.minor) + '.' + 
Math.max(SystemKeyspace.CURRENT_VERSION.patch - 1, 0);
+        es.addApplicationState(ApplicationState.RELEASE_VERSION, 
factory.releaseVersion(previousPatchVersion));
+        
Gossiper.instance.endpointStateMap.put(InetAddressAndPort.getByName("127.0.0.2"),
 es);
+        
Gossiper.instance.liveEndpoints.add(InetAddressAndPort.getByName("127.0.0.2"));
+        assertTrue(Gossiper.instance.hasMajorVersion3OrUnknownNodes());
+
+        
Gossiper.instance.endpointStateMap.remove(InetAddressAndPort.getByName("127.0.0.2"));
+        
Gossiper.instance.liveEndpoints.remove(InetAddressAndPort.getByName("127.0.0.2"));
+    }
+
     @Test
     public void testLargeGenerationJump() throws UnknownHostException, 
InterruptedException
     {


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

Reply via email to