Search in sources :

Example 1 with IFuture

use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.

the class JobListenerBlockedFutureTest method testEventsForBlockingJob.

@Test(timeout = 10000)
public void testEventsForBlockingJob() {
    final IBlockingCondition condition = Jobs.newBlockingCondition(true);
    IClientSession clientSession = mock(IClientSession.class);
    when(clientSession.getModelJobSemaphore()).thenReturn(Jobs.newExecutionSemaphore(1));
    JobEventCaptureListener captureListener = new JobEventCaptureListener();
    Jobs.getJobManager().addListener(ModelJobs.newEventFilterBuilder().toFilter(), captureListener);
    IFuture<Void> outerFuture = null;
    final AtomicReference<IFuture<?>> innerFuture = new AtomicReference<>();
    final JobInput modelJobInput = ModelJobs.newInput(ClientRunContexts.empty().withSession(clientSession, true));
    // start recording of events
    outerFuture = Jobs.getJobManager().schedule(new IRunnable() {

        @Override
        public void run() throws Exception {
            innerFuture.set(Jobs.getJobManager().schedule(new IRunnable() {

                @Override
                public void run() throws Exception {
                    condition.setBlocking(false);
                    // Wait until the outer future is re-acquiring the mutex.
                    // 2=outer-job + inner-job
                    JobTestUtil.waitForPermitCompetitors(modelJobInput.getExecutionSemaphore(), 2);
                }
            }, modelJobInput.copy().withName("inner").withExecutionTrigger(Jobs.newExecutionTrigger().withStartIn(2, TimeUnit.SECONDS))));
            condition.waitFor();
        }
    }, modelJobInput.copy().withName("outer"));
    Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchFuture(outerFuture).toFilter(), 1, TimeUnit.MINUTES);
    Jobs.getJobManager().shutdown();
    // verify events
    int i = -1;
    List<JobEvent> capturedEvents = captureListener.getCapturedEvents();
    List<JobState> capturedFutureStates = captureListener.getCapturedFutureStates();
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.SCHEDULED, capturedEvents.get(i));
    assertEquals(JobState.SCHEDULED, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.WAITING_FOR_PERMIT, capturedEvents.get(i));
    assertEquals(JobState.WAITING_FOR_PERMIT, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.RUNNING, capturedEvents.get(i));
    assertEquals(JobState.RUNNING, capturedFutureStates.get(i));
    // inner
    i++;
    assertStateChangedEvent(innerFuture.get(), JobState.SCHEDULED, capturedEvents.get(i));
    assertEquals(JobState.SCHEDULED, capturedFutureStates.get(i));
    // inner
    i++;
    assertStateChangedEvent(innerFuture.get(), JobState.PENDING, capturedEvents.get(i));
    assertEquals(JobState.PENDING, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.WAITING_FOR_BLOCKING_CONDITION, capturedEvents.get(i));
    assertEquals(JobState.WAITING_FOR_BLOCKING_CONDITION, capturedFutureStates.get(i));
    // inner
    i++;
    assertStateChangedEvent(innerFuture.get(), JobState.WAITING_FOR_PERMIT, capturedEvents.get(i));
    assertEquals(JobState.WAITING_FOR_PERMIT, capturedFutureStates.get(i));
    // inner
    i++;
    assertStateChangedEvent(innerFuture.get(), JobState.RUNNING, capturedEvents.get(i));
    assertEquals(JobState.RUNNING, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.WAITING_FOR_PERMIT, capturedEvents.get(i));
    assertEquals(JobState.WAITING_FOR_PERMIT, capturedFutureStates.get(i));
    // inner
    i++;
    assertStateChangedEvent(innerFuture.get(), JobState.DONE, capturedEvents.get(i));
    assertEquals(JobState.DONE, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.RUNNING, capturedEvents.get(i));
    assertEquals(JobState.RUNNING, capturedFutureStates.get(i));
    // outer
    i++;
    assertStateChangedEvent(outerFuture, JobState.DONE, capturedEvents.get(i));
    assertEquals(JobState.DONE, capturedFutureStates.get(i));
    assertEquals(i + 1, capturedEvents.size());
}
Also used : AtomicReference(java.util.concurrent.atomic.AtomicReference) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) IFuture(org.eclipse.scout.rt.platform.job.IFuture) JobInput(org.eclipse.scout.rt.platform.job.JobInput) JobEvent(org.eclipse.scout.rt.platform.job.listener.JobEvent) IClientSession(org.eclipse.scout.rt.client.IClientSession) JobState(org.eclipse.scout.rt.platform.job.JobState) IBlockingCondition(org.eclipse.scout.rt.platform.job.IBlockingCondition) Test(org.junit.Test)

