You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2004/04/22 22:02:17 UTC
cvs commit: logging-log4j/src/java/org/apache/log4j/scheduler Scheduler.java
ceki 2004/04/22 13:02:17
Modified: src/java/org/apache/log4j/scheduler Scheduler.java
Log:
The scheduler now support periodic elements, it can deal with job deletion,
change of period.
It's probably ready for public consuption.
Revision Changes Path
1.3 +108 -39 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.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Scheduler.java 20 Apr 2004 18:47:59 -0000 1.2
+++ Scheduler.java 22 Apr 2004 20:02:17 -0000 1.3
@@ -14,41 +14,41 @@
* limitations under the License.
*/
-/*
- * Created on Apr 19, 2004
- *
- * To change the template for this generated file go to
- * Window>Preferences>Java>Code Generation>Code and Comments
- */
package org.apache.log4j.scheduler;
import java.util.List;
-import java.util.NoSuchElementException;
import java.util.Vector;
/**
- * @author ceki
+ * A simple but still useful implementation of a Scheduler (in memory only).
+ *
+ * This implementation will work very well when the number of scheduled job is
+ * small, say less than 100 jobs. If a larger number of events need to be
+ * scheduled, than a better adapted data structure for the jobList can give
+ * improved performance.
+ *
+ * @author Ceki
*
- * To change the template for this generated type comment go to
- * Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Scheduler extends Thread {
//
List jobList;
- boolean interrupted;
- long key;
+ boolean shutdown = false;
public Scheduler() {
jobList = new Vector();
}
- public synchronized void delete(Job job) {
+ /**
+ * Find the index of a given job. Returns -1 if the job could not be found.
+ *
+ */
+ int findIndex(Job job) {
int size = jobList.size();
boolean found = false;
- // find the index i such that
- int i = 0;
+ int i = 0;
for (; i < size; i++) {
ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
if(se.job == job) {
@@ -56,66 +56,130 @@
break;
}
}
-
if(found) {
+ return i;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Delete the given job. Returns true if the job could be deleted, and
+ * false if the job could not be found.
+ */
+ public synchronized boolean delete(Job job) {
+ int i = findIndex(job);
+ if(i != -1) {
ScheduledJobEntry se = (ScheduledJobEntry) jobList.remove(i);
- if(se.job != job) {
- new IllegalStateException();
+ if(se.job != job) { // this should never happen
+ new IllegalStateException("Internal programming error");
}
// if the job is the first on the list, then notify the scheduler thread
// to schedule a new job
if(i == 0) {
this.notify();
}
+ return true;
} else {
- throw new NoSuchElementException();
+ return false;
}
}
-
- public synchronized void schedule(Job job, long expectedTime) {
-
- int size = jobList.size();
+
+ /**
+ * Schedule a {@link Job} for execution at system time given by
+ * the <code>desiredTime</code> parameter.
+ */
+ public synchronized void schedule(Job job, long desiredTime) {
+ schedule(new ScheduledJobEntry(job, desiredTime));
+ }
+
+ /**
+ * Schedule a {@link Job} for execution at system time given by
+ * the <code>desiredTime</code> parameter.
+ *
+ * The job will be rescheduled. It will execute with a frequency determined
+ * by the period parameter.
+ */
+ public synchronized void schedule(Job job, long desiredTime, long period) {
+ schedule(new ScheduledJobEntry(job, desiredTime, period));
+ }
+
+ /**
+ * Change the period of a job. The original job must exist for its period
+ * to be changed.
+ *
+ * The method returns true if the period could be changes, and false
+ * otherwise.
+ */
+ public synchronized boolean changePeriod(Job job, long newPeriod) {
+ if(newPeriod <= 0) {
+ throw new IllegalArgumentException("Period must be an integer langer than zero");
+ }
+
+ int i = findIndex(job);
+ if(i == -1) {
+ return false;
+ } else {
+ ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
+ se.period = newPeriod;
+ return true;
+ }
+ }
+
+ private synchronized void schedule(ScheduledJobEntry newSJE) {
+ int max = jobList.size();
+ long desiredExecutionTime = newSJE.desiredExecutionTime;
+
// find the index i such that timeInMillis < jobList[i]
int i = 0;
+ for (; i < max; i++) {
+
+ ScheduledJobEntry sje = (ScheduledJobEntry) jobList.get(i);
- for (; i < size; i++) {
- ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(i);
-
- if (expectedTime < se.timeInMillis) {
+ if (desiredExecutionTime < sje.desiredExecutionTime) {
break;
}
}
- jobList.add(i, new ScheduledJobEntry(job, expectedTime));
+ jobList.add(i, newSJE);
// if the jobList was empty, then notify the scheduler thread
if(i == 0) {
this.notify();
}
}
-
+
+ public void shutdown() {
+ shutdown = true;
+ }
+
public synchronized void run() {
- while (true) {
+ while (!shutdown) {
if (jobList.isEmpty()) {
linger();
} else {
- ScheduledJobEntry se = (ScheduledJobEntry) jobList.get(0);
+ ScheduledJobEntry sje = (ScheduledJobEntry) jobList.get(0);
long now = System.currentTimeMillis();
- if(now >= se.timeInMillis) {
- se.job.execute();
+ if(now >= sje.desiredExecutionTime) {
+ sje.job.execute();
jobList.remove(0);
+ if(sje.period > 0) {
+ sje.desiredExecutionTime = now + sje.period;
+ schedule(sje);
+ }
} else {
- linger(se.timeInMillis - now);
+ linger(sje.desiredExecutionTime - now);
}
}
}
+ System.out.println("Leaving scheduler run method");
}
void linger() {
try {
this.wait();
} catch (InterruptedException ie) {
- interrupted = true;
+ shutdown = true;
}
}
@@ -123,7 +187,7 @@
try {
this.wait(timeToLinger);
} catch (InterruptedException ie) {
- interrupted = true;
+ shutdown = true;
}
}
}
@@ -131,11 +195,16 @@
class ScheduledJobEntry {
- long timeInMillis;
+ long desiredExecutionTime;
Job job;
+ long period = 0;
- ScheduledJobEntry(Job job, long timeInMillis) {
- this.timeInMillis = timeInMillis;
+ ScheduledJobEntry(Job job, long desiredTime) {
+ this(job, desiredTime, 0);
+ }
+ ScheduledJobEntry(Job job, long desiredTime, long period) {
+ this.desiredExecutionTime = desiredTime;
this.job = job;
+ this.period = period;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org