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

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


The following commit(s) were added to refs/heads/cassandra-5.0 by this push:
     new ddfba19f9e Randomize Memtable type/allocation type and SSTable format 
in Simulator tests
ddfba19f9e is described below

commit ddfba19f9e547b102a54a700a0f99bcae565d06b
Author: Shruti Sekaran <[email protected]>
AuthorDate: Fri Feb 20 20:08:10 2026 -0800

    Randomize Memtable type/allocation type and SSTable format in Simulator 
tests
    
    patch by Shruti Sekaran; reviewed by Caleb Rackliffe and Francisco Guerrero 
for CASSANDRA-21177
---
 .../config/CassandraRelevantProperties.java        |   1 +
 .../cassandra/simulator/ClusterSimulation.java     | 114 ++++++++++++++++++++-
 .../systems/SimulatedFutureActionScheduler.java    |   7 ++
 .../simulator/test/ShortPaxosSimulationTest.java   |   6 +-
 .../simulator/test/SimulationTestBase.java         |  71 ++++++++++---
 .../simulator/test/TrivialSimulationTest.java      |   7 +-
 6 files changed, 186 insertions(+), 20 deletions(-)

diff --git 
a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java 
b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
index f8b983ba74..0c81d63afb 100644
--- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
+++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
@@ -480,6 +480,7 @@ public enum CassandraRelevantProperties
     
SERIALIZATION_EMPTY_TYPE_NONEMPTY_BEHAVIOR("cassandra.serialization.emptytype.nonempty_behavior"),
     SET_SEP_THREAD_NAME("cassandra.set_sep_thread_name", "true"),
     SHUTDOWN_ANNOUNCE_DELAY_IN_MS("cassandra.shutdown_announce_in_ms", "2000"),