Example 2 with IFuture

use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.

the class MutualExclusionTest method runTestBlockingCondition.

private void runTestBlockingCondition(final IBlockingCondition condition) {
    condition.setBlocking(true);
    // synchronized because modified/read by different threads.
    final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
    ModelJobs.schedule(new IRunnable() {

        @Override
        public void run() throws Exception {
            final IFuture<?> iFuture1 = IFuture.CURRENT.get();
            protocol.add("job-1-running");
            ModelJobs.schedule(new IRunnable() {

                @Override
                public void run() throws Exception {
                    final IFuture<?> iFuture2 = IFuture.CURRENT.get();
                    protocol.add("job-2-running");
                    if (iFuture1.getState() == JobState.WAITING_FOR_BLOCKING_CONDITION) {
                        protocol.add("job-1-blocked");
                    }
                    ModelJobs.schedule(new IRunnable() {

                        @Override
                        public void run() throws Exception {
                            protocol.add("job-3-running");
                            if (iFuture1.getState() == JobState.WAITING_FOR_BLOCKING_CONDITION) {
                                protocol.add("job-1-blocked");
                            }
                            if (iFuture2.getState() == JobState.WAITING_FOR_BLOCKING_CONDITION) {
                                protocol.add("job-2-blocked");
                            }
                            ModelJobs.schedule(new IRunnable() {

                                @Override
                                public void run() throws Exception {
                                    protocol.add("job-4-running");
                                }
                            }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
                            protocol.add("job-3-before-signaling");
                            condition.setBlocking(false);
                            // Wait for the other jobs to have tried re-acquiring the mutex.
                            JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 4);
                            protocol.add("job-3-after-signaling");
                            ModelJobs.schedule(new IRunnable() {

                                @Override
                                public void run() throws Exception {
                                    protocol.add("job-5-running");
                                }
                            }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
                        }
                    }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
                    protocol.add("job-2-beforeAwait");
                    condition.waitFor();
                    protocol.add("JOB-X-AFTERAWAIT");
                }
            }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
            protocol.add("job-1-beforeAwait");
            condition.waitFor();
            protocol.add("JOB-X-AFTERAWAIT");
        }
    }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
    awaitDoneElseFail(JOB_IDENTIFIER);
    List<String> expected = new ArrayList<>();
    expected.add("job-1-running");
    expected.add("job-1-beforeAwait");
    expected.add("job-2-running");
    expected.add("job-1-blocked");
    expected.add("job-2-beforeAwait");
    expected.add("job-3-running");
    expected.add("job-1-blocked");
    expected.add("job-2-blocked");
    expected.add("job-3-before-signaling");
    expected.add("job-3-after-signaling");
    // no guarantee about the sequence in which waiting threads are released when the blocking condition falls.
    expected.add("JOB-X-AFTERAWAIT");
    // no guarantee about the sequence in which waiting threads are released when the blocking condition falls.
    expected.add("JOB-X-AFTERAWAIT");
    expected.add("job-4-running");
    expected.add("job-5-running");
    assertEquals(expected, protocol);
}
Also used : ArrayList(java.util.ArrayList) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) IFuture(org.eclipse.scout.rt.platform.job.IFuture) ProcessingException(org.eclipse.scout.rt.platform.exception.ProcessingException) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException)

Example 3 with IFuture

use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.

the class MutualExclusionTest method testMutexDeadlock.

/**
 * Tests that a model-job cannot wait for a scheduled job.
 */
@Test
public void testMutexDeadlock() {
    // synchronized because modified/read by different threads.
    final List<Integer> protocol = Collections.synchronizedList(new ArrayList<Integer>());
    ModelJobs.schedule(new IRunnable() {

        @Override
        public void run() throws Exception {
            protocol.add(1);
            IFuture<Void> future = ModelJobs.schedule(new IRunnable() {

                @Override
                public void run() throws Exception {
                    protocol.add(3);
                }
            }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
            try {
                future.awaitDoneAndGet(1, TimeUnit.SECONDS, DefaultExceptionTranslator.class);
            } catch (AssertionException e) {
                protocol.add(2);
            } catch (Exception e) {
                protocol.add(4);
            }
        }
    }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withExecutionHint(JOB_IDENTIFIER));
    awaitDoneElseFail(JOB_IDENTIFIER);
    assertEquals(CollectionUtility.arrayList(1, 2, 3), protocol);
}
Also used : DefaultExceptionTranslator(org.eclipse.scout.rt.platform.exception.DefaultExceptionTranslator) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) IFuture(org.eclipse.scout.rt.platform.job.IFuture) ProcessingException(org.eclipse.scout.rt.platform.exception.ProcessingException) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException) Test(org.junit.Test)

Example 4 with IFuture

use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.

the class MutualExclusionTest method testBlockedJobs.

/**
 * We have 5 jobs that get scheduled simultaneously. The first waits some time so that job2, job3, job4 and job5 get
 * queued. Job1 then enters a blocking condition, which allows job2 to run. But job2 gets rejected by the executor,
 * which allows job3 to run. After job3 completes, job1 is resumed and continues running. After job1 complete, job4
 * gets scheduled. Job4 in turn gets blocked, which prevents job5 from running.
 */
@Test
public void testBlockedJobs() throws java.lang.InterruptedException {
    P_JobManager jobManager = new P_JobManager();
    ExecutorService executorMock = jobManager.getExecutorMock();
    IBean<IJobManager> jobManagerBean = JobTestUtil.replaceCurrentJobManager(jobManager);
    try {
        // synchronized because modified/read by different threads.
        final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
        // Executor mock
        doAnswer(new Answer<Future>() {

            @Override
            public Future answer(InvocationOnMock invocation) throws Throwable {
                final Runnable runnable = (Runnable) invocation.getArguments()[0];
                // Reject job-2 from being scheduled
                if (runnable instanceof JobFutureTask) {
                    JobFutureTask<?> futureTask = (JobFutureTask<?>) runnable;
                    if ("job-2".equals(futureTask.getJobInput().getName())) {
                        futureTask.reject();
                        return null;
                    }
                }
                s_executor.execute(new NamedThreadRunnable(runnable));
                return null;
            }
        }).when(executorMock).execute(any(Runnable.class));
        final BlockingCountDownLatch job4RunningLatch = new BlockingCountDownLatch(1);
        final IBlockingCondition condition = Jobs.newBlockingCondition(true);
        // Job-1
        IFuture<Void> future1 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                // Wait until all 5 jobs are scheduled.
                JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 5);
                try {
                    protocol.add("running-job-1 (a)");
                    condition.waitFor();
                    protocol.add("running-job-1 (b)");
                } catch (ProcessingException e) {
                    protocol.add("jobException");
                }
                if (ModelJobs.isModelThread()) {
                    protocol.add("running-job-1 (e) [model-thread]");
                }
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-1").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
        // Job-2
        IFuture<Void> future2 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-2");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-2").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
        // Job-3
        IFuture<Void> future3 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-3 (a)");
                condition.setBlocking(false);
                // Wait until job-1 tried to re-acquire the mutex.
                // 4 = job1(re-acquiring), job3(owner), job4, job5
                JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 4);
                protocol.add("running-job-3 (b)");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-3").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
        // Job-4
        IFuture<Void> future4 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-4");
                try {
                    job4RunningLatch.countDownAndBlock();
                } catch (java.lang.InterruptedException e) {
                    protocol.add("job-4 [interrupted]");
                }
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-4").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
        // Job-5
        IFuture<Void> future5 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-5");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-5").withExecutionHint(JOB_IDENTIFIER).withExceptionHandling(null, false));
        assertTrue(job4RunningLatch.await());
        try {
            Jobs.getJobManager().awaitDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(JOB_IDENTIFIER).toFilter(), 1, TimeUnit.MILLISECONDS);
            // job-4 and job-5 are pending
            fail("timeout expected");
        } catch (TimedOutError e) {
        // NOOP
        }
        // job-4 and job-5 are pending
        assertFalse(Jobs.getJobManager().isDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(JOB_IDENTIFIER).toFilter()));
        List<String> expectedProtocol = new ArrayList<>();
        expectedProtocol.add("running-job-1 (a)");
        expectedProtocol.add("running-job-3 (a)");
        expectedProtocol.add("running-job-3 (b)");
        expectedProtocol.add("running-job-1 (b)");
        expectedProtocol.add("running-job-1 (e) [model-thread]");
        expectedProtocol.add("running-job-4");
        assertEquals(expectedProtocol, protocol);
        assertFalse(future1.isCancelled());
        assertTrue(future1.isDone());
        assertTrue(future2.isCancelled());
        assertTrue(future2.isDone());
        assertFalse(future3.isCancelled());
        assertTrue(future3.isDone());
        assertFalse(future4.isCancelled());
        assertFalse(future4.isDone());
        assertFalse(future5.isCancelled());
        assertFalse(future5.isDone());
        // cancel job4
        future4.cancel(true);
        awaitDoneElseFail(JOB_IDENTIFIER);
        expectedProtocol.add("job-4 [interrupted]");
        expectedProtocol.add("running-job-5");
        assertEquals(expectedProtocol, protocol);
        assertTrue(Jobs.getJobManager().isDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(JOB_IDENTIFIER).toFilter()));
        assertTrue(future4.isCancelled());
        assertTrue(future4.isDone());
        assertFalse(future5.isCancelled());
        assertTrue(future5.isDone());
    } finally {
        JobTestUtil.unregisterAndShutdownJobManager(jobManagerBean);
    }
}
Also used : BlockingCountDownLatch(org.eclipse.scout.rt.testing.platform.util.BlockingCountDownLatch) ArrayList(java.util.ArrayList) IJobManager(org.eclipse.scout.rt.platform.job.IJobManager) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) TimedOutError(org.eclipse.scout.rt.platform.util.concurrent.TimedOutError) ProcessingException(org.eclipse.scout.rt.platform.exception.ProcessingException) JobFutureTask(org.eclipse.scout.rt.platform.job.internal.JobFutureTask) ProcessingException(org.eclipse.scout.rt.platform.exception.ProcessingException) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) IFuture(org.eclipse.scout.rt.platform.job.IFuture) IBlockingCondition(org.eclipse.scout.rt.platform.job.IBlockingCondition) Test(org.junit.Test)

