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