use of org.eclipse.scout.rt.platform.job.IFuture 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.job.IFuture 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.job.IFuture 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.job.IFuture in project scout.rt by eclipse.
the class FutureFilterBuilderTest method test.
@Test
public void test() {
IExecutionSemaphore mutex1 = Jobs.newExecutionSemaphore(1);
IExecutionSemaphore mutex2 = Jobs.newExecutionSemaphore(1);
IFuture<?> future1 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("A").withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future2 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("B").withRunContext(RunContexts.empty()).withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future3 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("C").withRunContext(new P_RunContext()).withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future4 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("D").withExecutionHint(JOB_IDENTIFIER).withExecutionTrigger(Jobs.newExecutionTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever())));
IFuture<?> future5 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("E").withExecutionHint(JOB_IDENTIFIER).withExecutionTrigger(Jobs.newExecutionTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever())));
IFuture<?> future6 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("E").withRunContext(new P_RunContext()).withExecutionHint(JOB_IDENTIFIER).withExecutionTrigger(Jobs.newExecutionTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever())));
IFuture<?> future7 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("F").withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future8 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("G").withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future9 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("H").withExecutionSemaphore(mutex2).withExecutionHint(JOB_IDENTIFIER));
IFuture<?> future10 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("I").withRunContext(new P_RunContext()).withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
assertTrue(new FutureFilterBuilder().toFilter().accept(future1));
assertTrue(new FutureFilterBuilder().toFilter().accept(future2));
assertTrue(new FutureFilterBuilder().toFilter().accept(future3));
assertTrue(new FutureFilterBuilder().toFilter().accept(future4));
assertTrue(new FutureFilterBuilder().toFilter().accept(future5));
assertTrue(new FutureFilterBuilder().toFilter().accept(future6));
assertTrue(new FutureFilterBuilder().toFilter().accept(future7));
assertTrue(new FutureFilterBuilder().toFilter().accept(future8));
assertTrue(new FutureFilterBuilder().toFilter().accept(future9));
assertTrue(new FutureFilterBuilder().toFilter().accept(future10));
// with filtering for futures
IFilter<IFuture<?>> filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).toFilter();
assertTrue(filter.accept(future1));
assertTrue(filter.accept(future2));
assertTrue(filter.accept(future3));
assertTrue(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertTrue(filter.accept(future8));
assertTrue(filter.accept(future9));
assertTrue(filter.accept(future10));
// additionally with filtering for single executing jobs
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().toFilter();
assertTrue(filter.accept(future1));
assertTrue(filter.accept(future2));
assertTrue(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertTrue(filter.accept(future8));
assertTrue(filter.accept(future9));
assertTrue(filter.accept(future10));
// additionally with filtering for mutex
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).toFilter();
assertFalse(filter.accept(future1));
assertTrue(filter.accept(future2));
assertTrue(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertTrue(filter.accept(future8));
assertFalse(filter.accept(future9));
assertTrue(filter.accept(future10));
// additionally with filtering for jobs running on behalf of a RunContext
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(RunContext.class).toFilter();
assertFalse(filter.accept(future1));
assertTrue(filter.accept(future2));
assertTrue(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertFalse(filter.accept(future8));
assertFalse(filter.accept(future9));
assertTrue(filter.accept(future10));
// additionally with filtering for jobs running on behalf of a specific P_RunContext
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).toFilter();
assertFalse(filter.accept(future1));
assertFalse(filter.accept(future2));
assertTrue(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertFalse(filter.accept(future8));
assertFalse(filter.accept(future9));
assertTrue(filter.accept(future10));
// additionally with filtering for names
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).andMatchName("A", "B", "C").toFilter();
assertFalse(filter.accept(future1));
assertFalse(filter.accept(future2));
assertTrue(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertFalse(filter.accept(future8));
assertFalse(filter.accept(future9));
assertFalse(filter.accept(future10));
// additionally with filtering for other names
filter = new FutureFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).andMatchName("D", "E", "F").toFilter();
assertFalse(filter.accept(future1));
assertFalse(filter.accept(future2));
assertFalse(filter.accept(future3));
assertFalse(filter.accept(future4));
assertFalse(filter.accept(future5));
assertFalse(filter.accept(future6));
assertFalse(filter.accept(future7));
assertFalse(filter.accept(future8));
assertFalse(filter.accept(future9));
assertFalse(filter.accept(future10));
}
use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.
the class AssertNoRunningJobsStatement method evaluate.
@Override
public void evaluate() throws Throwable {
final ScheduledDescendantJobListener jobListener = new ScheduledDescendantJobListener();
final IRegistrationHandle listenerRegistration = Jobs.getJobManager().addListener(Jobs.newEventFilterBuilder().andMatchEventType(JobEventType.JOB_STATE_CHANGED).andMatchState(JobState.SCHEDULED).toFilter(), jobListener);
try {
// Continue the chain.
m_next.evaluate();
} finally {
listenerRegistration.dispose();
}
final Set<IFuture<?>> scheduledFutures = jobListener.getScheduledFutures();
if (!scheduledFutures.isEmpty()) {
assertNoRunningJobs(Jobs.newFutureFilterBuilder().andMatchFuture(scheduledFutures).toFilter());
}
}
Aggregations