You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by pa...@apache.org on 2024/01/10 16:23:50 UTC
(cassandra) branch cassandra-4.0 updated: [CASSANDRA-18999] Gossiper::hasMajorVersion3Nodes returns true when a cluster is upgrading patch version without Cassandra 3 nodes.
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 <ir...@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-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org