diff --git a/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptingExecutor.java b/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptingExecutor.java index a9c0fb2e00..1c38cd813d 100644 --- a/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptingExecutor.java +++ b/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptingExecutor.java @@ -91,43 +91,9 @@ public interface InterceptingExecutor extends OrderOn OrderOn orderAppliesAfterScheduling(); - static class InterceptedScheduledFutureTask extends SyncFutureTask implements ScheduledFuture + interface InterceptableScheduledFuture extends ScheduledFuture, RunnableFuture { - final long delayNanos; - Runnable onCancel; - public InterceptedScheduledFutureTask(long delayNanos, Callable call) - { - super(call); - this.delayNanos = delayNanos; - } - - @Override - public long getDelay(TimeUnit unit) - { - return unit.convert(delayNanos, NANOSECONDS); - } - - @Override - public int compareTo(Delayed that) - { - return Long.compare(delayNanos, that.getDelay(NANOSECONDS)); - } - - void onCancel(Runnable onCancel) - { - this.onCancel = onCancel; - } - - @Override - public boolean cancel(boolean b) - { - if (onCancel != null) - { - onCancel.run(); - onCancel = null; - } - return super.cancel(b); - } + void onCancel(Runnable onCancel); } @PerClassLoader @@ -715,6 +681,45 @@ public interface InterceptingExecutor extends OrderOn @PerClassLoader class InterceptingSequentialExecutor extends AbstractSingleThreadedExecutorPlus implements InterceptingExecutor, ScheduledExecutorPlus, OrderOn { + static class InterceptableScheduledFutureTask extends SyncFutureTask implements InterceptableScheduledFuture + { + final long delayNanos; + Runnable onCancel; + public InterceptableScheduledFutureTask(long delayNanos, Callable call) + { + super(call); + this.delayNanos = delayNanos; + } + + @Override + public long getDelay(TimeUnit unit) + { + return unit.convert(delayNanos, NANOSECONDS); + } + + @Override + public int compareTo(Delayed that) + { + return Long.compare(delayNanos, that.getDelay(NANOSECONDS)); + } + + public void onCancel(Runnable onCancel) + { + this.onCancel = onCancel; + } + + @Override + public boolean cancel(boolean b) + { + if (onCancel != null) + { + onCancel.run(); + onCancel = null; + } + return super.cancel(b); + } + } + InterceptingSequentialExecutor(InterceptorOfExecution interceptorOfExecution, ThreadFactory threadFactory, InterceptingTaskFactory taskFactory) { super(interceptorOfExecution, threadFactory, taskFactory); @@ -765,7 +770,7 @@ public interface InterceptingExecutor extends OrderOn throw new RejectedExecutionException(); long delayNanos = unit.toNanos(delay); - return interceptorOfExecution.intercept().schedule(SCHEDULED_TASK, delayNanos, relativeToGlobalNanos(delayNanos), callable(run, null), this); + return schedule(SCHEDULED_TASK, delayNanos, relativeToGlobalNanos(delayNanos), callable(run, null)); } public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) @@ -774,7 +779,7 @@ public interface InterceptingExecutor extends OrderOn throw new RejectedExecutionException(); long delayNanos = unit.toNanos(delay); - return interceptorOfExecution.intercept().schedule(SCHEDULED_TASK, delayNanos, relativeToGlobalNanos(delayNanos), callable, this); + return schedule(SCHEDULED_TASK, delayNanos, relativeToGlobalNanos(delayNanos), callable); } public ScheduledFuture scheduleTimeoutWithDelay(Runnable run, long delay, TimeUnit unit) @@ -787,7 +792,7 @@ public interface InterceptingExecutor extends OrderOn if (isShutdown) throw new RejectedExecutionException(); - return interceptorOfExecution.intercept().schedule(SCHEDULED_TASK, localToRelativeNanos(deadlineNanos), localToGlobalNanos(deadlineNanos), callable(run, null), this); + return schedule(SCHEDULED_TASK, localToRelativeNanos(deadlineNanos), localToGlobalNanos(deadlineNanos), callable(run, null)); } public ScheduledFuture scheduleTimeoutAt(Runnable run, long deadlineNanos) @@ -795,7 +800,7 @@ public interface InterceptingExecutor extends OrderOn if (isShutdown) throw new RejectedExecutionException(); - return interceptorOfExecution.intercept().schedule(SCHEDULED_TIMEOUT, localToRelativeNanos(deadlineNanos), localToGlobalNanos(deadlineNanos), callable(run, null), this); + return schedule(SCHEDULED_TIMEOUT, localToRelativeNanos(deadlineNanos), localToGlobalNanos(deadlineNanos), callable(run, null)); } public ScheduledFuture scheduleSelfRecurring(Runnable run, long delay, TimeUnit unit) @@ -804,7 +809,7 @@ public interface InterceptingExecutor extends OrderOn throw new RejectedExecutionException(); long delayNanos = unit.toNanos(delay); - return interceptorOfExecution.intercept().schedule(SCHEDULED_DAEMON, delayNanos, relativeToGlobalNanos(delayNanos), callable(run, null), this); + return schedule(SCHEDULED_DAEMON, delayNanos, relativeToGlobalNanos(delayNanos), callable(run, null)); } public ScheduledFuture scheduleAtFixedRate(Runnable run, long initialDelay, long period, TimeUnit unit) @@ -813,7 +818,7 @@ public interface InterceptingExecutor extends OrderOn throw new RejectedExecutionException(); long delayNanos = unit.toNanos(initialDelay); - return interceptorOfExecution.intercept().schedule(SCHEDULED_DAEMON, delayNanos, relativeToGlobalNanos(delayNanos), new Callable() + return schedule(SCHEDULED_DAEMON, delayNanos, relativeToGlobalNanos(delayNanos), new Callable() { @Override public Object call() @@ -829,7 +834,12 @@ public interface InterceptingExecutor extends OrderOn { return run.toString(); } - }, this); + }); + } + + ScheduledFuture schedule(SimulatedAction.Kind kind, long delayNanos, long deadlineNanos, Callable task) + { + return interceptorOfExecution.intercept().schedule(kind, delayNanos, deadlineNanos, new InterceptableScheduledFutureTask<>(delayNanos, task), this); } public ScheduledFuture scheduleWithFixedDelay(Runnable run, long initialDelay, long delay, TimeUnit unit) @@ -843,6 +853,8 @@ public interface InterceptingExecutor extends OrderOn } } + + @PerClassLoader class InterceptingPooledLocalAwareExecutor extends InterceptingPooledExecutor implements LocalAwareExecutorPlus { diff --git a/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptorOfExecution.java b/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptorOfExecution.java index ac8255d506..6633e27408 100644 --- a/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptorOfExecution.java +++ b/test/simulator/main/org/apache/cassandra/simulator/systems/InterceptorOfExecution.java @@ -18,10 +18,10 @@ package org.apache.cassandra.simulator.systems; -import java.util.concurrent.Callable; import java.util.concurrent.ScheduledFuture; import java.util.function.Function; +import org.apache.cassandra.simulator.systems.InterceptingExecutor.InterceptableScheduledFuture; import org.apache.cassandra.simulator.systems.SimulatedAction.Kind; import org.apache.cassandra.utils.Shared; import org.apache.cassandra.utils.concurrent.RunnableFuture; @@ -38,7 +38,7 @@ public interface InterceptorOfExecution interface InterceptExecution { > T addTask(T task, InterceptingExecutor executor); - ScheduledFuture schedule(Kind kind, long delayNanos, long deadlineNanos, Callable runnable, InterceptingExecutor executor); + ScheduledFuture schedule(Kind kind, long delayNanos, long deadlineNanos, InterceptableScheduledFuture task, InterceptingExecutor executor); Thread start(Kind kind, Function factory, Runnable run); } } diff --git a/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedExecution.java b/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedExecution.java index bb6387908e..a56aa84ea6 100644 --- a/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedExecution.java +++ b/test/simulator/main/org/apache/cassandra/simulator/systems/SimulatedExecution.java @@ -29,7 +29,7 @@ import org.apache.cassandra.simulator.Actions; import org.apache.cassandra.simulator.OrderOn; import org.apache.cassandra.simulator.systems.InterceptedExecution.InterceptedFutureTaskExecution; import org.apache.cassandra.simulator.systems.InterceptedExecution.InterceptedThreadStart; -import org.apache.cassandra.simulator.systems.InterceptingExecutor.InterceptedScheduledFutureTask; +import org.apache.cassandra.simulator.systems.InterceptingExecutor.InterceptableScheduledFuture; import org.apache.cassandra.utils.concurrent.Condition; import org.apache.cassandra.utils.concurrent.NotScheduledFuture; import org.apache.cassandra.utils.concurrent.RunnableFuture; @@ -93,7 +93,7 @@ public class SimulatedExecution implements InterceptorOfExecution return task; } - public ScheduledFuture schedule(SimulatedAction.Kind kind, long delayNanos, long deadlineNanos, Callable runnable, InterceptingExecutor executor) + public ScheduledFuture schedule(SimulatedAction.Kind kind, long delayNanos, long deadlineNanos, InterceptableScheduledFuture task, InterceptingExecutor executor) { return new NotScheduledFuture<>(); } @@ -135,10 +135,9 @@ public class SimulatedExecution implements InterceptorOfExecution return task; } - public ScheduledFuture schedule(SimulatedAction.Kind kind, long delayNanos, long deadlineNanos, Callable call, InterceptingExecutor executor) + public ScheduledFuture schedule(SimulatedAction.Kind kind, long delayNanos, long deadlineNanos, InterceptableScheduledFuture task, InterceptingExecutor executor) { assert kind == SCHEDULED_TASK || kind == SCHEDULED_TIMEOUT || kind == SCHEDULED_DAEMON; - InterceptedScheduledFutureTask task = new InterceptedScheduledFutureTask<>(delayNanos, call); InterceptedFutureTaskExecution intercepted = new InterceptedFutureTaskExecution<>(kind, executor, task, deadlineNanos); task.onCancel(intercepted::cancel); intercept.interceptExecution(intercepted, executor.orderAppliesAfterScheduling());