Example 5 with IFuture

use of org.eclipse.scout.rt.platform.job.IFuture in project scout.rt by eclipse.

the class MutualExclusionTest method testRejection.

/**
 * We have 3 jobs that get scheduled simultaneously. The first waits some time so that job2 and job3 get queued. When
 * job2 gets scheduled, it is rejected by the executor. This test verifies, that job2 still gets scheduled.
 */
@Test
public void testRejection() {
    P_JobManager jobManager = new P_JobManager();
    ExecutorService executorMock = jobManager.getExecutorMock();
    IBean<IJobManager> jobManagerBean = JobTestUtil.replaceCurrentJobManager(jobManager);
    try {
        // synchronized because modified/read by different threads.
        final List<String> protocol = Collections.synchronizedList(new ArrayList<String>());
        // Executor mock
        doAnswer(new Answer<Future>() {

            @Override
            public Future answer(InvocationOnMock invocation) throws Throwable {
                final Runnable runnable = (Runnable) invocation.getArguments()[0];
                // Reject job-2 from being scheduled
                if (runnable instanceof JobFutureTask) {
                    JobFutureTask<?> futureTask = (JobFutureTask<?>) runnable;
                    if ("job-2".equals(futureTask.getJobInput().getName())) {
                        futureTask.reject();
                        return null;
                    }
                }
                s_executor.execute(new NamedThreadRunnable(runnable));
                return null;
            }
        }).when(executorMock).execute(any(Runnable.class));
        // Job-1
        final IFuture<Void> future1 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                // Wait until all 3 jobs are scheduled.
                JobTestUtil.waitForPermitCompetitors(m_clientSession.getModelJobSemaphore(), 3);
                protocol.add("running-job-1");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-1").withExecutionHint(JOB_IDENTIFIER));
        // Job-2
        final IFuture<Void> future2 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-2");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-2").withExecutionHint(JOB_IDENTIFIER));
        // Job-3
        IFuture<Void> future3 = Jobs.schedule(new IRunnable() {

            @Override
            public void run() throws Exception {
                protocol.add("running-job-3");
            }
        }, ModelJobs.newInput(ClientRunContexts.copyCurrent()).withName("job-3").withExecutionHint(JOB_IDENTIFIER));
        awaitDoneElseFail(JOB_IDENTIFIER);
        assertEquals(Arrays.asList("running-job-1", "running-job-3"), protocol);
        assertTrue(Jobs.getJobManager().isDone(Jobs.newFutureFilterBuilder().andMatchExecutionHint(JOB_IDENTIFIER).toFilter()));
        assertFalse(future1.isCancelled());
        assertTrue(future2.isCancelled());
        assertFalse(future3.isCancelled());
    } finally {
        JobTestUtil.unregisterAndShutdownJobManager(jobManagerBean);
    }
}
Also used : JobFutureTask(org.eclipse.scout.rt.platform.job.internal.JobFutureTask) IJobManager(org.eclipse.scout.rt.platform.job.IJobManager) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) ProcessingException(org.eclipse.scout.rt.platform.exception.ProcessingException) AssertionException(org.eclipse.scout.rt.platform.util.Assertions.AssertionException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) IRunnable(org.eclipse.scout.rt.platform.util.concurrent.IRunnable) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) IFuture(org.eclipse.scout.rt.platform.job.IFuture) Test(org.junit.Test)