+    SIMULATOR_ITERATIONS("simulator.iterations", "3"),
     SIZE_RECORDER_INTERVAL("cassandra.size_recorder_interval", "300"),
 
     /**
diff --git 
a/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java 
b/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
index f7f9346385..1bc900a13f 100644
--- a/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
+++ b/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
@@ -24,6 +24,7 @@ import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -38,7 +39,11 @@ import java.util.function.Supplier;
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.FutureCallback;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.cassandra.concurrent.ExecutorFactory;
+import org.apache.cassandra.config.CassandraRelevantProperties;
 import org.apache.cassandra.config.ParameterizedClass;
 import org.apache.cassandra.distributed.Cluster;
 import org.apache.cassandra.distributed.api.Feature;
@@ -112,6 +117,8 @@ import static 
org.apache.cassandra.utils.Shared.Scope.SIMULATION;
 @SuppressWarnings("RedundantCast")
 public class ClusterSimulation<S extends Simulation> implements AutoCloseable
 {
+    private static final Logger logger = 
LoggerFactory.getLogger(ClusterSimulation.class);
+
     public static final Class<?>[] SHARE = new Class[]
                                         {
                                             AsyncFunction.class,
@@ -188,6 +195,9 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
         protected HeapPool.Logged.Listener memoryListener;
         protected SimulatedTime.Listener timeListener = (i1, i2) -> {};
         protected LongConsumer onThreadLocalRandomCheck;
+        protected String memtableType = null;
+        protected String memtableAllocationType = null;
+        protected String sstableFormat = null;
 
         public Debug debug()
         {
@@ -516,6 +526,24 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
             return this;
         }
 
+        public Builder<S> memtableType(String type)
+        {
+            this.memtableType = type;
+            return this;
+        }
+
+        public Builder<S> memtableAllocationType(String type)
+        {
+            this.memtableAllocationType = type;
+            return this;
+        }
+
+        public Builder<S> sstableFormat(String format)
+        {
+            this.sstableFormat = format;
+            return this;
+        }
+
         public abstract ClusterSimulation<S> create(long seed) throws 
IOException;
     }
 
@@ -654,8 +682,68 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
 
         execution = new SimulatedExecution();
 
+        // Track randomized configuration for consolidated logging
+        Map<String, String> randomizedConfig = new LinkedHashMap<>();
+        randomizedConfig.put("nodes", String.valueOf(numOfNodes));
+        randomizedConfig.put("dcs", String.valueOf(numOfDcs));
+
+        // Log replication factors
+        StringBuilder rfString = new StringBuilder();
+        for (int i = 0; i < numOfDcs; ++i)
+        {
+            if (i > 0)
+                rfString.append(",");
+            rfString.append("dc").append(i).append(":").append(initialRf[i]);
+        }
+        randomizedConfig.put("replication_factors", rfString.toString());
+
+        // Randomize memtable type
+        String memtableType;
+        if (builder.memtableType != null)
+        {
+            memtableType = builder.memtableType;
+        }
+        else
+        {
+            String[] memtableTypes = {"TrieMemtable", "SkipListMemtable"};
+            memtableType = memtableTypes[random.uniform(0, 
memtableTypes.length)];
+        }
+        randomizedConfig.put("memtable", memtableType);
+
+        // Randomize memtable allocation type (heap-based only to avoid 
InterruptibleChannel issues with offheap)
+        String memtableAllocationType;
+        if (builder.memtableAllocationType != null)
+        {
+            memtableAllocationType = builder.memtableAllocationType;
+        }
+        else
+        {
+            String[] allocationTypes = {
+                "heap_buffers",           // Slab allocator (pooled memory)
+                "unslabbed_heap_buffers"  // Direct heap allocation (no 
pooling)
+            };
+            memtableAllocationType = allocationTypes[random.uniform(0, 
allocationTypes.length)];
+        }
+        randomizedConfig.put("memtable_allocation_type", 
memtableAllocationType);
+
+        // Randomize SSTable format
+        String sstableFormat;
+        if (builder.sstableFormat != null)
+        {
+            sstableFormat = builder.sstableFormat;
+        }
+        else
+        {
+            String[] formats = {"big", "bti"};
+            sstableFormat = formats[random.uniform(0, formats.length)];
+        }
+        randomizedConfig.put("sstable_format", sstableFormat);
+        
CassandraRelevantProperties.SSTABLE_FORMAT_DEFAULT.setString(sstableFormat);
+
         KindOfSequence kindOfDriftSequence = 
Choices.uniform(KindOfSequence.values()).choose(random);
         KindOfSequence kindOfDiscontinuitySequence = 
Choices.uniform(KindOfSequence.values()).choose(random);
+        randomizedConfig.put("clock_drift_sequence", 
kindOfDriftSequence.toString());
+        randomizedConfig.put("clock_discontinuity_sequence", 
kindOfDiscontinuitySequence.toString());
         time = new SimulatedTime(numOfNodes, random, 1577836800000L /*Jan 1st 
UTC*/, builder.clockDriftNanos, kindOfDriftSequence,
                                  
kindOfDiscontinuitySequence.period(builder.clockDiscontinuitIntervalNanos, 
random),
                                  builder.timeListener);
