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

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

commit 87d79f30a0f42bd3b3105145376450eb7b47a073
Merge: cdb67f62ff ddfba19f9e
Author: Caleb Rackliffe <[email protected]>
AuthorDate: Wed Mar 11 16:06:29 2026 -0500

    Merge branch 'cassandra-5.0' into trunk
    
    * cassandra-5.0:
      Randomize Memtable type/allocation type and SSTable format in Simulator 
tests

 .../config/CassandraRelevantProperties.java        |   2 +-
 .../cassandra/simulator/ClusterSimulation.java     | 117 ++++++++++++++++++++-
 .../systems/SimulatedFutureActionScheduler.java    |   7 ++
 .../simulator/test/ShortPaxosSimulationTest.java   |   8 +-
 .../simulator/test/SimulationTestBase.java         |  71 ++++++++++---
 .../simulator/test/TrivialSimulationTest.java      |   9 +-
 6 files changed, 189 insertions(+), 25 deletions(-)

diff --cc src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
index 9184b78395,0c81d63afb..05875726e3
--- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
+++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java
@@@ -528,11 -480,8 +528,12 @@@ public enum CassandraRelevantPropertie
      
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"),
 +    SIMULATOR_SEED("cassandra.simulator.seed"),
 +    SIMULATOR_STARTED("cassandra.simulator.started"),
      SIZE_RECORDER_INTERVAL("cassandra.size_recorder_interval", "300"),
 +    SKIP_AUTH_SETUP("cassandra.skip_auth_setup", "false"),
 +    SKIP_GC_INSPECTOR("cassandra.skip_gc_inspector", "false"),
  
      /**
       * Do not try to calculate optimal streaming candidates. This can take a 
lot of time in some configs specially
@@@ -559,7 -502,7 +560,6 @@@
      
SNAPSHOT_MIN_ALLOWED_TTL_SECONDS("cassandra.snapshot.min_allowed_ttl_seconds", 
"60"),
      SSL_ENABLE("ssl.enable"),
      SSL_STORAGE_PORT("cassandra.ssl_storage_port"),
--    SSTABLE_FORMAT_DEFAULT("cassandra.sstable.format.default"),
      START_GOSSIP("cassandra.start_gossip", "true"),
      START_NATIVE_TRANSPORT("cassandra.start_native_transport"),
      STORAGE_DIR("cassandra.storagedir"),
diff --cc 
test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
index ada4e51a34,1bc900a13f..8925c180ae
--- a/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
+++ b/test/simulator/main/org/apache/cassandra/simulator/ClusterSimulation.java
@@@ -22,8 -22,9 +22,9 @@@ import java.io.IOException
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.util.ArrayList;
 -import java.util.Arrays;
 +import java.util.Collections;
  import java.util.EnumMap;
+ import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.TreeMap;
@@@ -38,7 -39,9 +39,10 @@@ 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.auth.PasswordSaltSupplier;
  import org.apache.cassandra.concurrent.ExecutorFactory;
  import org.apache.cassandra.config.CassandraRelevantProperties;
  import org.apache.cassandra.config.ParameterizedClass;
@@@ -121,11 -117,8 +125,13 @@@ import static org.apache.cassandra.util
  @SuppressWarnings("RedundantCast")
  public class ClusterSimulation<S extends Simulation> implements AutoCloseable
  {
+     private static final Logger logger = 
LoggerFactory.getLogger(ClusterSimulation.class);
+ 
 +    static
 +    {
 +        
CassandraRelevantProperties.TEST_STORAGE_COMPATIBILITY_MODE.setEnum(StorageCompatibilityMode.NONE);
 +    }
 +
      public static final Class<?>[] SHARE = new Class[]
                                          {
                                              AsyncFunction.class,
@@@ -217,34 -195,10 +223,37 @@@
          protected HeapPool.Logged.Listener memoryListener;
          protected SimulatedTime.Listener timeListener = (i1, i2) -> {};
          protected LongConsumer onThreadLocalRandomCheck;
 +        protected String transactionalMode = "off";
 +        protected FutureActionSchedulerFactory futureActionSchedulerFactory;
 +        protected PerVerbFutureActionSchedulersFactory 
perVerbFutureActionSchedulersFactory;
+         protected String memtableType = null;
+         protected String memtableAllocationType = null;
+         protected String sstableFormat = null;
  
 +        public Builder<S> failures(Failures failures)
 +        {
 +            this.failures = failures;
 +            return this;
 +        }
 +
 +        public Builder<S> writeTimeoutNanos(long nanos)
 +        {
 +            this.writeTimeoutNanos = nanos;
 +            return this;
 +        }
 +
 +        public Builder<S> readTimeoutNanos(long nanos)
 +        {
 +            this.readTimeoutNanos = nanos;
 +            return this;
 +        }
 +
 +        public Builder<S> requestTimeoutNanos(long nanos)
 +        {
 +            this.requestTimeoutNanos = nanos;
 +            return this;
 +        }
 +
          public Debug debug()
          {
              return debug;
@@@ -612,17 -526,24 +621,35 @@@
              return this;
          }
  
 +        public Builder<S> transactionalMode(String mode)
 +        {
 +            this.transactionalMode = mode;
 +            return this;
 +        }
 +
 +        public TransactionalMode transactionalMode()
 +        {
 +            return TransactionalMode.fromString(transactionalMode);
 +        }
 +
+         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;
      }
  
@@@ -767,8 -682,68 +794,67 @@@
  
          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);
@@@ -778,29 -753,15 +864,28 @@@
          });
  
          Predicate<String> sharedClassPredicate = 
getSharedClassPredicate(ISOLATE, SHARE, ANY, SIMULATION);
 -        InterceptAsClassTransformer interceptClasses = new 
InterceptAsClassTransformer(builder.monitorDelayChance.asSupplier(random), 
builder.nemesisChance.asSupplier(random), NemesisFieldSelectors.get(), 
ClassLoader.getSystemClassLoader(), sharedClassPredicate.negate());
 +        DeterministicChanceSupplier monitorDelayChance; {
 +            long monitorDelayChanceSeed = random.uniform(0, Long.MAX_VALUE);
 +            monitorDelayChance = hash -> {
 +                RandomSource subRandom = new RandomSource.Default();
 +                subRandom.reset(monitorDelayChanceSeed * 31 + hash);
 +                return builder.monitorDelayChance.asSupplier(subRandom);
 +            };
 +        }
 +        DeterministicChanceSupplier nemesisChance; {
 +            long nemesisChanceSeed = random.uniform(0, Long.MAX_VALUE);
 +            nemesisChance = hash -> {
 +                RandomSource subRandom = new RandomSource.Default();
 +                subRandom.reset(nemesisChanceSeed * 31 + hash);
 +                return builder.nemesisChance.asSupplier(subRandom);
 +            };
 +        }
 +
 +        InterceptAsClassTransformer interceptClasses = new 
InterceptAsClassTransformer(monitorDelayChance, nemesisChance, 
NemesisFieldSelectors.get(), ClassLoader.getSystemClassLoader(), 
sharedClassPredicate.negate());
          threadLocalRandomCheck = new 
ThreadLocalRandomCheck(builder.onThreadLocalRandomCheck);
  
 -        Failures failures = new Failures();
 +        Failures failures = builder.failures;
          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"))
                           .withSharedClasses(sharedClassPredicate)
@@@ -812,17 -772,26 +897,32 @@@
                                     .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("accord.queue_submission_model", 
"ASYNC")
 +                                   .set("accord.range_migration", "explicit")
 +                                   .set("disk_access_mode", "standard")
                                     .set("failure_detector", 
SimulatedFailureDetector.Instance.class.getName())
 -                                   .set("commitlog_sync", "batch");
 +                                   .set("commitlog_compression", new 
ParameterizedClass(LZ4Compressor.class.getName(), emptyMap()))
 +                                   .set("commitlog_sync", "batch")
 +                                   .set("accord.journal.flush_mode", "BATCH")
-                                    .set("accord.command_store_shard_count", 
"4");
++                                   .set("accord.command_store_shard_count", 
"4")
++                                   .set("sstable", Map.of("selected_format", 
sstableFormat));
+ 
+                              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)
                               {
@@@ -913,28 -876,23 +1013,37 @@@
          DirectStreamingConnectionFactory.setup(cluster);
          delivery = new SimulatedMessageDelivery(cluster);
          failureDetector = new SimulatedFailureDetector(cluster);
 -        SimulatedFutureActionScheduler futureActionScheduler = 
builder.futureActionScheduler(numOfNodes, time, random);
 -        simulated = new SimulatedSystems(random, time, delivery, execution, 
ballots, failureDetector, snitch, futureActionScheduler, builder.debug, 
failures);
 -        simulated.register(futureActionScheduler);
 -
 -        RunnableActionScheduler scheduler = 
builder.schedulerFactory.create(random);
 +        FutureActionScheduler futureActionScheduler = 
builder.futureActionScheduler(numOfNodes, time, random);
 +        Map<Verb, FutureActionScheduler> perVerbFutureActionScheduler = 
builder.perVerbFutureActionSchedulers(numOfNodes, time, random, 
futureActionScheduler);
 +        simulated = new SimulatedSystems(random, time, delivery, execution, 
ballots, failureDetector, snitch, futureActionScheduler, 
perVerbFutureActionScheduler, builder.debug, failures);
 +        if (futureActionScheduler instanceof SimulatedFutureActionScheduler)
 +            simulated.register((SimulatedFutureActionScheduler) 
futureActionScheduler);
 +
 +        scheduler = builder.schedulerFactory.create(random);
 +        // TODO (required): we aren't passing paxos variant change parameter 
anymore
-         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);
++        options = new ClusterActions.Options(builder.topologyChangeLimit, 
topologyChangeSequence.period(builder.topologyChangeIntervalNanos, random),
 +                                             Choices.random(random, 
builder.topologyChanges),
 +                                             builder.consensusChangeLimit, 
Choices.uniform(KindOfSequence.values()).choose(random).period(builder.consensusChangeIntervalNanos,
 random),
 +                                             Choices.random(random, 
builder.consensusChanges),
 +                                             minRf, initialRf, maxRf, null);
 +        this.factory = factory;
  
+         // Add remaining randomization tracking
 -        randomizedConfig.put("network_scheduler", 
futureActionScheduler.getKind().toString());
++        if (futureActionScheduler instanceof SimulatedFutureActionScheduler)
++            randomizedConfig.put("network_scheduler", 
((SimulatedFutureActionScheduler) 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);
++
 +        // during cluster shutdown ignore all failures as there is no reason 
to track them
 +        onPreShutdown.add(() -> {simulated.failures.ignoreFailures(); return 
null;});
 +    }
 +
 +    public S simulation()
 +    {
 +        return factory.create(simulated, scheduler, cluster, options);
      }
  
      public synchronized void close() throws IOException
diff --cc 
test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
index 4f281dd7e8,006d39f8f7..7eb6584a6a
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/ShortPaxosSimulationTest.java
@@@ -22,99 -25,21 +22,103 @@@ import org.junit.Test
  
  import org.apache.cassandra.simulator.paxos.PaxosSimulationRunner;
  
+ import static 
org.apache.cassandra.simulator.test.SimulationTestBase.DEFAULT_ITERATIONS;
+ 
 +/**
 + * In order to run these tests in your IDE, you need to first build a 
simulator jara
 + *
 + *    ant simulator-jars
 + *
 + * And then run your test using the following settings (omit add-* if you are 
running on jdk8):
 + *
 +          -Dstorage-config=$MODULE_DIR$/test/conf
 +          -Djava.awt.headless=true
 +          -javaagent:$MODULE_DIR$/lib/jamm-0.4.0.jar
 +          -ea
 +          -Dcassandra.debugrefcount=true
 +          -Xss384k
 +          -XX:SoftRefLRUPolicyMSPerMB=0
 +          -XX:ActiveProcessorCount=2
 +          -XX:HeapDumpPath=build/test
 +          -Dcassandra.test.driver.connection_timeout_ms=10000
 +          -Dcassandra.test.driver.read_timeout_ms=24000
 +          -Dcassandra.memtable_row_overhead_computation_step=100
 +          -Dcassandra.test.use_prepared=true
 +          -Dcassandra.test.sstableformatdevelopment=true
 +          -Djava.security.egd=file:/dev/urandom
 +          -Dcassandra.testtag=.jdk11
 +          -Dcassandra.keepBriefBrief=true
 +          -Dcassandra.allow_simplestrategy=true
 +          -Dcassandra.strict.runtime.checks=true
 +          
-Dcassandra.reads.thresholds.coordinator.defensive_checks_enabled=true
 +          -Dcassandra.test.flush_local_schema_changes=false
 +          -Dcassandra.test.messagingService.nonGracefulShutdown=true
 +          -Dcassandra.use_nix_recursive_delete=true
 +          -Dcie-cassandra.disable_schema_drop_log=true
 +          
-Dlogback.configurationFile=file://$MODULE_DIR$/test/conf/logback-simulator.xml
 +          -Dcassandra.ring_delay_ms=10000
 +          -Dcassandra.tolerate_sstable_size=true
 +          -Dcassandra.skip_sync=true
 +          -Dcassandra.debugrefcount=false
 +          -Dcassandra.test.simulator.determinismcheck=strict
 +          -Dcassandra.test.simulator.print_asm=none
 +          -javaagent:$MODULE_DIR$/build/test/lib/jars/simulator-asm.jar
 +          
-Xbootclasspath/a:$MODULE_DIR$/build/test/lib/jars/simulator-bootstrap.jar
 +          -XX:ActiveProcessorCount=4
 +          -XX:-TieredCompilation
 +          -XX:-BackgroundCompilation
 +          -XX:CICompilerCount=1
 +          -XX:Tier4CompileThreshold=1000
 +          -XX:ReservedCodeCacheSize=256M
 +          -Xmx16G
 +          --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
 +          --add-exports java.base/jdk.internal.ref=ALL-UNNAMED
 +          --add-exports java.base/sun.nio.ch=ALL-UNNAMED
 +          --add-exports 
java.management.rmi/com.sun.jmx.remote.internal.rmi=ALL-UNNAMED
 +          --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
 +          --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED
 +          --add-exports java.sql/java.sql=ALL-UNNAMED
 +          --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED
 +          --add-opens java.base/java.lang.module=ALL-UNNAMED
 +          --add-opens java.base/java.net=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.ref=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.math=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.module=ALL-UNNAMED
 +          --add-opens java.base/jdk.internal.util.jar=ALL-UNNAMED
 +          --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED
 +          --add-opens jdk.management.jfr/jdk.management.jfr=ALL-UNNAMED
 +          --add-opens java.desktop/com.sun.beans.introspect=ALL-UNNAMED
 + */
  public class ShortPaxosSimulationTest
  {
      @Test
 -    public void simulationTest() throws IOException
 +    public void simulationTest()
      {
 -        PaxosSimulationRunner.main(new String[] { "run", "-n", "3..6", "-t", 
"1000", "-c", "2", "--cluster-action-limit", "2", "-s", "30", "--simulations", 
String.valueOf(DEFAULT_ITERATIONS) });
 +        PaxosSimulationRunner.executeWithExceptionThrowing(new String[] { 
"run",
 +                                                                          
"--variant", "v2",
 +                                                                          
"-n", "3..6",
 +                                                                          
"-t", "1000",
 +                                                                          
"-c", "2",
 +                                                                          
"--cluster-action-limit", "2",
-                                                                           
"-s", "30" });
++                                                                          
"-s", "30",
++                                                                          
"--simulations", String.valueOf(DEFAULT_ITERATIONS) });
      }
  
      @Test
 -    @Ignore("fails due to OOM DirectMemory - unclear why")
 -    public void selfReconcileTest() throws IOException
 +    public void selfReconcileTest()
      {
 -        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) });
 +        PaxosSimulationRunner.executeWithExceptionThrowing(new String[] { 
"reconcile",
 +                                                                          
"-n", "3..6",
 +                                                                          
"-t", "1000",
 +                                                                          
"-c", "2",
 +                                                                          
"--cluster-action-limit", "2",
 +                                                                          
"-s", "30",
 +                                                                          
"--with-self",
 +                                                                          
"--with-rng", "0",
-                                                                           
"--with-time", "0",});
++                                                                          
"--with-time", "0",
++                                                                          
"--simulations", String.valueOf(DEFAULT_ITERATIONS) });
      }
  }
  
