ceki 2004/04/20 11:47:59
Modified: src/java/org/apache/log4j/scheduler Scheduler.java
tests/src/java/org/apache/log4j/scheduler SchedulerTest.java
Log:
Schduler is now pretty heavily tested.
Events can be scheduled and scheduled events can be deleted.
Revision Changes Path
1.2 +38 -11 logging-log4j/src/java/org/apache/log4j/scheduler/Scheduler.java
Index: Scheduler.java
===================================================================
RCS file:
/home/cvs/logging-log4j/src/java/org/apache/log4j/scheduler/Scheduler.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Scheduler.java 20 Apr 2004 10:04:04 -0000 1.1
+++ Scheduler.java 20 Apr 2004 18:47:59 -0000 1.2
@@ -22,9 +22,9 @@
*/
package org.apache.log4j.scheduler;
-import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Vector;
/**
@@ -40,10 +40,40 @@
long key;
public Scheduler() {
- jobList = new LinkedList();
+ jobList = new Vector();
}
- public synchronized long schedule(Job job, Date date) {
- long timeInMillis = date.getTime();
+
+ public synchronized void delete(Job job) {
+ int size = jobList.size();
+ boolean found = false;
+ // find the index i such that
+ int i = 0;
+
+ for (; i < size; i++) {
+ ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
+ if(se.job == job) {
+ found = true;
+ break;
+ }
+ }
+
+ if(found) {
+ ScheduledJobEntry se = (ScheduledJobEntry) jobList.remove(i);
+ if(se.job != job) {
+ new IllegalStateException();
+ }
+ // if the job is the first on the list, then notify the scheduler thread
+ // to schedule a new job
+ if(i == 0) {
+ this.notify();
+ }
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public synchronized void schedule(Job job, long expectedTime) {
+
int size = jobList.size();
@@ -53,16 +83,15 @@
for (; i < size; i++) {
ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
- if (timeInMillis < se.timeInMillis) {
+ if (expectedTime < se.timeInMillis) {
break;
}
}
- jobList.add(i, new ScheduledJobEntry(key, job, timeInMillis));
+ jobList.add(i, new ScheduledJobEntry(job, expectedTime));
// if the jobList was empty, then notify the scheduler thread
if(i == 0) {
this.notify();
}
- return key++;
}
public synchronized void run() {
@@ -104,10 +133,8 @@
class ScheduledJobEntry {
long timeInMillis;
Job job;
- long key;
- ScheduledJobEntry(long key, Job job, long timeInMillis) {
- this.key = key;
+ ScheduledJobEntry(Job job, long timeInMillis) {
this.timeInMillis = timeInMillis;
this.job = job;
}
1.2 +156 -33
logging-log4j/tests/src/java/org/apache/log4j/scheduler/SchedulerTest.java
Index: SchedulerTest.java
===================================================================
RCS file:
/home/cvs/logging-log4j/tests/src/java/org/apache/log4j/scheduler/SchedulerTest.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- SchedulerTest.java 20 Apr 2004 10:04:04 -0000 1.1
+++ SchedulerTest.java 20 Apr 2004 18:47:59 -0000 1.2
@@ -16,19 +16,23 @@
package org.apache.log4j.scheduler;
-import java.util.Date;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
import java.util.Iterator;
+import java.util.Random;
import java.util.Vector;
-import junit.framework.TestCase;
-
/**
* @author Ceki Gulcu
*
*/
public class SchedulerTest extends TestCase {
- static final long TOLERATED_GAP = 50;
+ static final long TOLERATED_GAP = 1000;
+ Random random = new Random(480361007);
+ final long START_TIME = System.currentTimeMillis();
public SchedulerTest(String arg0) {
super(arg0);
@@ -45,59 +49,178 @@
public void testBasic() {
Scheduler scheduler = new Scheduler();
scheduler.start();
+
long now = System.currentTimeMillis();
long expected = now + 100;
- CountingJob cj = new CountingJob(expected);
- scheduler.schedule(cj, new Date(expected));
+ CountingJob cj = new CountingJob(0, expected);
+ scheduler.schedule(cj, expected);
sleep(300);
assertEquals(1, cj.count);
}
-
- public void testMultipleEvent() {
+
+ public void testMultipleEvents() {
Vector jobs = new Vector();
Scheduler scheduler = new Scheduler();
scheduler.start();
+
long now = System.currentTimeMillis();
-
- for(int i = 0; i < 40; i++) {
- long expected = now + i*100;
- CountingJob cj = new CountingJob(expected);
+
+ int loopLength = 100;
+
+ for (int i = 0; i < loopLength; i++) {
+ long expected = now + (i * 100);
+ CountingJob cj = new CountingJob(i, expected);
jobs.add(cj);
- scheduler.schedule(cj, new Date(expected));
+ scheduler.schedule(cj, expected);
+ }
+
+ sleep((100 * loopLength) + 200);
+
+ for (Iterator i = jobs.iterator(); i.hasNext();) {
+ CountingJob cj = (CountingJob) i.next();
+ assertEquals(1, cj.count);
+ }
+ }
+
+ public void testDelete() {
+ Vector jobs = new Vector();
+ Scheduler scheduler = new Scheduler();
+ scheduler.start();
+
+ long now = System.currentTimeMillis();
+
+ long expected0 = now + 200;
+ CountingJob cj0 = new CountingJob(0, expected0);
+ long expected1 = expected0 + 200;
+ CountingJob cj1 = new CountingJob(1, expected1);
+ scheduler.schedule(cj0, expected0);
+ scheduler.schedule(cj1, expected1);
+ scheduler.delete(cj0);
+ sleep(100 + (3 * 200));
+ assertEquals(0, cj0.count);
+ assertEquals(1, cj1.count);
+ }
+
+ /**
+ * A test that inserts and deltes a large number of jobs at random
+ */
+ public void testRandom() {
+ Scheduler scheduler = new Scheduler();
+ scheduler.start();
+
+ Vector jobVector = new Vector();
+ Vector deletedVector = new Vector();
+
+ // the approximative duration of this test in millisecs
+ final int TEST_DURATION = 50000;
+
+ // the frequncy of operations in millisecs
+ final int OP_FREQUENCY = 10;
+
+ // The number of times we will perform an operation on the scheduler
+ final int MAX_OPS = TEST_DURATION / OP_FREQUENCY;
+
+ long start = System.currentTimeMillis();
+
+ for (long i = 0; i < MAX_OPS; i++) {
+ if (shouldDelete() && !jobVector.isEmpty()) {
+ int indexToDelete = getRandomIndexToDelete(jobVector.size());
+ CountingJob j = (CountingJob) jobVector.remove(indexToDelete);
+ if (j.count == 0) {
+ scheduler.delete(j);
+ deletedVector.add(j);
+ if(j.count == 1) {
+ fail("Error in the test code itself.");
+ }
+ }
+ } else {
+ long expected = start + random.nextInt(TEST_DURATION);
+ CountingJob cj = new CountingJob((int) i, expected);
+ jobVector.add(cj);
+ scheduler.schedule(cj, expected);
+ }
+ }
+ long loopEnd = System.currentTimeMillis();
+ sleep(TEST_DURATION - (loopEnd - start) + 2000);
+
+ if (deletedVector.size() > (MAX_OPS/2)) {
+ fail("too many deleted jobs: " + deletedVector.size());
+ }
+ if (jobVector.size() < (MAX_OPS/2)) {
+ fail("too few jobs: " + jobVector.size());
}
- sleep(100*40+200);
- for(Iterator i = jobs.iterator(); i.hasNext();) {
+ for (Iterator i = jobVector.iterator(); i.hasNext();) {
CountingJob cj = (CountingJob) i.next();
assertEquals(1, cj.count);
- }
+ }
+ for (Iterator i = deletedVector.iterator(); i.hasNext();) {
+ CountingJob cj = (CountingJob) i.next();
+ assertEquals(0, cj.count);
+ }
}
-
-
+
+ boolean shouldDelete() {
+ int r = random.nextInt(2);
+
+ if (r == 2) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // On average, make the index of 1 out of 5 deletes zero
+ int getRandomIndexToDelete(int range) {
+ int r = random.nextInt(5);
+ if(r == 0) {
+ return 0;
+ } else {
+ return random.nextInt(range);
+ }
+ }
+
void sleep(long duration) {
try {
Thread.sleep(duration);
- } catch(InterruptedException ie) {
- }
+ } catch (InterruptedException ie) {
+ }
}
-}
-
-class CountingJob implements Job {
-
- int count = 0;
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new SchedulerTest("testRandom"));
+ return suite;
+ }
+
+
+
+ class CountingJob implements Job {
+ int count = 0;
+ int id;
long scheduledTime;
- CountingJob(long scheduledTime) {
+
+ CountingJob(int id, long scheduledTime) {
+ this.id = id;
this.scheduledTime = scheduledTime;
}
-
+
public void execute() {
long now = System.currentTimeMillis();
- if(now < scheduledTime) {
- throw new IllegalStateException("Job executed too early.");
- } else if((now - scheduledTime) > SchedulerTest.TOLERATED_GAP) {
- throw new IllegalStateException("Job executed too late");
+ count++;
+ if (now < scheduledTime) {
+ throw new IllegalStateException("Job executed too early.");
+ } else if ((now - scheduledTime) > SchedulerTest.TOLERATED_GAP) {
+ String msg =
+ "Job id "+id+" executed " + (now - scheduledTime) + " too late "+
+ "diff "+(scheduledTime-SchedulerTest.this.START_TIME);
+ System.out.println(msg);
+ throw new IllegalStateException(msg);
}
- count++;
}
-}
\ No newline at end of file
+}
+}
+
+
+
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]