diff --git a/.gitignore b/.gitignore index 50b2ed416..d568db7eb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,7 @@ bin/ *.ipr *.iws *.db +alitheia/core/nb-configuration.xml +alitheia/pom.xml +alitheia/pom.xml +alitheia/pom.xml diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/SchedulerServiceImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/SchedulerServiceImpl.java index bf303d134..97b3762e2 100644 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/SchedulerServiceImpl.java +++ b/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/SchedulerServiceImpl.java @@ -38,9 +38,7 @@ import java.util.List; import java.util.PriorityQueue; import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.*; import org.osgi.framework.BundleContext; @@ -65,13 +63,17 @@ public class SchedulerServiceImpl implements Scheduler { // thread safe job queue private PriorityQueue blockedQueue = new PriorityQueue(1, new JobPriorityComparator()); - private BlockingQueue workQueue = new PriorityBlockingQueue(1, - new JobPriorityComparator()); private BlockingQueue failedQueue = new ArrayBlockingQueue(1000); + private ExecutorService executorService; + + private List frozenJobs = new LinkedList(); + private List myWorkerThreads = null; + private boolean isExecuting = false; + public SchedulerServiceImpl() { } public void enqueue(Job job) throws SchedulerException { @@ -89,10 +91,14 @@ public void enqueue(Job job) throws SchedulerException { public void enqueueNoDependencies(Set jobs) throws SchedulerException { synchronized (this) { for (Job job : jobs) { - logger.debug("Scheduler ServiceImpl: queuing job " + if (logger != null) + logger.debug("Scheduler ServiceImpl: queuing job " + job.toString()); job.callAboutToBeEnqueued(this); - workQueue.add(job); + + Future future = executorService.submit(job); + job.future = future; + stats.addWaitingJob(job.getClass().toString()); stats.incTotalJobs(); } @@ -102,7 +108,8 @@ public void enqueueNoDependencies(Set jobs) throws SchedulerException { public void enqueueBlock(List jobs) throws SchedulerException { synchronized (this) { for (Job job : jobs) { - logger.debug("SchedulerServiceImpl: queuing job " + job.toString()); + if (logger != null) + logger.debug("SchedulerServiceImpl: queuing job " + job.toString()); job.callAboutToBeEnqueued(this); blockedQueue.add(job); stats.addWaitingJob(job.getClass().toString()); @@ -115,7 +122,7 @@ public void enqueueBlock(List jobs) throws SchedulerException { public void dequeue(Job job) { synchronized (this) { - if (!blockedQueue.contains(job) && !workQueue.contains(job)) { + if (!blockedQueue.contains(job) && job.future == null) { if (logger != null) { logger.info("SchedulerServiceImpl: job " + job.toString() + " not found in the queue."); @@ -124,7 +131,12 @@ public void dequeue(Job job) { } job.callAboutToBeDequeued(this); blockedQueue.remove(job); - workQueue.remove(job); + if (job.future != null) { + job.future.cancel(false); + } + + stats.removeWaitingJob(job.getClass().toString()); + stats.decTotalJobs(); } if (logger != null) { logger.warn("SchedulerServiceImpl: job " + job.toString() @@ -133,23 +145,11 @@ public void dequeue(Job job) { } public Job takeJob() throws java.lang.InterruptedException { - /* - * no synchronize needed here, the queue is doing that adding - * synchronize here would actually dead-lock this, since no new items - * can be added as long someone is waiting for items - */ - return workQueue.take(); + return null; } public Job takeJob(Job job) throws SchedulerException { - synchronized (workQueue) { - if (!workQueue.contains(job)) { - throw new SchedulerException("Can't take job " + job - + ": It is not in the scheduler's queue right now."); - } - workQueue.remove(job); - return job; - } + return null; } public void jobStateChanged(Job job, Job.State state) { @@ -179,56 +179,46 @@ public void jobStateChanged(Job job, Job.State state) { public void jobDependenciesChanged(Job job) { synchronized (this) { - if (workQueue.contains(job) && !job.canExecute()) { - workQueue.remove(job); - blockedQueue.add(job); + if (jobIsQueuedForWork(job) && !job.canExecute()) { + if (job.future.cancel(false)) { + job.future = null; + blockedQueue.add(job); + } } else if (job.canExecute()) { blockedQueue.remove(job); - workQueue.add(job); + Future future = executorService.submit(job); + job.future = future; } } } + /** + * Returns whether the job meets its dependencies and is + * therefore not blocked but queued for work + */ + public boolean jobIsQueuedForWork(Job job) + { + return (job.future != null && !job.future.isDone()); + } + public void startExecute(int n) { - if (logger != null) - logger.info("Starting " + n + " worker threads"); - synchronized (this) { - if (myWorkerThreads == null) { - myWorkerThreads = new LinkedList(); - } - - for (int i = 0; i < n; ++i) { - WorkerThread t = new WorkerThreadImpl(this, i); - t.start(); - myWorkerThreads.add(t); - stats.incWorkerThreads(); - } + executorService = Executors.newCachedThreadPool(); + for(Runnable runnable : frozenJobs) + { + Job job = (Job)runnable; + Future future = executorService.submit(job); + job.future = future; } + isExecuting = true; } - public void stopExecute() { - synchronized (this) { - if (myWorkerThreads == null) { - return; - } - - for (WorkerThread t : myWorkerThreads) { - t.stopProcessing(); - stats.decWorkerThreads(); - } - - myWorkerThreads.clear(); - } + public void stopExecute() { + frozenJobs = executorService.shutdownNow(); + isExecuting = false; } synchronized public boolean isExecuting() { - synchronized (this) { - if (myWorkerThreads == null) { - return false; - } else { - return !myWorkerThreads.isEmpty(); - } - } + return isExecuting; } public SchedulerStats getSchedulerStats() { @@ -245,8 +235,6 @@ public WorkerThread[] getWorkerThreads() { } public void startOneShotWorkerThread() { - WorkerThread t = new WorkerThreadImpl(this, true); - t.start(); } @Override @@ -304,8 +292,12 @@ public synchronized void yield(Job j, ResumePoint p) throws SchedulerException { if (j.state() != Job.State.Yielded) j.yield(p); - workQueue.remove(j); - blockedQueue.add(j); + + if (jobIsQueuedForWork(j) && j.future.cancel(false)) { + j.future = null; + blockedQueue.add(j); + } + } } diff --git a/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/WorkerThreadImpl.java b/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/WorkerThreadImpl.java deleted file mode 100644 index c5399e7a4..000000000 --- a/alitheia/core/src/main/java/eu/sqooss/impl/service/scheduler/WorkerThreadImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This file is part of the Alitheia system, developed by the SQO-OSS - * consortium as part of the IST FP6 SQO-OSS project, number 033331. - * - * Copyright 2007 - 2010 - Organization for Free and Open Source Software, - * Athens, Greece. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package eu.sqooss.impl.service.scheduler; - -import eu.sqooss.core.AlitheiaCore; -import eu.sqooss.service.logging.Logger; -import eu.sqooss.service.scheduler.Job; -import eu.sqooss.service.scheduler.ResumePoint; -import eu.sqooss.service.scheduler.Scheduler; -import eu.sqooss.service.scheduler.SchedulerException; -import eu.sqooss.service.scheduler.WorkerThread; - -/** - * Worker thread executing jobs given by a scheduler. - * - * @author Christoph Schleifenbaum - */ -class WorkerThreadImpl extends Thread implements WorkerThread { - private static final String PERF_LOG_PROPERTY = "eu.sqooss.log.perf"; - - private boolean perfLog = false; - - private Scheduler m_scheduler; - - private volatile boolean m_processing; - - private volatile Job m_job = null; - - private boolean m_oneshot = false; - - /** - * Constructor creating a new WorkerThread - * @param s the schedule being asked for jobs. - */ - public WorkerThreadImpl(Scheduler s, int n) { - - super(null, null, "Worker "); - m_scheduler = s; - String perfLog = System.getProperty(PERF_LOG_PROPERTY); - if (perfLog != null && perfLog.equals("true")) { - this.perfLog = true; - } - } - - /** - * Constructor creating a new WorkerThread - * @param s the schedule being asked for jobs. - */ - public WorkerThreadImpl(Scheduler s, boolean oneshot) { - super(null, null, "OneShot Worker Thread"); - m_scheduler = s; - } - - /** - * Runs the worker thread. - */ - public void run() { - m_processing = true; - while (m_processing) { - try { - // get a job from the scheduler - executeJob(m_scheduler.takeJob()); - } catch (InterruptedException e) { - // we were interrupted, just try again - continue; - } - if (m_oneshot) { - m_processing = false; - } - } - } - - /** - * Stops processing of jobs, after the current job has finished. - */ - public void stopProcessing() { - m_processing = false; - interrupt(); - } - - public Job executedJob() { - return m_job; - } - - protected void executeJob(Job j) { - Job oldJob = m_job; - long time = -1; - try { - m_job = j; - if (m_job.state() == Job.State.Yielded) { - time = m_job.resume(); - } else { - time = m_job.execute(); - } - } catch (ClassCastException cce) { - AlitheiaCore.getInstance().getLogManager().createLogger( - Logger.NAME_SQOOSS_SCHEDULING).error("Job " + j + " is not resumable"); - } catch (Exception e) { - // no error handling needed here, the job - // itself takes care of that. - } finally { - if (perfLog) { - AlitheiaCore.getInstance().getLogManager(). - createLogger("sqooss.jobtimer"). - debug(m_job.toString() + ", time: " + time + " ms"); - } - m_job = oldJob; - } - } - - /** - * Temporary Worker Thread is used to trigger instant - * execution of a job. - * @author christoph - * - */ - public class TemporaryWorkerThread implements Runnable { - - private WorkerThreadImpl worker; - private Job job; - - public TemporaryWorkerThread(Job job) { - this.worker = new WorkerThreadImpl(null, -1); - } - - TemporaryWorkerThread(WorkerThreadImpl worker,Job job) { - this.worker = worker; - this.job = job; - } - - public void run() { - worker.executeJob(job); - } - - } - - public void takeJob(Job job) throws SchedulerException { - Thread thread = new Thread( - new TemporaryWorkerThread( - this, - m_scheduler.takeJob(job)), "Temporary Scheduler Worker Thread"); - thread.start(); - } -} diff --git a/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java b/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java index 62e9745cc..d443e5c57 100644 --- a/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java +++ b/alitheia/core/src/main/java/eu/sqooss/service/scheduler/Job.java @@ -38,14 +38,15 @@ import java.util.Iterator; import java.util.List; import java.util.LinkedList; - +import java.util.concurrent.Callable; +import java.util.concurrent.Future; import java.lang.Comparable; import java.lang.InterruptedException; import eu.sqooss.core.AlitheiaCore; import eu.sqooss.service.util.Pair; - import eu.sqooss.service.db.DBService; +import eu.sqooss.service.logging.Logger; import eu.sqooss.service.scheduler.SchedulerException; /** @@ -53,7 +54,7 @@ * * @author Christoph Schleifenbam */ -public abstract class Job implements Comparable { +public abstract class Job implements Comparable, Callable { /** * The state of the job. @@ -101,6 +102,13 @@ public enum State { private ResumePoint resumePoint; + private DBService dbs; + + public Future future; + + private static final String PERF_LOG_PROPERTY = "eu.sqooss.log.perf"; + private boolean perfLog = false; + public void setWorkerThread(WorkerThread worker) { m_worker = worker; } @@ -215,7 +223,6 @@ private final synchronized void removeDependee(Job other) { * @throws Exception */ final public long execute() throws Exception { - DBService dbs = AlitheiaCore.getInstance().getDBService(); long timer = System.currentTimeMillis(); try { setState(State.Running); @@ -322,9 +329,12 @@ public final void waitForFinished() { } catch (Exception e) { // if something went wrong with taking the job // ok - we might be stuck... + /* if (m_scheduler.getSchedulerStats().getIdleWorkerThreads() == 0) { m_scheduler.startOneShotWorkerThread(); } + */ + e.printStackTrace(); } synchronized (this) { while (state() != State.Finished) { @@ -374,10 +384,25 @@ public int compareTo(Job other) /** * Protected default constructor. */ - protected Job() { + protected Job() { + this(AlitheiaCore.getInstance().getDBService()); + } + + /** + * Constructor allowing dependency injection + */ + protected Job(DBService dbs) + { + String perfLog = System.getProperty(PERF_LOG_PROPERTY); + if (perfLog != null && perfLog.equals("true")) { + this.perfLog = true; + } + m_scheduler = null; m_errorException = null; setState( State.Created ); + + this.dbs = dbs; } /** @@ -470,7 +495,39 @@ protected void restart() throws Exception { * @throws Exception * If thrown, the job ends up in Error state. */ - abstract protected void run() throws Exception; + abstract protected void run() throws Exception; + + /** + * Wrapper method for run(), created in order to conform to the + * Callable interface. + */ + public Void call() throws Exception + { + //Job oldJob = m_job; + long time = -1; + try { + //m_job = j; + if (this.state() == Job.State.Yielded) { + time = this.resume(); + } else { + time = this.execute(); + } + } catch (ClassCastException cce) { + AlitheiaCore.getInstance().getLogManager().createLogger( + Logger.NAME_SQOOSS_SCHEDULING).error("Job " + this + " is not resumable"); + } catch (Exception e) { + throw e; + } finally { + if (perfLog) { + AlitheiaCore.getInstance().getLogManager(). + createLogger("sqooss.jobtimer"). + debug(this.toString() + ", time: " + time + " ms"); + } + //m_job = oldJob; + } + + return null; + } /** * Stop execution of the job until @@ -493,7 +550,6 @@ public void yield(ResumePoint p) throws SchedulerException { public long resume() throws Exception { long ts = System.currentTimeMillis(); - DBService dbs = AlitheiaCore.getInstance().getDBService(); if (state() != State.Yielded) throw new SchedulerException("Cannot resume a non-yielded job"); diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTest.java b/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTest.java new file mode 100644 index 000000000..cfcf77b0f --- /dev/null +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTest.java @@ -0,0 +1,194 @@ +package eu.sqooss.test.service.scheduler; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import eu.sqooss.impl.service.db.DBServiceImpl; +import eu.sqooss.impl.service.scheduler.SchedulerServiceImpl; +import eu.sqooss.service.db.DBService; +import eu.sqooss.service.scheduler.Job; +import eu.sqooss.service.scheduler.SchedulerException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; + +public class SchedulerTest { + + static SchedulerServiceImpl sched; + + @Before + public void setUp() { + sched = new SchedulerServiceImpl(); + sched.startExecute(2); + } + + @Test + public void testFinishing() throws SchedulerException { + + DBService dbs = DBServiceImpl.getInstance(); + + TestJob j1 = new TestJob(1, "Job 1", dbs); + sched.enqueue(j1); + TestJob j2 = new TestJob(2, "Job 2", dbs); + sched.enqueue(j2); + TestJob j3 = new TestJob(3, "Job 3", dbs); + sched.enqueue(j3); + TestJob j4 = new TestJob(4, "Job 4", dbs); + sched.enqueue(j4); + + + try{ //a future object returns as it has been done. So this section ensures that all tasks are executed before going further + j1.future.get(); + j2.future.get(); + j3.future.get(); + j4.future.get(); + } + catch(Exception e){ + Assert.fail(); + } + + if(sched.getSchedulerStats().getWaitingJobs() !=0) + Assert.fail(); + + } + + @Test + public void testWaitingJobs() throws SchedulerException + { + + DBService dbs = DBServiceImpl.getInstance(); + + TestJob j1 = new TestJob(1, "Job 1", dbs); + sched.enqueue(j1); + TestJob j2 = new TestJob(2, "Job 2", dbs); + sched.enqueue(j2); + TestJob j3 = new TestJob(3, "Job 3", dbs); + sched.enqueue(j3); + TestJob j4 = new TestJob(4, "Job 4", dbs); + sched.enqueue(j4); + + + try{ //a future object returns as it has been done. So this section ensures that all tasks are executed before going further + j1.future.get(); + j2.future.get(); + j3.future.get(); + j4.future.get(); + } + catch(Exception e){ + Assert.fail(); + } + + Assert.assertEquals(Job.State.Finished, j1.state()); + Assert.assertEquals(Job.State.Finished, j2.state()); + Assert.assertEquals(Job.State.Finished, j3.state()); + Assert.assertEquals(Job.State.Finished, j4.state()); + } + + /*@Test + public void testDequeue() throws SchedulerException { + DBService dbs = DBServiceImpl.getInstance(); + + TestJob j1 = new TestJob(1, "Job 1", dbs); + sched.stopExecute(); + sched.enqueue(j1); + Assert.assertEquals(Job.State.Queued, j1.state()); + sched.dequeue(j1); + Assert.assertEquals(Job.State.Created, j1.state()); + }*/ + + @Test + public void testSetNoDependensies() throws SchedulerException { + + DBService dbs = DBServiceImpl.getInstance(); + + Assert.assertEquals(0,sched.getSchedulerStats().getTotalJobs()); + + TestJob j1 = new TestJob(1, "Job 1", dbs); + TestJob j2 = new TestJob(2, "Job 2", dbs); + TestJob j3 = new TestJob(3, "Job 3", dbs); + TestJob j4 = new TestJob(4, "Job 4", dbs); + Set jobs = new HashSet(); + jobs.add(j1); + jobs.add(j2); + jobs.add(j3); + jobs.add(j4); + + sched.enqueueNoDependencies(jobs); + Assert.assertEquals(4,sched.getSchedulerStats().getTotalJobs()); + + try{ //a future object returns as it has been done. So this section ensures that all tasks are executed before going further + j1.future.get(); + j2.future.get(); + j3.future.get(); + j4.future.get(); + } + catch(Exception e){ + Assert.fail(); + } + Assert.assertEquals(Job.State.Finished, j1.state()); + Assert.assertEquals(Job.State.Finished, j2.state()); + Assert.assertEquals(Job.State.Finished, j3.state()); + Assert.assertEquals(Job.State.Finished, j4.state()); + + } + + @Test + public void enqueueBlockTest(){ + DBService dbs = DBServiceImpl.getInstance(); + + TestJob j1 = new TestJob(1, "Job 1", dbs); + TestJob j2 = new TestJob(2, "Job 2", dbs); + TestJob j3 = new TestJob(3, "Job 3", dbs); + TestJob j4 = new TestJob(4, "Job 4", dbs); + List jobs = new ArrayList(); + jobs.add(j1); + jobs.add(j2); + jobs.add(j3); + jobs.add(j4); + + try{ + sched.enqueueBlock(jobs); + j1.future.get(); + j2.future.get(); + j3.future.get(); + j4.future.get(); + } + catch(Exception e) + { + Assert.fail(); + } + Assert.assertEquals(4,sched.getSchedulerStats().getTotalJobs()); + Assert.assertEquals(Job.State.Finished, j1.state()); + Assert.assertEquals(Job.State.Finished, j2.state()); + Assert.assertEquals(Job.State.Finished, j3.state()); + Assert.assertEquals(Job.State.Finished, j4.state()); + } + + @Test + public void IsExecutingTest() //tests wheter the isExecuting boolean is standard false + { + Assert.assertTrue(sched.isExecuting()); + sched.stopExecute(); + Assert.assertFalse(sched.isExecuting()); + } + + //@Test + //public void + + @After + public void tearDown() { + while (sched.getSchedulerStats().getWaitingJobs() > 0) + try { + System.out.println(sched.getSchedulerStats().getWaitingJobs()); + System.out.println("AfterClassSleeping"); + Thread.sleep(500); + } catch (InterruptedException e) {} + + sched.stopExecute(); + } +} \ No newline at end of file diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTests.java b/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTests.java deleted file mode 100644 index f30f92f84..000000000 --- a/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/SchedulerTests.java +++ /dev/null @@ -1,42 +0,0 @@ -package eu.sqooss.test.service.scheduler; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import eu.sqooss.impl.service.scheduler.SchedulerServiceImpl; -import eu.sqooss.service.scheduler.SchedulerException; - -public class SchedulerTests { - - static SchedulerServiceImpl sched; - - @BeforeClass - public static void setUp() { - sched = new SchedulerServiceImpl(); - sched.startExecute(2); - } - - @Test - public void testJobYield() throws SchedulerException { - - TestJob j1 = new TestJob(20, "Test"); - sched.enqueue(j1); - TestJob j2 = new TestJob(20, "Test"); - sched.enqueue(j2); - TestJob j3 = new TestJob(20, "Test"); - sched.enqueue(j3); - TestJob j4 = new TestJob(20, "Test"); - sched.enqueue(j4); - } - - @AfterClass - public static void tearDown() { - while (sched.getSchedulerStats().getWaitingJobs() > 0) - try { - Thread.sleep(500); - } catch (InterruptedException e) {} - - sched.stopExecute(); - } -} \ No newline at end of file diff --git a/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/TestJob.java b/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/TestJob.java index f9d8bc4fb..227024587 100644 --- a/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/TestJob.java +++ b/alitheia/core/src/test/java/eu/sqooss/test/service/scheduler/TestJob.java @@ -33,6 +33,7 @@ package eu.sqooss.test.service.scheduler; +import eu.sqooss.service.db.DBService; import eu.sqooss.service.scheduler.Job; /** @@ -50,7 +51,8 @@ class TestJob extends Job /** * Contructor creating a job printing string \a s \a n times. */ - public TestJob(int n, String s) { + public TestJob(int n, String s, DBService dbs) { + super(dbs); this.n = n; this.s = s; } @@ -62,7 +64,6 @@ public long priority() { protected void run() throws Exception { System.out.println("Testjob running!"); for (int i = 0; i < n; ++i) { - Thread.sleep(500); System.out.println(s); } System.out.println("Testjob finished!");