diff --cc 
test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
index 195a4f23a5,682fe9f167..6c87b01e78
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/SimulationTestBase.java
@@@ -78,13 -65,10 +78,14 @@@ import org.apache.cassandra.utils.Clock
  import org.apache.cassandra.utils.CloseableIterator;
  
  import static java.util.concurrent.TimeUnit.MILLISECONDS;
 +import static java.util.concurrent.TimeUnit.MINUTES;
  import static java.util.concurrent.TimeUnit.NANOSECONDS;
  import static java.util.concurrent.TimeUnit.SECONDS;
 +import static 
org.apache.cassandra.config.CassandraRelevantProperties.CLOCK_GLOBAL;
 +import static 
org.apache.cassandra.config.CassandraRelevantProperties.CLOCK_MONOTONIC_APPROX;
 +import static 
org.apache.cassandra.config.CassandraRelevantProperties.CLOCK_MONOTONIC_PRECISE;
+ 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.TIME_LIMITED;
  import static org.apache.cassandra.simulator.ActionSchedule.Mode.UNLIMITED;
  import static org.apache.cassandra.simulator.ClusterSimulation.ISOLATE;
  import static org.apache.cassandra.simulator.ClusterSimulation.SHARE;
@@@ -96,29 -80,20 +97,31 @@@ import static org.apache.cassandra.util
  
  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
 +    @BeforeClass
 +    public static void beforeAll()
 +    {
 +        // Disallow time on the bootstrap classloader
 +        for (CassandraRelevantProperties property : 
Arrays.asList(CLOCK_GLOBAL, CLOCK_MONOTONIC_APPROX, CLOCK_MONOTONIC_PRECISE))
 +            
property.setString("org.apache.cassandra.simulator.systems.SimulatedTime$Delegating");
 +        try { Clock.Global.nanoTime(); } catch (IllegalStateException e) {} 
// make sure static initializer gets called
 +    }
 +
 +    // Don't use loggers before invoking simulator it messes up 