Aggregations

IFuture (org.eclipse.scout.rt.platform.job.IFuture)19 IRunnable (org.eclipse.scout.rt.platform.util.concurrent.IRunnable)14 Test (org.junit.Test)12 AssertionException (org.eclipse.scout.rt.platform.util.Assertions.AssertionException)6 TimedOutError (org.eclipse.scout.rt.platform.util.concurrent.TimedOutError)6 IExecutionSemaphore (org.eclipse.scout.rt.platform.job.IExecutionSemaphore)5 ArrayList (java.util.ArrayList)4 ProcessingException (org.eclipse.scout.rt.platform.exception.ProcessingException)4 IBlockingCondition (org.eclipse.scout.rt.platform.job.IBlockingCondition)4 IClientSession (org.eclipse.scout.rt.client.IClientSession)3 IJobManager (org.eclipse.scout.rt.platform.job.IJobManager)3 HashSet (java.util.HashSet)2 ExecutorService (java.util.concurrent.ExecutorService)2 Future (java.util.concurrent.Future)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 JobInput (org.eclipse.scout.rt.platform.job.JobInput)2 JobFutureTask (org.eclipse.scout.rt.platform.job.internal.JobFutureTask)2 JobEvent (org.eclipse.scout.rt.platform.job.listener.JobEvent)2 IRegistrationHandle (org.eclipse.scout.rt.platform.util.IRegistrationHandle)2 ThreadInterruptedError (org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError)2