use of org.apache.cassandra.simulator.Action in project cassandra by apache.
the class SimulationTestBase method simulate.
public static void simulate(IIsolatedExecutor.SerializableRunnable[] runnables, IIsolatedExecutor.SerializableRunnable check) {
RandomSource random = new RandomSource.Default();
SimulatedWaits waits = new SimulatedWaits(random);
SimulatedTime time = new SimulatedTime(random, 1577836800000L, /*Jan 1st UTC*/
new LongRange(1, 100, MILLISECONDS, NANOSECONDS), UNIFORM, UNIFORM.period(new LongRange(10L, 60L, SECONDS, NANOSECONDS), random));
SimulatedExecution execution = new SimulatedExecution();
InstanceClassLoader classLoader = new InstanceClassLoader(1, 1, AbstractCluster.CURRENT_VERSION.classpath, Thread.currentThread().getContextClassLoader(), AbstractCluster.getSharedClassPredicate(ISOLATE, SHARE, ANY, SIMULATION), new InterceptClasses(() -> 1.0f, () -> 1.0f, NemesisFieldSelectors.get())::apply);
ThreadGroup tg = new ThreadGroup("test");
InterceptorOfGlobalMethods interceptorOfGlobalMethods = waits.interceptGlobalMethods(classLoader);
InterceptingExecutorFactory factory = execution.factory(interceptorOfGlobalMethods, classLoader, tg);
IsolatedExecutor.transferAdhoc((IIsolatedExecutor.SerializableConsumer<ExecutorFactory>) ExecutorFactory.Global::unsafeSet, classLoader).accept(factory);
IsolatedExecutor.transferAdhoc((IIsolatedExecutor.SerializableBiConsumer<InterceptorOfGlobalMethods, IntSupplier>) InterceptorOfGlobalMethods.Global::unsafeSet, classLoader).accept(interceptorOfGlobalMethods, () -> {
if (InterceptibleThread.isDeterministic())
throw failWithOOM();
return random.uniform(Integer.MIN_VALUE, Integer.MAX_VALUE);
});
SimulatedSystems simulated = new SimulatedSystems(random, time, waits, null, execution, null, null, null, new FutureActionScheduler() {
@Override
public Deliver shouldDeliver(int from, int to) {
return Deliver.DELIVER;
}
@Override
public long messageDeadlineNanos(int from, int to) {
return 0;
}
@Override
public long messageTimeoutNanos(long expiresAfterNanos) {
return 0;
}
@Override
public long messageFailureNanos(int from, int to) {
return 0;
}
@Override
public long schedulerDelayNanos() {
return 0;
}
}, new Debug(), new Failures());
RunnableActionScheduler runnableScheduler = new RunnableActionScheduler.RandomUniform(random);
Action entrypoint = new Action("entrypoint", Action.Modifiers.NONE, Action.Modifiers.NONE) {
protected ActionList performSimple() {
Action[] actions = new Action[runnables.length];
for (int i = 0; i < runnables.length; i++) actions[i] = toAction(runnables[i], classLoader, factory, simulated);
return ActionList.of(actions);
}
};
ActionSchedule testSchedule = new ActionSchedule(simulated.time, simulated.futureScheduler, () -> 0, new Work(UNLIMITED, runnableScheduler, Collections.singletonList(ActionList.of(entrypoint))));
Iterators.advance(testSchedule, Integer.MAX_VALUE);
ActionSchedule checkSchedule = new ActionSchedule(simulated.time, simulated.futureScheduler, () -> 0, new Work(UNLIMITED, runnableScheduler, Collections.singletonList(ActionList.of(toAction(check, classLoader, factory, simulated)))));
Iterators.advance(checkSchedule, Integer.MAX_VALUE);
}
use of org.apache.cassandra.simulator.Action in project cassandra by apache.
the class SimulatedAction method applyToMessage.
Action applyToMessage(IInvokableInstance from, IInvokableInstance to, IMessage message) {
Executor executor = to.executorFor(message.verb());
if (executor instanceof ImmediateExecutor)
executor = to.executor();
InterceptedExecution.InterceptedTaskExecution task = new InterceptedRunnableExecution((InterceptingExecutor) executor, () -> to.receiveMessageWithInvokingThread(message));
Verb verb = Verb.fromId(message.verb());
Modifiers self = verbModifiers.getOrDefault(verb, NONE);
int fromNum = from.config().num();
int toNum = to.config().num();
Deliver deliver;
if (is(Modifier.RELIABLE) || self.is(Modifier.RELIABLE))
deliver = DELIVER;
else
deliver = simulated.futureScheduler.shouldDeliver(fromNum, toNum);
Action action;
switch(deliver) {
default:
throw new AssertionError();
case DELIVER:
{
Object description = lazy(() -> String.format("%s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), message.from(), to.broadcastAddress()));
OrderOn orderOn = task.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, verb, task);
action.setDeadline(simulated.futureScheduler.messageDeadlineNanos(fromNum, toNum));
break;
}
case FAILURE:
case TIMEOUT:
{
task.cancel();
self = DROP.with(self);
InetSocketAddress failedOn;
IInvokableInstance notify;
if (verb.isResponse()) {
failedOn = from.broadcastAddress();
notify = to;
} else {
failedOn = to.broadcastAddress();
notify = from;
}
InterceptedExecution.InterceptedTaskExecution failTask = new InterceptedRunnableExecution((InterceptingExecutor) notify.executorFor(verb.id), () -> notify.unsafeApplyOnThisThread((socketAddress, id, isTimeout) -> {
InetAddressAndPort address = InetAddressAndPort.getByAddress(socketAddress);
RequestCallbacks.CallbackInfo callback = instance().callbacks.remove(id, address);
if (callback != null) {
RequestCallback<?> invokeOn = (RequestCallback<?>) callback.callback;
RequestFailureReason reason = isTimeout ? RequestFailureReason.TIMEOUT : RequestFailureReason.UNKNOWN;
invokeOn.onFailure(address, reason);
}
return null;
}, failedOn, message.id(), deliver == TIMEOUT));
Object description = (lazy(() -> String.format("Report Timeout of %s(%d) from %s to %s", Verb.fromId(message.verb()), message.id(), failedOn, notify.broadcastAddress())));
OrderOn orderOn = failTask.executor.orderAppliesAfterScheduling();
action = applyTo(description, MESSAGE, orderOn, self, failTask);
switch(deliver) {
default:
throw new AssertionError();
case TIMEOUT:
long expiresAfterNanos = from.unsafeApplyOnThisThread(id -> Verb.fromId(id).expiresAfterNanos(), (verb.isResponse() ? forVerb : verb).id);
action.setDeadline(simulated.futureScheduler.messageTimeoutNanos(expiresAfterNanos));
break;
case FAILURE:
action.setDeadline(simulated.futureScheduler.messageFailureNanos(toNum, fromNum));
break;
}
break;
}
}
return action;
}
use of org.apache.cassandra.simulator.Action in project cassandra by apache.
the class PairOfSequencesPaxosSimulation method plan.
public ActionPlan plan() {
ActionPlan plan = new KeyspaceActions(simulated, KEYSPACE, TABLE, CREATE_TABLE, cluster, clusterOptions, serialConsistency, this, primaryKeys, debug).plan();
plan = plan.encapsulate(ActionPlan.setUpTearDown(ActionList.of(cluster.stream().map(i -> simulated.run("Insert Partitions", i, executeForPrimaryKeys(INSERT1, primaryKeys)))), ActionList.of(cluster.stream().map(i -> simulated.run("Delete Partitions", i, executeForPrimaryKeys(DELETE1, primaryKeys))))));
final int nodes = cluster.size();
for (int primaryKey : primaryKeys) historyCheckers.add(new HistoryChecker(primaryKey));
List<Supplier<Action>> primaryKeyActions = new ArrayList<>();
for (int pki = 0; pki < primaryKeys.length; ++pki) {
int primaryKey = primaryKeys[pki];
HistoryChecker historyChecker = historyCheckers.get(pki);
Supplier<Action> supplier = new Supplier<Action>() {
int i = 0;
@Override
public Action get() {
int node = simulated.random.uniform(1, nodes + 1);
IInvokableInstance instance = cluster.get(node);
switch(serialConsistency) {
default:
throw new AssertionError();
case LOCAL_SERIAL:
if (simulated.snitch.dcOf(node) > 0) {
// perform some queries against these nodes but don't expect them to be linearizable
return new NonVerifyingOperation(i++, instance, serialConsistency, primaryKey, historyChecker);
}
case SERIAL:
return simulated.random.decide(readRatio) ? new VerifyingOperation(i++, instance, serialConsistency, primaryKey, historyChecker) : new ModifyingOperation(i++, instance, ANY, serialConsistency, primaryKey, historyChecker);
}
}
@Override
public String toString() {
return Integer.toString(primaryKey);
}
};
final ActionListener listener = debug.debug(PARTITION, simulated.time, cluster, KEYSPACE, primaryKey);
if (listener != null) {
Supplier<Action> wrap = supplier;
supplier = new Supplier<Action>() {
@Override
public Action get() {
Action action = wrap.get();
action.register(listener);
return action;
}
@Override
public String toString() {
return wrap.toString();
}
};
}
primaryKeyActions.add(supplier);
}
List<Integer> available = IntStream.range(0, primaryKeys.length).boxed().collect(Collectors.toList());
Action stream = Actions.infiniteStream(concurrency, new Supplier<Action>() {
@Override
public Action get() {
int i = simulated.random.uniform(0, available.size());
int next = available.get(i);
available.set(i, available.get(available.size() - 1));
available.remove(available.size() - 1);
long untilNanos = simulated.time.nanoTime() + SECONDS.toNanos(simulateKeyForSeconds.select(simulated.random));
int concurrency = withinKeyConcurrency.select(simulated.random);
Supplier<Action> supplier = primaryKeyActions.get(next);
// while this stream is finite, it participates in an infinite stream via its parent, so we want to permit termination while it's running
return Actions.infiniteStream(concurrency, new Supplier<Action>() {
@Override
public Action get() {
if (simulated.time.nanoTime() >= untilNanos) {
available.add(next);
return null;
}
return supplier.get();
}
@Override
public String toString() {
return supplier.toString();
}
});
}
@Override
public String toString() {
return "Primary Key Actions";
}
});
return simulated.execution.plan().encapsulate(plan).encapsulate(ActionPlan.interleave(singletonList(ActionList.of(stream))));
}
use of org.apache.cassandra.simulator.Action in project cassandra by apache.
the class OnClusterUpdateGossip method safeInvalidate.
@Override
protected Throwable safeInvalidate(boolean isCancellation) {
ActionList list = cancel;
if (list == null)
return null;
cancel = null;
return list.safeForEach(Action::invalidate);
}
Aggregations