initialization order
 +//    private static final Logger logger = 
LoggerFactory.getLogger(Logger.class);
 +
 +
 +    static abstract class SimpleSimulation extends AbstractSimulation
      {
 -        final SimulatedSystems simulated;
 -        final RunnableActionScheduler scheduler;
 -        final Cluster cluster;
 +        protected SimpleSimulation(SimulatedSystems simulated, 
RunnableActionScheduler scheduler, Cluster cluster)
 +        {
 +            super(simulated, scheduler, cluster);
 +        }
  
 -        public DTestClusterSimulation(SimulatedSystems simulated, 
RunnableActionScheduler scheduler, Cluster cluster)
 +        protected SimpleSimulation(SimulatedSystems simulated, 
RunnableActionScheduler scheduler, Cluster cluster, ClusterActions.Options 
options)
          {
 -            this.simulated = simulated;
 -            this.scheduler = scheduler;
 -            this.cluster = cluster;
 +            super(simulated, scheduler, cluster, options);
          }
  
          public Action executeQuery(int node, String query, ConsistencyLevel 
cl, Object... bindings)
@@@ -198,157 -144,62 +201,180 @@@
          }
      }
  
 -    public static void simulate(Function<DTestClusterSimulation, ActionList> 
init,
 -                                Function<DTestClusterSimulation, ActionList> 
test,
 -                                
Consumer<ClusterSimulation.Builder<DTestClusterSimulation>> configure) throws 
IOException
 +    static class DTestClusterSimulationBuilder extends 
