use of org.eclipse.scout.rt.platform.util.concurrent.TimedOutError in project scout.rt by eclipse.
the class TimeoutClientRunContextStatement method evaluate.
@Override
public void evaluate() throws Throwable {
final SafeStatementInvoker invoker = new SafeStatementInvoker(m_next);
final IFuture<Void> future = ModelJobs.schedule(invoker, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("Running test with support for JUnit timeout"));
try {
if (m_timeoutMillis <= 0) {
future.awaitDone();
} else {
future.awaitDone(m_timeoutMillis, TimeUnit.MILLISECONDS);
}
} catch (ThreadInterruptedError | TimedOutError e) {
// NOSONAR
future.cancel(true);
// JUnit timeout exception
throw new TestTimedOutException(m_timeoutMillis, TimeUnit.MILLISECONDS);
}
invoker.throwOnError();
}
use of org.eclipse.scout.rt.platform.util.concurrent.TimedOutError in project scout.rt by eclipse.
the class AbstractClientSession method cancelRunningJobs.
protected void cancelRunningJobs() {
// Filter matches all running jobs that have the same client session associated, except the current thread
// and model jobs. Because the current thread is (or should be) a model job, we cannot wait for other
// model threads. They are always cancelled.
IFilter<IFuture<?>> runningJobsFilter = Jobs.newFutureFilterBuilder().andMatch(new SessionFutureFilter(ISession.CURRENT.get())).andMatchNotFuture(IFuture.CURRENT.get()).andMatchNot(ModelJobFutureFilter.INSTANCE).andMatchNotState(JobState.DONE, JobState.REJECTED).toFilter();
// Wait for running jobs to complete before we cancel them
long delay = NumberUtility.nvl(CONFIG.getPropertyValue(JobCompletionDelayOnSessionShutdown.class), 0L);
if (delay > 0L) {
try {
Jobs.getJobManager().awaitDone(runningJobsFilter, delay, TimeUnit.SECONDS);
} catch (TimedOutError e) {
// NOSONAR
// NOP (not all jobs have been finished within the delay)
} catch (ThreadInterruptedError e) {
LOG.warn("Failed to await for running jobs to complete.", e);
}
}
// Cancel remaining jobs and write a warning to the logger
Set<IFuture<?>> runningFutures = Jobs.getJobManager().getFutures(runningJobsFilter);
if (!runningFutures.isEmpty()) {
LOG.warn("Some running client jobs found while stopping the client session; sent a cancellation request to release associated worker threads. [session={}, user={}, jobs={}]", AbstractClientSession.this, getUserId(), runningFutures);
Jobs.getJobManager().cancel(Jobs.newFutureFilterBuilder().andMatchFuture(runningFutures).toFilter(), true);
}
// Now cancel all other model jobs. Because the current thread is a model job, they can never run anyway.
Set<IFuture<?>> runningModelJobs = Jobs.getJobManager().getFutures(Jobs.newFutureFilterBuilder().andMatch(new SessionFutureFilter(ISession.CURRENT.get())).andMatchNotFuture(IFuture.CURRENT.get()).andMatch(ModelJobFutureFilter.INSTANCE).andMatchNotState(JobState.DONE, JobState.REJECTED).toFilter());
if (!runningModelJobs.isEmpty()) {
LOG.info("Cancel running model jobs because the client session was shut down. [session={}, user={}, jobs={}]", AbstractClientSession.this, getUserId(), runningModelJobs);
Jobs.getJobManager().cancel(Jobs.newFutureFilterBuilder().andMatchFuture(runningModelJobs).toFilter(), true);
}
}
use of org.eclipse.scout.rt.platform.util.concurrent.TimedOutError in project scout.rt by eclipse.
the class ExecutionSemaphoreTest method testChangePermits1.
/**
* Tests no permit available upon completion
*/
@Test
public void testChangePermits1() {
final IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(1);
// synchronized because modified/read by different threads.
final Set<String> protocol = Collections.synchronizedSet(new HashSet<String>());
final String executionHint = UUID.randomUUID().toString();
IFuture<Void> future = Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-1-running");
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-2-running");
}
}, Jobs.newInput().withName("job-2").withExecutionHint(executionHint).withExceptionHandling(null, false).withExecutionSemaphore(semaphore));
// Change the permits to 0
semaphore.withPermits(0);
}
}, Jobs.newInput().withName("job-1").withExecutionHint(executionHint).withExecutionSemaphore(semaphore));
future.awaitDone(1, TimeUnit.SECONDS);
assertEquals(CollectionUtility.hashSet("job-1-running"), protocol);
IFilter<IFuture<?>> job2Filter = Jobs.newFutureFilterBuilder().andMatchExecutionHint(executionHint).toFilter();
try {
Jobs.getJobManager().awaitDone(job2Filter, 1, TimeUnit.SECONDS);
fail("timeout expected because no permit available");
} catch (TimedOutError e) {
// NOOP
}
// Change permits to 1 --> job-2 should run
protocol.clear();
semaphore.withPermits(1);
Jobs.getJobManager().awaitDone(job2Filter, 1, TimeUnit.SECONDS);
assertEquals(CollectionUtility.hashSet("job-2-running"), protocol);
}
use of org.eclipse.scout.rt.platform.util.concurrent.TimedOutError in project scout.rt by eclipse.
the class ExecutionSemaphoreTest method testInternalDeadlock.
/**
* Tests an internal of {@link ExecutionSemaphore}, that {@link AcquisitionTask#notifyPermitAcquired()} is invoked
* outside the {@link ExecutionSemaphore} lock.
* <p>
* Otherwise, a deadlock might occur, once the resuming job-1 tries to re-acquire the permit, namely exactly the time
* when owning acquisitionLock in {@link ExecutionSemaphore#acquire(IFuture, QueuePosition)} and querying
* 'isPermitOwner'. Thereto, job-1 must compete for the semaphore lock, while job-2 (owning semaphore lock) tries to
* notify the resuming job-1 via {@link AcquisitionTask#notifyPermitAcquired()}, but cannot get monitor of
* acquisitionLock.
*/
@Test
// regression; do not remove
@Times(1_000)
public void testInternalDeadlock() {
final IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(1);
final IBlockingCondition condition = Jobs.newBlockingCondition(true);
final AtomicReference<IFuture<?>> future2Ref = new AtomicReference<>();
IFuture<Void> future1 = Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
future2Ref.set(Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
condition.setBlocking(false);
}
}, Jobs.newInput().withName("job-2").withExecutionSemaphore(semaphore)));
condition.waitFor();
}
}, Jobs.newInput().withName("job-1").withExecutionSemaphore(semaphore));
try {
future1.awaitDoneAndGet(5, TimeUnit.SECONDS);
} catch (TimedOutError e) {
fail(String.format("Deadlock while passing permit from 'job-2' to 'job-1' [job-1-state=%s, job-2-state=%s", future1.getState(), future2Ref.get().getState()));
}
}
use of org.eclipse.scout.rt.platform.util.concurrent.TimedOutError in project scout.rt by eclipse.
the class MisfireTest method testFinalRunAfterMisfire.
/**
* Tests that a last round is scheduled upon a 'misfire' with the end-time arrived.
*/
@Test
// regression
@Times(10)
public void testFinalRunAfterMisfire() {
final int endsIn = 20;
final int schedulingInterval = 1;
// synchronized because modified/read by different threads.
final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
final AtomicInteger roundCounter = new AtomicInteger();
IFuture<Void> future = Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
int round = roundCounter.incrementAndGet();
writeProtocol("BEFORE-SLEEP", (JobFutureTask<?>) IFuture.CURRENT.get(), round, protocol);
if (round == 1) {
SleepUtil.sleepSafe(endsIn + 50, TimeUnit.MILLISECONDS);
}
writeProtocol("AFTER-SLEEP", (JobFutureTask<?>) IFuture.CURRENT.get(), round, protocol);
}
}, Jobs.newInput().withExecutionTrigger(Jobs.newExecutionTrigger().withEndIn(endsIn, TimeUnit.MILLISECONDS).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(schedulingInterval).repeatForever())));
// Wait until done
try {
future.awaitDone(10, TimeUnit.SECONDS);
} catch (TimedOutError e) {
future.cancel(true);
fail("Job is hanging because no last round scheduled upon misfire with end-time arrived");
}
// Verify
List<String> expectedProtocol = new ArrayList<>();
expectedProtocol.add("BEFORE-SLEEP: has-next-execution [round=1]");
expectedProtocol.add("AFTER-SLEEP: has-next-execution [round=1]");
expectedProtocol.add("BEFORE-SLEEP: final-run [round=2]");
expectedProtocol.add("AFTER-SLEEP: final-run [round=2]");
assertEquals(expectedProtocol, protocol);
assertTrue(((JobFutureTask<?>) future).isFinalRun());
assertFalse(((JobFutureTask<?>) future).hasNextExecution());
}
Aggregations