@@ -672,6 +760,7 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
         ThreadAllocator threadAllocator = new ThreadAllocator(random, 
builder.threadCount, numOfNodes);
         List<String> allowedDiskAccessModes = Arrays.asList("mmap", 
"mmap_index_only", "standard");
         String disk_access_mode = allowedDiskAccessModes.get(random.uniform(0, 
allowedDiskAccessModes.size() - 1));
+        randomizedConfig.put("disk_access_mode", disk_access_mode);
         boolean commitlogCompressed = random.decide(.5f);
         cluster = snitch.setup(Cluster.build(numOfNodes)
                          .withRoot(fs.getPath("/cassandra"))
@@ -683,13 +772,26 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
                                    .set("cas_contention_timeout", 
String.format("%dms", NANOSECONDS.toMillis(builder.contentionTimeoutNanos)))
                                    .set("request_timeout", 
String.format("%dms", NANOSECONDS.toMillis(builder.requestTimeoutNanos)))
                                    .set("memtable_heap_space", "1MiB")
-                                   .set("memtable_allocation_type", 
builder.memoryListener != null ? "unslabbed_heap_buffers_logged" : 
"heap_buffers")
+                                   .set("memtable_allocation_type", 
builder.memoryListener != null ? "unslabbed_heap_buffers_logged" : 
memtableAllocationType)
                                    .set("file_cache_size", "16MiB")
                                    .set("use_deterministic_table_id", true)
                                    .set("disk_access_mode", disk_access_mode)
                                    .set("failure_detector", 
SimulatedFailureDetector.Instance.class.getName())
                                    .set("commitlog_sync", "batch");
 
+                             if (memtableType.equals("TrieMemtable"))
+                             {
+                                 config.set("memtable", Map.of(
+                                           "configurations", Map.of(
+                                               "default", Map.of("class_name", 
"TrieMemtable"))));
+                             }
+                             else
+                             {
+                                 config.set("memtable", Map.of(
+                                           "configurations", Map.of(
+                                               "default", Map.of("class_name", 
"SkipListMemtable"))));
+                             }
+
                              // TODO: Add remove() to IInstanceConfig
                              if (config instanceof InstanceConfig)
                              {
@@ -779,10 +881,18 @@ public class ClusterSimulation<S extends Simulation> 
implements AutoCloseable
         simulated.register(futureActionScheduler);
 
         RunnableActionScheduler scheduler = 
builder.schedulerFactory.create(random);
-        ClusterActions.Options options = new 
ClusterActions.Options(builder.topologyChangeLimit, 
Choices.uniform(KindOfSequence.values()).choose(random).period(builder.topologyChangeIntervalNanos,
 random),
+        KindOfSequence topologyChangeSequence = 
Choices.uniform(KindOfSequence.values()).choose(random);
+        ClusterActions.Options options = new 
ClusterActions.Options(builder.topologyChangeLimit, 
topologyChangeSequence.period(builder.topologyChangeIntervalNanos, random),
                                                                     
Choices.random(random, builder.topologyChanges),
                                                                     minRf, 
initialRf, maxRf, null);
         simulation = factory.create(simulated, scheduler, cluster, options);
+
+        // Add remaining randomization tracking
+        randomizedConfig.put("network_scheduler", 
futureActionScheduler.getKind().toString());
+        randomizedConfig.put("runnable_scheduler", 
scheduler.getClass().getSimpleName());
+        randomizedConfig.put("topology_change_sequence", 
topologyChangeSequence.toString());
+
+        logger.warn("Seed 0x{} - Randomized config: {}", 
Long.toHexString(seed), randomizedConfig);
     }
 
     public synchronized void close() throws IOException
diff --git 
a/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedFutureActionScheduler.java
 
b/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedFutureActionScheduler.java
index f66999bb5a..99ebda73c7 100644
--- 
a/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedFutureActionScheduler.java
+++ 
b/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedFutureActionScheduler.java
@@ -67,6 +67,7 @@ public class SimulatedFutureActionScheduler implements 
FutureActionScheduler, To
     final int nodeCount;
     final RandomSource random;
     final SimulatedTime time;
+    final KindOfSequence kind;
 
     // TODO (feature): should we produce more than two simultaneous partitions?
     final BitSet isInDropPartition = new BitSet();
@@ -86,6 +87,7 @@ public class SimulatedFutureActionScheduler implements 
FutureActionScheduler, To
 
     public SimulatedFutureActionScheduler(KindOfSequence kind, int nodeCount, 
RandomSource random, SimulatedTime time, NetworkConfig network, SchedulerConfig 
scheduler)
     {
+        this.kind = kind;
         this.nodeCount = nodeCount;
         this.random = random;
         this.time = time;
@@ -196,4 +198,9 @@ public class SimulatedFutureActionScheduler implements 
FutureActionScheduler, To
         if (oldTopology == null || (newTopology.quorumRf < 
oldTopology.quorumRf && newTopology.quorumRf < isInDropPartition.cardinality()))
             recompute();
     }
+
+    public KindOfSequence getKind()
+    {
+        return kind;
+    }
 }
diff --git 
a/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
 
b/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
index f195f1b12d..006d39f8f7 100644
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
@@ -25,19 +25,21 @@ import org.junit.Test;
 
 import org.apache.cassandra.simulator.paxos.PaxosSimulationRunner;
 
+import static 
org.apache.cassandra.simulator.test.SimulationTestBase.DEFAULT_ITERATIONS;
+
 public class ShortPaxosSimulationTest
 {
     @Test
     public void simulationTest() throws IOException
     {
-        PaxosSimulationRunner.main(new String[] { "run", "-n", "3..6", "-t", 
"1000", "-c", "2", "--cluster-action-limit", "2", "-s", "30" });
+        PaxosSimulationRunner.main(new String[] { "run", "-n", "3..6", "-t", 
"1000", "-c", "2", "--cluster-action-limit", "2", "-s", "30", "--simulations", 
String.valueOf(DEFAULT_ITERATIONS) });
     }
 
     @Test
     @Ignore("fails due to OOM DirectMemory - unclear why")
     public void selfReconcileTest() throws IOException
     {
-        PaxosSimulationRunner.main(new String[] { "reconcile", "-n", "3..6", 
"-t", "1000", "-c", "2", "--cluster-action-limit", "2", "-s", "30", 
"--with-self" });
+        PaxosSimulationRunner.main(new String[] { "reconcile", "-n", "3..6", 
"-t", "1000", "-c", "2", "--cluster-action-limit", "2", "-s", "30", 
"--with-self", "--simulations", String.valueOf(DEFAULT_ITERATIONS) });
     }
 }
 
diff --git 
a/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
 
b/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
index 4cceb8fa3e..682fe9f167 100644
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
@@ -28,6 +28,9 @@ import java.util.function.Predicate;
 
 import com.google.common.collect.Iterators;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.cassandra.concurrent.ExecutorFactory;
 import org.apache.cassandra.distributed.Cluster;
 import org.apache.cassandra.distributed.api.ConsistencyLevel;
@@ -64,6 +67,7 @@ import org.apache.cassandra.utils.CloseableIterator;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static 
org.apache.cassandra.config.CassandraRelevantProperties.SIMULATOR_ITERATIONS;
 import static 
org.apache.cassandra.simulator.ActionSchedule.Mode.STREAM_LIMITED;
 import static org.apache.cassandra.simulator.ActionSchedule.Mode.UNLIMITED;
 import static org.apache.cassandra.simulator.ClusterSimulation.ISOLATE;
@@ -76,6 +80,9 @@ import static 
org.apache.cassandra.utils.Shared.Scope.SIMULATION;
 
 public class SimulationTestBase
 {
+    private static final Logger logger = 
LoggerFactory.getLogger(SimulationTestBase.class);
+    public static final int DEFAULT_ITERATIONS = SIMULATOR_ITERATIONS.getInt();
+
     static abstract class DTestClusterSimulation implements Simulation
     {
         final SimulatedSystems simulated;
@@ -140,15 +147,23 @@ public class SimulationTestBase
     public static void simulate(Function<DTestClusterSimulation, ActionList> 
init,
                                 Function<DTestClusterSimulation, ActionList> 
test,
                                 
Consumer<ClusterSimulation.Builder<DTestClusterSimulation>> configure) throws 
IOException
+    {
+        simulate(init, test, configure, 1);
+    }
+
+    public static void simulate(Function<DTestClusterSimulation, ActionList> 
init,
+                                Function<DTestClusterSimulation, ActionList> 
test,
+                                
Consumer<ClusterSimulation.Builder<DTestClusterSimulation>> configure,
+                                int iterations) throws IOException
     {
         SimulationRunner.beforeAll();
         long seed = System.currentTimeMillis();
-        RandomSource random = new RandomSource.Default();
-        random.reset(seed);
         class Factory extends ClusterSimulation.Builder<DTestClusterSimulation>
         {
             public ClusterSimulation<DTestClusterSimulation> create(long seed) 
throws IOException
             {
+                RandomSource random = new RandomSource.Default();
+                random.reset(seed);
                 return new ClusterSimulation<>(random, seed, 1, this,
                                                (c) -> {},
                                                (simulated, scheduler, cluster, 
options) -> new DTestClusterSimulation(simulated, scheduler, cluster) {
@@ -168,16 +183,21 @@ public class SimulationTestBase
 
         Factory factory = new Factory();
         configure.accept(factory);
-        try (ClusterSimulation<?> cluster = factory.create(seed))
+        for (int i = 0; i < iterations; i++)
         {
-            try
-            {
-                cluster.simulation.run();
-            }
-            catch (Throwable t)
+            long currentSeed = seed + i;
+            logger.info("Running iteration {} of {} with seed {}L", i + 1, 
iterations, currentSeed);
+            try (ClusterSimulation<?> cluster = factory.create(currentSeed))
             {
-                throw new AssertionError(String.format("Failed on seed %s", 
Long.toHexString(seed)),
-                                         t);
+                try
+                {
+                    cluster.simulation.run();
+                }
+                catch (Throwable t)
+                {
+                    throw new AssertionError(String.format("Failed on seed 
0x%s (base seed 0x%s + %d)",
+                                                           
Long.toHexString(currentSeed), Long.toHexString(seed), i), t);
+                }
             }
         }
     }
@@ -185,16 +205,41 @@ public class SimulationTestBase
     public static void simulate(IIsolatedExecutor.SerializableRunnable run,
                                 IIsolatedExecutor.SerializableRunnable check)
     {
-        simulate(new IIsolatedExecutor.SerializableRunnable[]{run},
-                 check);
+        simulate(new IIsolatedExecutor.SerializableRunnable[]{run}, check, 1);
+    }
+
+    public static void simulate(IIsolatedExecutor.SerializableRunnable run,
+                                IIsolatedExecutor.SerializableRunnable check,
+                                int iterations)
+    {
+        simulate(new IIsolatedExecutor.SerializableRunnable[]{run}, check, 
iterations);
     }
 
     public static void simulate(IIsolatedExecutor.SerializableRunnable[] 
runnables,
                                 IIsolatedExecutor.SerializableRunnable check)
+    {
+        simulate(runnables, check, 1);
+    }
+
+    public static void simulate(IIsolatedExecutor.SerializableRunnable[] 
runnables,
+                                IIsolatedExecutor.SerializableRunnable check,
+                                int iterations)
+    {
+        long seed = System.currentTimeMillis();
+        for (int i = 0; i < iterations; i++)
+        {
+            long currentSeed = seed + i;
+            logger.info("Running iteration {} of {} with seed {}L", i + 1, 
iterations, currentSeed);
+            simulate(runnables, check, currentSeed);
+        }
+    }
+
+    public static void simulate(IIsolatedExecutor.SerializableRunnable[] 
runnables,
+                                IIsolatedExecutor.SerializableRunnable check,
+                                long seed)
     {
         Failures failures = new Failures();
         RandomSource random = new RandomSource.Default();
-        long seed = System.currentTimeMillis();
         System.out.println("Using seed: " + seed);
         random.reset(seed);
         SimulatedTime time = new SimulatedTime(1, random, 1577836800000L /*Jan 
1st UTC*/, new LongRange(1, 100, MILLISECONDS, NANOSECONDS),
diff --git 
a/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
 
b/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
index cf8fe1b25f..1872bed12f 100644
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
@@ -55,7 +55,8 @@ public class TrivialSimulationTest extends SimulationTestBase
                  (config) -> config
                              .threadCount(10)
                              .nodes(3, 3)
-                             .dcs(1, 1));
+                             .dcs(1, 1),
+                 DEFAULT_ITERATIONS);
     }
 
     @Test
@@ -80,13 +81,13 @@ public class TrivialSimulationTest extends 
SimulationTestBase
                          });
                      }
                  }),
-                 () -> {});
+                 () -> {}, DEFAULT_ITERATIONS);
     }
 
     @Test
     public void identityHashMapTest()
     {
         simulate(arr(() -> new IdentityHashMap<>().put(1, 1)),
-                 () -> {});
+                 () -> {}, DEFAULT_ITERATIONS);
     }
 }


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

Reply via email to