ClusterSimulation.Builder<SimpleSimulation>
      {
 -        simulate(init, test, configure, 1);
 +        protected final Function<SimpleSimulation, ActionList> init;
 +        protected final Function<SimpleSimulation, ActionList> test;
 +        protected final Function<SimpleSimulation, ActionList> teardown;
 +        protected final BiConsumer<RandomSource, IInstanceConfig> 
configUpdater;
 +
 +        DTestClusterSimulationBuilder(Function<SimpleSimulation, ActionList> 
init,
 +                                      Function<SimpleSimulation, ActionList> 
test,
 +                                      Function<SimpleSimulation, ActionList> 
teardown,
 +                                      BiConsumer<RandomSource, 
IInstanceConfig> configUpdater)
 +        {
 +            this.init = init;
 +            this.test = test;
 +            this.teardown = teardown;
 +            this.configUpdater = configUpdater;
 +        }
 +
 +        public ClusterSimulation<SimpleSimulation> create(long seed) throws 
IOException
 +        {
 +            RandomSource random = new RandomSource.Default();
 +            random.reset(seed);
 +
 +            return new ClusterSimulation<>(random, seed, 1, this,
 +                                           c -> configUpdater.accept(random, 
c),
 +                                           (simulated, scheduler, cluster, 
options) -> new SimpleSimulation(simulated, scheduler, cluster)
 +                                           {
 +                                               protected ActionList 
initialize()
 +                                               {
 +                                                   return init.apply(this);
 +                                               }
 +
 +                                               protected ActionList teardown()
 +                                               {
 +                                                   return 
teardown.apply(this);
 +                                               }
 +
 +                                               protected ActionList execute()
 +                                               {
 +                                                   return test.apply(this);
 +                                               }
 +                                           });
 +        }
      }
  
 -    public static void simulate(Function<DTestClusterSimulation, ActionList> 
init,
 -                                Function<DTestClusterSimulation, ActionList> 
test,
 -                                
Consumer<ClusterSimulation.Builder<DTestClusterSimulation>> configure,
 -                                int iterations) throws IOException
 +    static void simulate(Function<SimpleSimulation, ActionList> init,
 +                         Function<SimpleSimulation, ActionList> test,
 +                         Function<SimpleSimulation, ActionList> teardown,
 +                         
Consumer<ClusterSimulation.Builder<SimpleSimulation>> configure) throws 
IOException
      {
 -        SimulationRunner.beforeAll();
 -        long seed = System.currentTimeMillis();
 -        class Factory extends 
ClusterSimulation.Builder<DTestClusterSimulation>
 +        simulate(init, test, teardown, configure, (i1, i2) -> {});
 +    }
 +
