use of org.eclipse.scout.rt.platform.job.IExecutionSemaphore in project scout.rt by eclipse.
the class ExecutionSemaphoreTest method testThreePermitsAndBlocking.
/**
* Tests execution semaphore with 3 permits and with a blocking condition involved.
* <p>
* In total, 7 jobs are scheduled. Thereby, job-1 and job-3 never finish, and job-2 enters a blocking condition.
* <p>
* This test tests, that because job-2 enters a blocking condition, job-4 starts running. Once job-4 completed, job-5
* starts running. Then, job-5 unblocks the conditions, with lets job-2 to continue after job-5 finished. After job-2
* finished, job-6, and then job-7 start running.
* <p>
*/
@Test
// regression
@Times(500)
public void testThreePermitsAndBlocking() throws InterruptedException {
final IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(3);
// synchronized because modified/read by different threads.
final Set<String> protocol = Collections.synchronizedSet(new HashSet<String>());
final IBlockingCondition condition = Jobs.newBlockingCondition(true);
final BlockingCountDownLatch setupLatch = new BlockingCountDownLatch(3);
final BlockingCountDownLatch finishLatch = new BlockingCountDownLatch(2);
final BlockingCountDownLatch latchJob2 = new BlockingCountDownLatch(1);
final BlockingCountDownLatch latchJob5 = new BlockingCountDownLatch(1);
final BlockingCountDownLatch latchJob6 = new BlockingCountDownLatch(1);
final BlockingCountDownLatch latchJob7 = new BlockingCountDownLatch(1);
// job-1
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-1-running");
setupLatch.countDownAndBlock();
finishLatch.countDownAndBlock();
}
}, Jobs.newInput().withName("job-1").withExecutionSemaphore(semaphore));
// job-2
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-2-running (a)");
condition.waitFor(30, TimeUnit.SECONDS);
protocol.add("job-2-running (b)");
latchJob2.countDownAndBlock();
}
}, Jobs.newInput().withName("job-2").withExecutionSemaphore(semaphore));
// job-3
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-3-running");
setupLatch.countDownAndBlock();
finishLatch.countDownAndBlock();
}
}, Jobs.newInput().withName("job-3").withExecutionSemaphore(semaphore));
// job-4
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-4-running");
setupLatch.countDownAndBlock();
}
}, Jobs.newInput().withName("job-4").withExecutionSemaphore(semaphore));
// job-5
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-5-running");
condition.setBlocking(false);
// Wait until job-2 is competing for a permit anew.
// Otherwise, job-6 might get the permit before job-2.
// permit-owners: job-1, job-3, job-5, queue: job-2 (RE-ACQUIRE), job-6, job-7
JobTestUtil.waitForPermitCompetitors(semaphore, 6);
latchJob5.countDownAndBlock();
}
}, Jobs.newInput().withName("job-5").withExecutionSemaphore(semaphore));
// job-6
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-6-running");
latchJob6.countDownAndBlock();
}
}, Jobs.newInput().withName("job-6").withExecutionSemaphore(semaphore));
// job-7
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add("job-7-running");
latchJob7.countDownAndBlock();
}
}, Jobs.newInput().withName("job-7").withExecutionSemaphore(semaphore));
// verify
assertTrue(setupLatch.await());
assertEquals(CollectionUtility.hashSet("job-1-running", "job-2-running (a)", "job-3-running", "job-4-running"), protocol);
protocol.clear();
setupLatch.unblock();
assertTrue(latchJob5.await());
assertEquals(CollectionUtility.hashSet("job-5-running"), protocol);
protocol.clear();
latchJob5.unblock();
try {
assertTrue(latchJob2.await());
} catch (AssertionError e) {
System.out.println(protocol);
throw e;
}
assertEquals(CollectionUtility.hashSet("job-2-running (b)"), protocol);
protocol.clear();
latchJob2.unblock();
assertTrue(latchJob6.await());
assertEquals(CollectionUtility.hashSet("job-6-running"), protocol);
protocol.clear();
latchJob6.unblock();
assertTrue(latchJob7.await());
assertEquals(CollectionUtility.hashSet("job-7-running"), protocol);
latchJob7.unblock();
finishLatch.unblock();
}
use of org.eclipse.scout.rt.platform.job.IExecutionSemaphore in project scout.rt by eclipse.
the class PermitAcquisitionOrderTest method testOrderWithinFixedDelayRepetitiveJob.
/**
* Tests permit acquisition of repetitive job at fixed delay.
*/
@Test
public void testOrderWithinFixedDelayRepetitiveJob() {
// regression
int regressionCount = 100;
// synchronized because modified/read by different threads.
final List<Integer> protocol = Collections.synchronizedList(new ArrayList<Integer>());
final String jobIdentifier = UUID.randomUUID().toString();
final IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(1);
final AtomicInteger counter = new AtomicInteger();
// Schedule repetitive semaphore aware job
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
final int a = counter.incrementAndGet();
final int b = counter.incrementAndGet();
protocol.add(a);
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add(b);
}
}, Jobs.newInput().withName("inner").withExecutionSemaphore(semaphore).withExecutionHint(jobIdentifier));
}
}, Jobs.newInput().withName("outer").withExecutionSemaphore(semaphore).withExecutionHint(jobIdentifier).withExecutionTrigger(Jobs.newExecutionTrigger().withSchedule(FixedDelayScheduleBuilder.repeatForTotalCount(regressionCount, 1, TimeUnit.MILLISECONDS))));
Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(jobIdentifier).toFilter(), Long.MAX_VALUE, TimeUnit.SECONDS);
List<Integer> expectedProtocol = new ArrayList<>();
for (int i = 1; i <= regressionCount * 2; i++) {
expectedProtocol.add(i);
}
assertEquals(expectedProtocol, protocol);
}
use of org.eclipse.scout.rt.platform.job.IExecutionSemaphore in project scout.rt by eclipse.
the class PermitAcquisitionOrderTest method testOrderWithinFixedRateRepetitiveJob.
/**
* Tests that a repetitive semaphore aware job does not acquire the permit before the scheduled job of the last round.
*/
@Test
public void testOrderWithinFixedRateRepetitiveJob() {
// regression
int regressionCount = 100;
// synchronized because modified/read by different threads.
final List<Integer> protocol = Collections.synchronizedList(new ArrayList<Integer>());
final String jobIdentifier = UUID.randomUUID().toString();
final IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(1);
final AtomicInteger counter = new AtomicInteger();
// Schedule repetitive semaphore aware job
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
final int a = counter.incrementAndGet();
final int b = counter.incrementAndGet();
protocol.add(a);
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add(b);
}
}, Jobs.newInput().withExecutionSemaphore(semaphore).withExecutionHint(jobIdentifier));
}
}, Jobs.newInput().withExecutionSemaphore(semaphore).withExecutionHint(jobIdentifier).withExecutionTrigger(Jobs.newExecutionTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(1).withRepeatCount(regressionCount))));
Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(jobIdentifier).toFilter(), 10, TimeUnit.SECONDS);
// However, it is likely that rounds were consolidated, so simply compare the ascending order.
for (int i = 0; i < protocol.size(); i++) {
int expectedOrder = i + 1;
int actualOrder = protocol.get(i).intValue();
if (expectedOrder != actualOrder) {
fail("expected=" + expectedOrder + ", actual=" + actualOrder + ", actualProtocol=" + protocol);
}
}
}
use of org.eclipse.scout.rt.platform.job.IExecutionSemaphore in project scout.rt by eclipse.
the class PermitAcquisitionOrderTest method testOrderIfStartingInSequence.
/**
* Tests that schedule aware jobs scheduled in a row respect the scheduling order when acquiring a permit.
*/
@Test
public void testOrderIfStartingInSequence() {
// regression
int regressionCount = 100;
// synchronized because modified/read by different threads.
final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
final String jobIdentifier = UUID.randomUUID().toString();
IExecutionSemaphore semaphore = Jobs.newExecutionSemaphore(1);
// Schedule 100 jobs to start at the same time
for (int i = 0; i < regressionCount; i++) {
Jobs.schedule(new IRunnable() {
@Override
public void run() throws Exception {
protocol.add(IFuture.CURRENT.get().getJobInput().getName());
}
}, Jobs.newInput().withName("job-{}", i).withExecutionSemaphore(semaphore).withExecutionHint(jobIdentifier));
}
Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(jobIdentifier).toFilter(), 10, TimeUnit.SECONDS);
List<String> expectedProtocol = new ArrayList<>();
for (int i = 0; i < regressionCount; i++) {
expectedProtocol.add("job-" + i);
}
assertEquals(expectedProtocol, protocol);
}
use of org.eclipse.scout.rt.platform.job.IExecutionSemaphore in project scout.rt by eclipse.
the class JobEventFilterBuilderTest 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));
IFuture<?> future10 = Jobs.schedule(mock(IRunnable.class), Jobs.newInput().withName("I").withRunContext(new P_RunContext()).withExecutionSemaphore(mutex1).withExecutionHint(JOB_IDENTIFIER));
// with filtering for futures
IFilter<JobEvent> filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).toFilter();
assertTrue(filter.accept(newJobStateChangedEvent(future1)));
assertTrue(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertTrue(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertTrue(filter.accept(newJobStateChangedEvent(future8)));
assertTrue(filter.accept(newJobStateChangedEvent(future9)));
assertTrue(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for single executing jobs
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().toFilter();
assertTrue(filter.accept(newJobStateChangedEvent(future1)));
assertTrue(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertTrue(filter.accept(newJobStateChangedEvent(future8)));
assertTrue(filter.accept(newJobStateChangedEvent(future9)));
assertTrue(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for mutex
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).toFilter();
assertFalse(filter.accept(newJobStateChangedEvent(future1)));
assertTrue(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertTrue(filter.accept(newJobStateChangedEvent(future8)));
assertFalse(filter.accept(newJobStateChangedEvent(future9)));
assertTrue(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for jobs running on behalf of a RunContext
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(RunContext.class).toFilter();
assertFalse(filter.accept(newJobStateChangedEvent(future1)));
assertTrue(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertFalse(filter.accept(newJobStateChangedEvent(future8)));
assertFalse(filter.accept(newJobStateChangedEvent(future9)));
assertTrue(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for jobs running on behalf of a specific P_RunContext
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).toFilter();
assertFalse(filter.accept(newJobStateChangedEvent(future1)));
assertFalse(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertFalse(filter.accept(newJobStateChangedEvent(future8)));
assertFalse(filter.accept(newJobStateChangedEvent(future9)));
assertTrue(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for names
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).andMatchName("A", "B", "C").toFilter();
assertFalse(filter.accept(newJobStateChangedEvent(future1)));
assertFalse(filter.accept(newJobStateChangedEvent(future2)));
assertTrue(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertFalse(filter.accept(newJobStateChangedEvent(future8)));
assertFalse(filter.accept(newJobStateChangedEvent(future9)));
assertFalse(filter.accept(newJobStateChangedEvent(future10)));
// additionally with filtering for other names
filter = new JobEventFilterBuilder().andMatchFuture(future1, future2, future3, future4, future8, future9, future10).andAreSingleExecuting().andMatchExecutionSemaphore(mutex1).andMatchRunContext(P_RunContext.class).andMatchName("D", "E", "F").toFilter();
assertFalse(filter.accept(newJobStateChangedEvent(future1)));
assertFalse(filter.accept(newJobStateChangedEvent(future2)));
assertFalse(filter.accept(newJobStateChangedEvent(future3)));
assertFalse(filter.accept(newJobStateChangedEvent(future4)));
assertFalse(filter.accept(newJobStateChangedEvent(future5)));
assertFalse(filter.accept(newJobStateChangedEvent(future6)));
assertFalse(filter.accept(newJobStateChangedEvent(future7)));
assertFalse(filter.accept(newJobStateChangedEvent(future8)));
assertFalse(filter.accept(newJobStateChangedEvent(future9)));
assertFalse(filter.accept(newJobStateChangedEvent(future10)));
}
Aggregations