This is an automated email from the ASF dual-hosted git repository.
dcapwell pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new 0fa26aa75d Fix flakey tests due to tests updating SSTable format
dynamically
0fa26aa75d is described below
commit 0fa26aa75d51cb394d375d1650c0d8fd7ed0bb96
Author: David Capwell <[email protected]>
AuthorDate: Mon Jan 26 16:20:26 2026 -0800
Fix flakey tests due to tests updating SSTable format dynamically
patch by David Capwell; reviewed by Jyothsna Konisa, Nitsan Wakart for
CASSANDRA-21130
---
.../distributed/test/cql3/StatefulASTBase.java | 3 +-
.../cassandra/config/TestDatabaseDescriptor.java | 120 +++++++++++++++++++++
.../apache/cassandra/cql3/RandomSchemaTest.java | 3 +-
.../db/virtual/PartitionKeyStatsTableTest.java | 4 +-
.../autorepair/RepairTokenRangeSplitterTest.java | 3 +-
.../service/accord/AccordKeyspaceTest.java | 4 +-
6 files changed, 130 insertions(+), 7 deletions(-)
diff --git
a/test/distributed/org/apache/cassandra/distributed/test/cql3/StatefulASTBase.java
b/test/distributed/org/apache/cassandra/distributed/test/cql3/StatefulASTBase.java
index cec98dcbea..3f0d50b4e5 100644
---
a/test/distributed/org/apache/cassandra/distributed/test/cql3/StatefulASTBase.java
+++
b/test/distributed/org/apache/cassandra/distributed/test/cql3/StatefulASTBase.java
@@ -49,6 +49,7 @@ import accord.utils.RandomSource;
import org.apache.cassandra.config.CassandraRelevantProperties;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.TestDatabaseDescriptor;
import org.apache.cassandra.cql3.KnownIssue;
import org.apache.cassandra.cql3.ast.Bind;
import org.apache.cassandra.cql3.ast.CQLFormatter;
@@ -442,7 +443,7 @@ public class StatefulASTBase extends TestBaseImpl
createTable(metadata);
String sstableFormatName = this.sstableFormatName =
Generators.toGen(CassandraGenerators.sstableFormatNames()).next(rs);
- cluster.forEach(i -> i.runOnInstance(() ->
DatabaseDescriptor.setSelectedSSTableFormat(sstableFormatName)));
+ cluster.forEach(i -> i.runOnInstance(() ->
TestDatabaseDescriptor.setUnsafeSelectedSSTableFormat(sstableFormatName)));
}
public boolean hasPartitions()
diff --git a/test/unit/org/apache/cassandra/config/TestDatabaseDescriptor.java
b/test/unit/org/apache/cassandra/config/TestDatabaseDescriptor.java
new file mode 100644
index 0000000000..d7f9aaaf1d
--- /dev/null
+++ b/test/unit/org/apache/cassandra/config/TestDatabaseDescriptor.java
@@ -0,0 +1,120 @@
+/*
+ * 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.config;
+
+import java.util.ArrayList;
+
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.compaction.CompactionManager;
+import org.apache.cassandra.io.sstable.format.SSTableFormat;
+
+import static org.apache.cassandra.utils.Throwables.maybeFail;
+import static org.apache.cassandra.utils.Throwables.merge;
+
+/**
+ * Test utilities for DatabaseDescriptor that require server-side classes.
+ * These methods are separated from DatabaseDescriptor to avoid loading
+ * server classes during initialization.
+ */
+public class TestDatabaseDescriptor
+{
+ /**
+ * Sets the global SSTable format after safely pausing all compactions.
+ *
+ * @param name the SSTable format name (e.g., "big" or "bti")
+ */
+ public static void setUnsafeSelectedSSTableFormat(String name)
+ {
+ SSTableFormat<?, ?> format =
DatabaseDescriptor.getSSTableFormats().get(name);
+ if (format == null)
+ throw new IllegalArgumentException("Unknown sstable format: " +
name);
+ setUnsafeSelectedSSTableFormat(format);
+ }
+
+ /**
+ * Sets the global SSTable format after safely pausing all compactions.
+ * <p>
+ * This method:
+ * 1. Pauses global compactions
+ * 2. Pauses all table compaction strategies
+ * 3. Waits for in-flight compactions to complete
+ * 4. Changes the SSTable format
+ * 5. Resumes compactions
+ *
+ * @param format the SSTable format to set
+ */
+ public static void setUnsafeSelectedSSTableFormat(SSTableFormat<?, ?>
format)
+ {
+ // Get all CFSs across all keyspaces since SSTable format is global
+ Iterable<ColumnFamilyStore> allCfs = ColumnFamilyStore.all();
+
+ // Pause both global compactions and all table compaction strategies
+ // This prevents NEW compactions from starting
+ try (CompactionManager.CompactionPauser globalPause =
CompactionManager.instance.pauseGlobalCompaction();
+ CompactionManager.CompactionPauser strategiesPause =
pauseAllCompactionStrategies(allCfs))
+ {
+ // Wait for all existing in-flight compactions to complete
naturally (don't interrupt)
+ // Uses 1-minute timeout per waitForCessation implementation
+ CompactionManager.instance.waitForCessation(allCfs, sstable ->
true);
+
+ // Now safe to change the global SSTable format
+ DatabaseDescriptor.setSelectedSSTableFormat(format);
+ }
+ // Compactions auto-resume when pausers are closed
+ }
+
+ /**
+ * Pauses compaction strategies for all given ColumnFamilyStores.
+ * Pattern matches {@link ColumnFamilyStore#pauseCompactionStrategies}.
+ */
+ private static CompactionManager.CompactionPauser
pauseAllCompactionStrategies(Iterable<ColumnFamilyStore> toPause)
+ {
+ ArrayList<ColumnFamilyStore> successfullyPaused = new ArrayList<>();
+ try
+ {
+ for (ColumnFamilyStore cfs : toPause)
+ {
+ successfullyPaused.ensureCapacity(successfullyPaused.size() +
1); // to avoid OOM after pausing the strategies
+ cfs.getCompactionStrategyManager().pause();
+ successfullyPaused.add(cfs);
+ }
+ return () -> maybeFail(resumeAll(null, toPause));
+ }
+ catch (Throwable t)
+ {
+ resumeAll(t, successfullyPaused);
+ throw t;
+ }
+ }
+
+ private static Throwable resumeAll(Throwable accumulate,
Iterable<ColumnFamilyStore> cfss)
+ {
+ for (ColumnFamilyStore cfs : cfss)
+ {
+ try
+ {
+ cfs.getCompactionStrategyManager().resume();
+ }
+ catch (Throwable t)
+ {
+ accumulate = merge(accumulate, t);
+ }
+ }
+ return accumulate;
+ }
+}
diff --git a/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
b/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
index c4c8815866..f137bdd934 100644
--- a/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
+++ b/test/unit/org/apache/cassandra/cql3/RandomSchemaTest.java
@@ -37,6 +37,7 @@ import org.quicktheories.impl.JavaRandom;
import org.apache.cassandra.config.CassandraRelevantProperties;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.TestDatabaseDescriptor;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.compaction.CursorCompactor;
import org.apache.cassandra.io.sstable.format.SSTableFormat;
@@ -79,7 +80,7 @@ public class RandomSchemaTest extends CQLTester.InMemory
resetSchema();
// TODO : when table level override of sstable format is allowed,
migrate to that
- if (!STRESS_CURSOR_COMPACTION)
DatabaseDescriptor.setSelectedSSTableFormat(sstableFormatGen.generate(random));
+ if (!STRESS_CURSOR_COMPACTION)
TestDatabaseDescriptor.setUnsafeSelectedSSTableFormat(sstableFormatGen.generate(random));
Gen<String> udtName = Generators.unique(IDENTIFIER_GEN);
diff --git
a/test/unit/org/apache/cassandra/db/virtual/PartitionKeyStatsTableTest.java
b/test/unit/org/apache/cassandra/db/virtual/PartitionKeyStatsTableTest.java
index e78c46ebb3..e61a3b17ad 100644
--- a/test/unit/org/apache/cassandra/db/virtual/PartitionKeyStatsTableTest.java
+++ b/test/unit/org/apache/cassandra/db/virtual/PartitionKeyStatsTableTest.java
@@ -41,7 +41,7 @@ import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.apache.cassandra.Util;
-import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.TestDatabaseDescriptor;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.io.sstable.format.bti.BtiFormat;
@@ -73,7 +73,7 @@ public class PartitionKeyStatsTableTest extends CQLTester
public void before()
{
if (useBtiFormat)
- DatabaseDescriptor.setSelectedSSTableFormat(new
BtiFormat.BtiFormatFactory().getInstance(Collections.emptyMap()));
+ TestDatabaseDescriptor.setUnsafeSelectedSSTableFormat(new
BtiFormat.BtiFormatFactory().getInstance(Collections.emptyMap()));
PartitionKeyStatsTable primaryIdTable = new
PartitionKeyStatsTable(KS_NAME);
scanned = new AtomicInteger();
diff --git
a/test/unit/org/apache/cassandra/repair/autorepair/RepairTokenRangeSplitterTest.java
b/test/unit/org/apache/cassandra/repair/autorepair/RepairTokenRangeSplitterTest.java
index 989573824e..2383a1eb68 100644
---
a/test/unit/org/apache/cassandra/repair/autorepair/RepairTokenRangeSplitterTest.java
+++
b/test/unit/org/apache/cassandra/repair/autorepair/RepairTokenRangeSplitterTest.java
@@ -38,6 +38,7 @@ import org.junit.runners.Parameterized;
import org.apache.cassandra.auth.AuthKeyspace;
import org.apache.cassandra.config.DataStorageSpec.LongMebibytesBound;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.config.TestDatabaseDescriptor;
import org.apache.cassandra.cql3.CQLTester;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.lifecycle.SSTableSet;
@@ -94,7 +95,7 @@ public class RepairTokenRangeSplitterTest extends CQLTester
public void setUp()
{
AutoRepairService.instance.getAutoRepairConfig().setRepairByKeyspace(RepairType.FULL,
true);
-
DatabaseDescriptor.setSelectedSSTableFormat(DatabaseDescriptor.getSSTableFormats().get(sstableFormat));
+
TestDatabaseDescriptor.setUnsafeSelectedSSTableFormat(DatabaseDescriptor.getSSTableFormats().get(sstableFormat));
repairRangeSplitter = new RepairTokenRangeSplitter(RepairType.FULL,
Collections.emptyMap());
tableName = createTable("CREATE TABLE %s (k INT PRIMARY KEY, v INT)");
// ensure correct format is selected.
diff --git
a/test/unit/org/apache/cassandra/service/accord/AccordKeyspaceTest.java
b/test/unit/org/apache/cassandra/service/accord/AccordKeyspaceTest.java
index cb3c6147c5..b467edce53 100644
--- a/test/unit/org/apache/cassandra/service/accord/AccordKeyspaceTest.java
+++ b/test/unit/org/apache/cassandra/service/accord/AccordKeyspaceTest.java
@@ -75,7 +75,7 @@ import org.apache.cassandra.utils.CassandraGenerators;
import static accord.local.Command.Committed.committed;
import static accord.utils.Property.qt;
import static org.apache.cassandra.config.DatabaseDescriptor.getPartitioner;
-import static
org.apache.cassandra.config.DatabaseDescriptor.setSelectedSSTableFormat;
+import static
org.apache.cassandra.config.TestDatabaseDescriptor.setUnsafeSelectedSSTableFormat;
import static org.apache.cassandra.db.ColumnFamilyStore.FlushReason.UNIT_TESTS;
import static
org.apache.cassandra.distributed.test.log.ClusterMetadataTestHelper.setMemtable;
import static org.apache.cassandra.schema.SchemaConstants.ACCORD_KEYSPACE_NAME;
@@ -147,7 +147,7 @@ public class AccordKeyspaceTest extends CQLTester.InMemory
qt().check(rs -> {
AccordKeyspace.unsafeClear();
// control SSTable format
-
setSelectedSSTableFormat(sstableFormats.get(rs.pick(sstableFormatNames)));
+
setUnsafeSelectedSSTableFormat(sstableFormats.get(rs.pick(sstableFormatNames)));
// control memtable format
setMemtable(ACCORD_KEYSPACE_NAME, "commands_for_key",
rs.pick(memtableFormats));
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]