++    static void simulate(Function<SimpleSimulation, ActionList> init,
++                         Function<SimpleSimulation, ActionList> test,
++                         Function<SimpleSimulation, ActionList> teardown,
++                         
Consumer<ClusterSimulation.Builder<SimpleSimulation>> configure,
++                         int iterations) throws IOException
++    {
++        simulate(System::currentTimeMillis, new 
DTestClusterSimulationBuilder(init, test, teardown, (i1, i2) -> {}),
++                 configure, iterations);
++    }
++
 +    @SuppressWarnings("unused")
 +    static void simulate(long seed,
 +                         Function<SimpleSimulation, ActionList> init,
 +                         Function<SimpleSimulation, ActionList> test,
 +                         Function<SimpleSimulation, ActionList> teardown,
 +                         
Consumer<ClusterSimulation.Builder<SimpleSimulation>> configure) throws 
IOException
 +    {
 +        simulate(seed, init, test, teardown, configure, (i1, i2) -> {});
 +    }
 +
 +    static void simulate(Function<SimpleSimulation, ActionList> init,
 +                         Function<SimpleSimulation, ActionList> test,
 +                         Function<SimpleSimulation, ActionList> teardown,
 +                         
Consumer<ClusterSimulation.Builder<SimpleSimulation>> configure,
 +                         BiConsumer<RandomSource, IInstanceConfig> 
configUpdater) throws IOException
 +    {
 +        simulate(new DTestClusterSimulationBuilder(init, test, teardown, 
configUpdater),
 +                 configure);
 +    }
 +
 +    @SuppressWarnings("unused")
 +    static void simulate(long seed,
 +                         Function<SimpleSimulation, ActionList> init,
 +                         Function<SimpleSimulation, ActionList> test,
 +                         Function<SimpleSimulation, ActionList> teardown,
 +                         
Consumer<ClusterSimulation.Builder<SimpleSimulation>> configure,
 +                         BiConsumer<RandomSource, IInstanceConfig> 
configUpdater) throws IOException
 +    {
 +        simulate(() -> seed, new DTestClusterSimulationBuilder(init, test, 
teardown, configUpdater),
 +                configure);
 +    }
 +
 +    public static <T extends Simulation> void 
