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