simulate(ClusterSimulation.Builder<T> factory,
 +                                                       
Consumer<ClusterSimulation.Builder<T>> configure) throws IOException
 +    {
 +        simulate(System::currentTimeMillis, factory, configure);
 +    }
 +
 +    public static <T extends Simulation> void simulate(long seed, 
ClusterSimulation.Builder<T> factory) throws IOException
 +    {
 +        simulate(() -> seed, factory, i ->{});
 +    }
 +
 +    public static <T extends Simulation> void 
simulate(ClusterSimulation.SimulationFactory<T> factory) throws IOException
 +    {
 +        simulate(System.currentTimeMillis(), factory);
 +    }
 +
 +    public static <T extends Simulation> void simulate(long seed, 
ClusterSimulation.SimulationFactory<T> factory) throws IOException
 +    {
 +        simulate(seed, factory, b -> {});
 +    }
 +
 +    public static <T extends Simulation> void 
simulate(ClusterSimulation.SimulationFactory<T> factory, 
Consumer<ClusterSimulation.Builder<T>> configure) throws IOException
 +    {
 +        simulate(System.currentTimeMillis(), factory, configure);
 +    }
 +
 +    public static <T extends Simulation> void simulate(long seed, 
ClusterSimulation.SimulationFactory<T> factory, 
Consumer<ClusterSimulation.Builder<T>> configure) throws IOException
 +    {
 +        BasicSimulationBuilder<T> builder = new BasicSimulationBuilder<>()
          {
 -            public ClusterSimulation<DTestClusterSimulation> create(long 
seed) throws IOException
 +            @Override
 +            T create(SimulatedSystems simulated, RunnableActionScheduler 
scheduler, Cluster cluster, ClusterActions.Options options)
              {
 -                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) {
 -
 -                                                   protected ActionList 
initialize()
 -                                                   {
 -                                                       return 
init.apply(this);
 -                                                   }
 -
 -                                                   protected ActionList 
execute()
 -                                                   {
 -                                                       return 
test.apply(this);
 -                                                   }
 -                                               });
 +                return factory.create(simulated, scheduler, cluster, options);
              }
 -        }
 +        };
 +        simulate(() -> seed, builder, configure);
 +    }
 +
 +    public static <T extends Simulation> void simulate(LongSupplier seedGen,
 +                                                       
ClusterSimulation.Builder<T> factory,
 +                                                       
Consumer<ClusterSimulation.Builder<T>> configure) throws IOException
++    {
++        simulate(seedGen, factory, configure, 1);
++    }
+ 
 -        Factory factory = new Factory();
++    public static <T extends Simulation> void simulate(LongSupplier seedGen,
++                                                       
ClusterSimulation.Builder<T> factory,
++                                                       
Consumer<ClusterSimulation.Builder<T>> configure,
++                                                       int iterations) throws 
IOException
 +    {
 +        SimulationRunner.beforeAll();
 +        long seed = seedGen.getAsLong();
 +        // Development seed:
 +        //long seed = 1687184561194L;
 +        System.out.printf("Simulation seed: %dL%n", seed);
          configure.accept(factory);
-         try (ClusterSimulation<?> cluster = factory.create(seed))
+         for (int i = 0; i < iterations; i++)
          {
-             try (Simulation simulation = cluster.simulation())
+             long currentSeed = seed + i;
 -            logger.info("Running iteration {} of {} with seed {}L", i + 1, 
iterations, currentSeed);
++            System.out.printf("Running iteration %d of %d with seed %dL%n", i 
+ 1, iterations, currentSeed);
+             try (ClusterSimulation<?> cluster = factory.create(currentSeed))
              {
-                 simulation.run();
 -                try
++                try (Simulation simulation = cluster.simulation())
+                 {
 -                    cluster.simulation.run();
++                    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);
++                    throw new SimulationException(currentSeed, t);
+                 }
              }
 +            catch (Throwable t)
 +            {
-                 throw new SimulationException(seed, t);
++                if (t instanceof SimulationException)
++                    throw t;
++                throw new SimulationException(currentSeed, t);
 +            }
          }
-         catch (Throwable t)
-         {
-             if (t instanceof SimulationException)
-                 throw t;
-             throw new SimulationException(seed, t);
-         }
      }
  
      public static void simulate(IIsolatedExecutor.SerializableRunnable run,
@@@ -361,7 -218,20 +393,20 @@@
      public static void simulate(IIsolatedExecutor.SerializableRunnable[] 
runnables,
                                  IIsolatedExecutor.SerializableRunnable check)
      {
-         simulate(runnables, check, System.currentTimeMillis());
+         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);
++            System.out.printf("Running iteration %d of %d with seed %dL%n", i 
+ 1, iterations, currentSeed);
+             simulate(runnables, check, currentSeed);
+         }
      }
  
      public static void simulate(IIsolatedExecutor.SerializableRunnable[] 
runnables,
diff --cc 
test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
index 404606c1a4,1872bed12f..8d94c7a2c3
--- 
a/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
+++ 
b/test/simulator/test/org/apache/cassandra/simulator/test/TrivialSimulationTest.java
@@@ -34,13 -38,7 +34,13 @@@ import static org.apache.cassandra.simu
  
  public class TrivialSimulationTest extends SimulationTestBase
  {
 +    @Test
 +    public void identityHashMapTest()
 +    {
 +        simulate(arr(() -> new IdentityHashMap<>().put(1, 1)),
-                  () -> {});
++                 () -> {}, DEFAULT_ITERATIONS);
 +    }
 +
      @Test
      public void trivialTest() throws IOException // for 
demonstration/experiment purposes
      {
@@@ -81,8 -81,13 +82,6 @@@
                           });
                       }
                   }),
-                  () -> {});
+                  () -> {}, 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