You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2006/10/14 03:19:21 UTC

svn commit: r463877 - in /incubator/roller/trunk: src/org/apache/roller/business/ src/org/apache/roller/business/pings/ src/org/apache/roller/business/runnable/ src/org/apache/roller/model/ src/org/apache/roller/planet/tasks/ src/org/apache/roller/ui/c...

Author: agilliland
Date: Fri Oct 13 18:19:17 2006
New Revision: 463877

URL: http://svn.apache.org/viewvc?view=rev&rev=463877
Log:
finishing up clustered tasks work by finalizing configuration options for tasks.

1. Defined new configuration method for scheduled tasks

  * tasks are now configured independing in the roller.properties file using a convention of tasks.<taskname>.<prop>=<value>
  * extended base RollerTask class with a method to easy get the properties for a given task.
  * updated existing tasks to make use of new configuration.
  * added definitions for all existing tasks in roller.properties

2. Updated task initialization to use new configuration options

  * RollerContext now sets up tasks based on new tasks.enabled property
  * We no longer fail entirely when a single task fails to initialize

3. Updated ThreadManager with consolidated scheduling option

  * Remove scheduleHourlyTask() and scheduleDailyTask() methods which are no longer needed.
  * Modified scheduleFixedRateTimeTask() method to accept a start time rather than start delay.



Modified:
    incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java
    incubator/roller/trunk/src/org/apache/roller/business/pings/PingQueueTask.java
    incubator/roller/trunk/src/org/apache/roller/business/runnable/RollerTask.java
    incubator/roller/trunk/src/org/apache/roller/business/runnable/TurnoverReferersTask.java
    incubator/roller/trunk/src/org/apache/roller/model/ThreadManager.java
    incubator/roller/trunk/src/org/apache/roller/planet/tasks/RefreshEntriesTask.java
    incubator/roller/trunk/src/org/apache/roller/planet/tasks/SyncWebsitesTask.java
    incubator/roller/trunk/src/org/apache/roller/planet/tasks/TechnoratiRankingsTask.java
    incubator/roller/trunk/src/org/apache/roller/ui/core/RollerContext.java
    incubator/roller/trunk/src/org/apache/roller/util/DateUtil.java
    incubator/roller/trunk/tests/org/apache/roller/business/TaskLockTest.java
    incubator/roller/trunk/web/WEB-INF/classes/roller.properties

Modified: incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/business/ThreadManagerImpl.java Fri Oct 13 18:19:17 2006
@@ -75,23 +75,14 @@
     }
     
     
-    public void scheduleDailyTimerTask(RollerTask task) {
-        scheduler.scheduleAtFixedRate(task,
-                DateUtil.getEndOfDay(new Date()), DateUtil.millisInDay);
-    }
-    
-    
-    public void scheduleHourlyTimerTask(RollerTask task) {
-        scheduler.scheduleAtFixedRate(task, new Date(), 60*60*1000);
-    }
-    
-    
-    public void scheduleFixedRateTimerTask(RollerTask task, long delayMins, long periodMins) {
-        if (periodMins < MIN_RATE_INTERVAL_MINS) {
-            throw new IllegalArgumentException("Period (" + periodMins +
+    public void scheduleFixedRateTimerTask(RollerTask task, Date startTime, long intervalMins) {
+        
+        if (intervalMins < MIN_RATE_INTERVAL_MINS) {
+            throw new IllegalArgumentException("Interval (" + intervalMins +
                     ") shorter than minimum allowed (" + MIN_RATE_INTERVAL_MINS + ")");
         }
-        scheduler.scheduleAtFixedRate(task, delayMins * 60 * 1000, periodMins * 60 * 1000);
+        
+        scheduler.scheduleAtFixedRate(task, startTime, intervalMins * 60 * 1000);
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/business/pings/PingQueueTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/business/pings/PingQueueTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/pings/PingQueueTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/business/pings/PingQueueTask.java Fri Oct 13 18:19:17 2006
@@ -18,6 +18,9 @@
 
 package org.apache.roller.business.pings;
 
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
@@ -38,23 +41,65 @@
     
     private static final Log logger = LogFactory.getLog(PingQueueTask.class);
     
-
+    // a String description of when to start this task
+    private String startTimeDesc = "immediate";
+    
+    // interval at which the task is run, default is 5 minutes
+    private int interval = 5;
+    
+    // lease time given to task lock, default is 30 minutes
+    private int leaseTime = 30;
+    
+    
     public String getName() {
         return "PingQueueTask";
     }
     
-    public int getLeaseTime() {
-        return 3;
+    public Date getStartTime(Date currentTime) {
+        return getAdjustedTime(currentTime, startTimeDesc);
     }
     
     public int getInterval() {
-        return PingConfig.getQueueProcessingIntervalMins();
+        return this.interval;
     }
     
-    /**
-     * Initialize the task.
-     */
+    public int getLeaseTime() {
+        return this.leaseTime;
+    }
+    
+    
     public void init() throws RollerException {
+        
+        // get relevant props
+        Properties props = this.getTaskProperties();
+        
+        // extract start time
+        String startTimeStr = props.getProperty("startTime");
+        if(startTimeStr != null) {
+            this.startTimeDesc = startTimeStr;
+        }
+        
+        // extract interval
+        String intervalStr = props.getProperty("interval");
+        if(intervalStr != null) {
+            try {
+                this.interval = Integer.parseInt(intervalStr);
+            } catch (NumberFormatException ex) {
+                logger.warn("Invalid interval: "+intervalStr);
+            }
+        }
+        
+        // extract lease time
+        String leaseTimeStr = props.getProperty("leaseTime");
+        if(leaseTimeStr != null) {
+            try {
+                this.leaseTime = Integer.parseInt(leaseTimeStr);
+            } catch (NumberFormatException ex) {
+                logger.warn("Invalid leaseTime: "+leaseTimeStr);
+            }
+        }
+        
+        // initialize queue processor
         PingQueueProcessor.init();
     }
     

Modified: incubator/roller/trunk/src/org/apache/roller/business/runnable/RollerTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/business/runnable/RollerTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/runnable/RollerTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/business/runnable/RollerTask.java Fri Oct 13 18:19:17 2006
@@ -19,12 +19,16 @@
 package org.apache.roller.business.runnable;
 
 import java.util.Date;
+import java.util.Enumeration;
+import java.util.Properties;
 import java.util.TimerTask;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
 import org.apache.roller.model.RollerFactory;
 import org.apache.roller.model.ThreadManager;
+import org.apache.roller.util.DateUtil;
 
 
 /**
@@ -50,27 +54,48 @@
     
     /**
      * Get the unique name for this task.
+     *
+     * @return The unique name for this task.
      */
     public abstract String getName();
     
     
     /**
-     * Get the time, in seconds, this task wants to be leased for.
+     * When should this task be started?  The task is given the current time
+     * so that it may determine a start time relative to the current time, 
+     * such as the end of the day or hour.
      *
-     * example: 300 means the task is allowed 5 minutes to run.
+     * It is acceptable to return the currentTime object passed in or any other
+     * time after it.  If the return value is before currentTime then it will
+     * be ignored and the task will be started at currentTime.
+     *
+     * @param currentTime The current time.
+     * @return The Date when this task should be started.
      */
-    public abstract int getLeaseTime();
+    public abstract Date getStartTime(Date currentTime);
     
     
     /**
      * How often should the task run, in seconds.
      *
      * example: 3600 means this task runs once every hour.
+     *
+     * @return The interval the task should be run at, in minutes.
      */
     public abstract int getInterval();
     
     
     /**
+     * Get the time, in seconds, this task wants to be leased for.
+     *
+     * example: 300 means the task is allowed 5 minutes to run.
+     *
+     * @return The time this task should lease its lock for, in minutes.
+     */
+    public abstract int getLeaseTime();
+    
+    
+    /**
      * Run the task.
      */
     public abstract void runTask() throws RollerException;
@@ -148,4 +173,60 @@
         
     }
 
+    
+    /**
+     * Get the properties from RollerConfig which pertain to this task.
+     *
+     * This extracts all properties from the RollerConfig of the type
+     * task.<taskname>.<prop>=value and returns them in a properties object
+     * where each item is keyed by <prop>.
+     */
+    protected Properties getTaskProperties() {
+        
+        String prefix = "tasks."+this.getName()+".";
+        
+        Properties taskProps = new Properties();
+        
+        String key = null;
+        Enumeration keys = RollerConfig.keys();
+        while(keys.hasMoreElements()) {
+            key = (String) keys.nextElement();
+            
+            if(key.startsWith(prefix)) {
+                taskProps.setProperty(key.substring(prefix.length()), 
+                        RollerConfig.getProperty(key));
+            }
+        }
+        
+        return taskProps;
+    }
+    
+    
+    /**
+     * A convenience method for calculating an adjusted time given an initial
+     * Date to work from and a "changeFactor" which describes how the time 
+     * should be adjusted.
+     *
+     * Allowed change factors are ...
+     *   'immediate' - no change
+     *   'startOfHour' - top of the hour, beginning with next hour
+     *   'startOfDay' - midnight, beginning on the next day
+     */
+    protected Date getAdjustedTime(Date startTime, String changeFactor) {
+        
+        if(startTime == null || changeFactor == null) {
+            return startTime;
+        }
+        
+        Date adjustedTime = startTime;
+        
+        if("startOfDay".equals(changeFactor)) {
+            adjustedTime = DateUtil.getEndOfDay(startTime);
+        } else if("startOfHour".equals(changeFactor)) {
+            adjustedTime = DateUtil.getEndOfHour(startTime);
+        }
+        
+        return adjustedTime;
+    }
+    
 }

Modified: incubator/roller/trunk/src/org/apache/roller/business/runnable/TurnoverReferersTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/business/runnable/TurnoverReferersTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/business/runnable/TurnoverReferersTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/business/runnable/TurnoverReferersTask.java Fri Oct 13 18:19:17 2006
@@ -18,6 +18,8 @@
 
 package org.apache.roller.business.runnable;
 
+import java.util.Date;
+import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
@@ -32,25 +34,63 @@
     
     Log log = LogFactory.getLog(TurnoverReferersTask.class);
     
+    // a String description of when to start this task
+    private String startTimeDesc = "startOfDay";
+    
+    // interval at which the task is run, default is 1 day
+    private int interval = 1440;
+    
+    // lease time given to task lock, default is 30 minutes
+    private int leaseTime = 30;
+    
     
     public String getName() {
         return "TurnoverReferersTask";
     }
     
-    public int getLeaseTime() {
-        return 5;
+    public Date getStartTime(Date currentTime) {
+        return getAdjustedTime(currentTime, startTimeDesc);
     }
     
     public int getInterval() {
-        return 60;
+        return this.interval;
+    }
+    
+    public int getLeaseTime() {
+        return this.leaseTime;
     }
     
     
-    /**
-     * Task init.
-     */
     public void init() throws RollerException {
-        log.debug("initing");
+        
+        // get relevant props
+        Properties props = this.getTaskProperties();
+        
+        // extract start time
+        String startTimeStr = props.getProperty("startTime");
+        if(startTimeStr != null) {
+            this.startTimeDesc = startTimeStr;
+        }
+        
+        // extract interval
+        String intervalStr = props.getProperty("interval");
+        if(intervalStr != null) {
+            try {
+                this.interval = Integer.parseInt(intervalStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid interval: "+intervalStr);
+            }
+        }
+        
+        // extract lease time
+        String leaseTimeStr = props.getProperty("leaseTime");
+        if(leaseTimeStr != null) {
+            try {
+                this.leaseTime = Integer.parseInt(leaseTimeStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid leaseTime: "+leaseTimeStr);
+            }
+        }
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/model/ThreadManager.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/model/ThreadManager.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/model/ThreadManager.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/model/ThreadManager.java Fri Oct 13 18:19:17 2006
@@ -48,21 +48,13 @@
     
     
     /**
-     * Schedule task to run once a day.
-     */
-    public void scheduleDailyTimerTask(RollerTask task);
-    
-    
-    /**
-     * Schedule task to run once per hour.
-     */
-    public void scheduleHourlyTimerTask(RollerTask task);
-    
-    
-    /**
      * Schedule task to run at fixed rate.
+     *
+     * @param task The RollerTask to schedule.
+     * @param startTime The Date at which to start the task.
+     * @param long The interval (in minutes) at which the task should run.
      */
-    public void scheduleFixedRateTimerTask(RollerTask task, long delayMins, long periodMins);
+    public void scheduleFixedRateTimerTask(RollerTask task, Date startTime, long intervalMins);
     
     
     /**
@@ -102,7 +94,7 @@
     
     
     /**
-     * What was the next time a task is allowed to run?
+     * What is the next time a task is allowed to run?
      * 
      * @param task The RollerTask to calculate the next run time for.
      * @return Date The next time the task is allowed to run, or null if task has never been run.
@@ -121,4 +113,4 @@
      */
     public void release();
     
-}
\ No newline at end of file
+}

Modified: incubator/roller/trunk/src/org/apache/roller/planet/tasks/RefreshEntriesTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/planet/tasks/RefreshEntriesTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/planet/tasks/RefreshEntriesTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/planet/tasks/RefreshEntriesTask.java Fri Oct 13 18:19:17 2006
@@ -18,6 +18,8 @@
 
 package org.apache.roller.planet.tasks;
 
+import java.util.Date;
+import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
@@ -33,21 +35,63 @@
     
     private static Log log = LogFactory.getLog(RefreshEntriesTask.class);
     
+    // a String description of when to start this task
+    private String startTimeDesc = "startOfHour";
+    
+    // interval at which the task is run, default is 60 minutes
+    private int interval = 60;
+    
+    // lease time given to task lock, default is 30 minutes
+    private int leaseTime = 30;
+    
     
     public String getName() {
         return "RefreshEntriesTask";
     }
     
-    public int getLeaseTime() {
-        return 10;
+    public Date getStartTime(Date currentTime) {
+        return getAdjustedTime(currentTime, startTimeDesc);
     }
     
     public int getInterval() {
-        return 60;
+        return this.interval;
     }
     
+    public int getLeaseTime() {
+        return this.leaseTime;
+    }
+    
+    
     public void init() throws RollerException {
-        // no-op
+        
+        // get relevant props
+        Properties props = this.getTaskProperties();
+        
+        // extract start time
+        String startTimeStr = props.getProperty("startTime");
+        if(startTimeStr != null) {
+            this.startTimeDesc = startTimeStr;
+        }
+        
+        // extract interval
+        String intervalStr = props.getProperty("interval");
+        if(intervalStr != null) {
+            try {
+                this.interval = Integer.parseInt(intervalStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid interval: "+intervalStr);
+            }
+        }
+        
+        // extract lease time
+        String leaseTimeStr = props.getProperty("leaseTime");
+        if(leaseTimeStr != null) {
+            try {
+                this.leaseTime = Integer.parseInt(leaseTimeStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid leaseTime: "+leaseTimeStr);
+            }
+        }
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/planet/tasks/SyncWebsitesTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/planet/tasks/SyncWebsitesTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/planet/tasks/SyncWebsitesTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/planet/tasks/SyncWebsitesTask.java Fri Oct 13 18:19:17 2006
@@ -19,8 +19,10 @@
 package org.apache.roller.planet.tasks;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
@@ -42,21 +44,63 @@
     
     private static Log log = LogFactory.getLog(SyncWebsitesTask.class);
     
+    // a String description of when to start this task
+    private String startTimeDesc = "startOfDay";
+    
+    // interval at which the task is run, default is 1 day
+    private int interval = 1440;
+    
+    // lease time given to ping task lock, default is 30 minutes
+    private int leaseTime = 30;
+    
     
     public String getName() {
         return "SyncWebsitesTask";
     }
     
-    public int getLeaseTime() {
-        return 30;
+    public Date getStartTime(Date currentTime) {
+        return getAdjustedTime(currentTime, startTimeDesc);
     }
     
     public int getInterval() {
-        return 24 * 60;
+        return this.interval;
     }
     
+    public int getLeaseTime() {
+        return this.leaseTime;
+    }
+    
+    
     public void init() throws RollerException {
-        // no-op
+        
+        // get relevant props
+        Properties props = this.getTaskProperties();
+        
+        // extract start time
+        String startTimeStr = props.getProperty("startTime");
+        if(startTimeStr != null) {
+            this.startTimeDesc = startTimeStr;
+        }
+        
+        // extract interval
+        String intervalStr = props.getProperty("interval");
+        if(intervalStr != null) {
+            try {
+                this.interval = Integer.parseInt(intervalStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid interval: "+intervalStr);
+            }
+        }
+        
+        // extract lease time
+        String leaseTimeStr = props.getProperty("leaseTime");
+        if(leaseTimeStr != null) {
+            try {
+                this.leaseTime = Integer.parseInt(leaseTimeStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid leaseTime: "+leaseTimeStr);
+            }
+        }
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/planet/tasks/TechnoratiRankingsTask.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/planet/tasks/TechnoratiRankingsTask.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/planet/tasks/TechnoratiRankingsTask.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/planet/tasks/TechnoratiRankingsTask.java Fri Oct 13 18:19:17 2006
@@ -22,13 +22,13 @@
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Iterator;
+import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.RollerException;
 import org.apache.roller.business.runnable.RollerTask;
 import org.apache.roller.config.RollerConfig;
 import org.apache.roller.planet.model.PlanetManager;
-import org.apache.roller.model.Roller;
 import org.apache.roller.model.RollerFactory;
 import org.apache.roller.model.UserManager;
 import org.apache.roller.planet.pojos.PlanetConfigData;
@@ -43,21 +43,63 @@
     
     private static Log log = LogFactory.getLog(TechnoratiRankingsTask.class);
     
+    // a String description of when to start this task
+    private String startTimeDesc = "startOfDay";
+    
+    // interval at which the task is run, default is 5 minutes
+    private int interval = 1440;
+    
+    // lease time given to task lock, default is 30 minutes
+    private int leaseTime = 30;
+    
     
     public String getName() {
         return "TechnoratiRankingsTask";
     }
     
-    public int getLeaseTime() {
-        return 30;
+    public Date getStartTime(Date currentTime) {
+        return getAdjustedTime(currentTime, startTimeDesc);
     }
     
     public int getInterval() {
-        return 24 * 60;
+        return this.interval;
     }
     
+    public int getLeaseTime() {
+        return this.leaseTime;
+    }
+    
+    
     public void init() throws RollerException {
-        // no-op
+        
+        // get relevant props
+        Properties props = this.getTaskProperties();
+        
+        // extract start time
+        String startTimeStr = props.getProperty("startTime");
+        if(startTimeStr != null) {
+            this.startTimeDesc = startTimeStr;
+        }
+        
+        // extract interval
+        String intervalStr = props.getProperty("interval");
+        if(intervalStr != null) {
+            try {
+                this.interval = Integer.parseInt(intervalStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid interval: "+intervalStr);
+            }
+        }
+        
+        // extract lease time
+        String leaseTimeStr = props.getProperty("leaseTime");
+        if(leaseTimeStr != null) {
+            try {
+                this.leaseTime = Integer.parseInt(leaseTimeStr);
+            } catch (NumberFormatException ex) {
+                log.warn("Invalid leaseTime: "+leaseTimeStr);
+            }
+        }
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/ui/core/RollerContext.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/ui/core/RollerContext.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/ui/core/RollerContext.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/ui/core/RollerContext.java Fri Oct 13 18:19:17 2006
@@ -24,8 +24,8 @@
 import java.io.InputStream;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Date;
 import java.util.Properties;
-import java.util.TimerTask;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.servlet.ServletContext;
@@ -49,7 +49,7 @@
 import org.apache.roller.config.RollerConfig;
 import org.apache.roller.model.Roller;
 import org.apache.roller.model.RollerFactory;
-import org.apache.roller.business.pings.PingQueueTask;
+import org.apache.roller.model.ThreadManager;
 import org.apache.roller.ui.core.security.AutoProvision;
 import org.apache.roller.util.cache.CacheManager;
 import org.apache.velocity.runtime.RuntimeSingleton;
@@ -190,8 +190,7 @@
             roller.getThemeManager();
             setupIndexManager(roller);
             initializePingFeatures(roller);
-            setupPingQueueTask(roller);
-            setupScheduledTasks(mContext, roller);
+            setupTasks();
             
             roller.flush();
             roller.release();
@@ -244,36 +243,41 @@
     }
     
     
-    /** Setup daily and hourly tasks specified in web.xml */
-    private void setupScheduledTasks(ServletContext context, Roller roller)
-            throws RollerException, InstantiationException,
-            IllegalAccessException, ClassNotFoundException {
-        
-        // setup the hourly tasks
-        String hourlyString = RollerConfig.getProperty("tasks.hourly");
-        if (hourlyString != null && hourlyString.trim().length() > 0) {
-            String[] hourlyTasks = StringUtils.stripAll(
-                    StringUtils.split(hourlyString, ",") );
-            for (int i=0; i<hourlyTasks.length; i++) {
-                mLogger.info("Setting hourly task: "+hourlyTasks[i]);
-                RollerTask task =
-                        (RollerTask) Class.forName(hourlyTasks[i]).newInstance();
-                task.init();
-                roller.getThreadManager().scheduleHourlyTimerTask((RollerTask)task);
-            }
-        }
+    private void setupTasks() throws RollerException {
+        
+        ThreadManager tmgr = RollerFactory.getRoller().getThreadManager();
         
-        // setup the daily tasks
-        String dailyString = RollerConfig.getProperty("tasks.daily");
-        if (dailyString != null && dailyString.trim().length() > 0) {
-            String[] dailyTasks = StringUtils.stripAll(
-                    StringUtils.split(dailyString, ",") );
-            for (int j=0; j<dailyTasks.length; j++) {
-                mLogger.info("Setting daily task: "+dailyTasks[j]);
-                RollerTask task =
-                        (RollerTask) Class.forName(dailyTasks[j]).newInstance();
-                task.init();
-                roller.getThreadManager().scheduleDailyTimerTask((RollerTask)task);
+        Date now = new Date();
+        
+        // okay, first we look for what tasks have been enabled
+        String tasksStr = RollerConfig.getProperty("tasks.enabled");
+        String[] tasks = StringUtils.stripAll(StringUtils.split(tasksStr, ","));
+        for (int i=0; i < tasks.length; i++) {
+            
+            String taskClassName = RollerConfig.getProperty("tasks."+tasks[i]+".class");
+            if(taskClassName != null) {
+                mLogger.info("Initializing task: "+tasks[i]);
+                
+                try {
+                    Class taskClass = Class.forName(taskClassName);
+                    RollerTask task = (RollerTask) taskClass.newInstance();
+                    task.init();
+                    
+                    Date startTime = task.getStartTime(now);
+                    if(startTime == null || now.after(startTime)) {
+                        startTime = now;
+                    }
+                    
+                    // schedule it
+                    tmgr.scheduleFixedRateTimerTask(task, startTime, task.getInterval());
+                    
+                } catch (ClassCastException ex) {
+                    mLogger.warn("Task does not extend RollerTask class", ex);
+                } catch (RollerException ex) {
+                    mLogger.error("Error scheduling task", ex);
+                } catch (Exception ex) {
+                    mLogger.error("Error instantiating task", ex);
+                }
             }
         }
     }
@@ -296,29 +300,6 @@
             mLogger.info("Ping usage has been disabled.  Removing any existing auto ping configurations.");
             roller.getAutopingManager().removeAllAutoPings();
         }
-    }
-    
-    
-    // Set up the ping queue processing task
-    private void setupPingQueueTask(Roller roller) throws RollerException {
-        
-        long intervalMins = PingConfig.getQueueProcessingIntervalMins();
-        if (intervalMins == 0) {
-            // Ping queue processing interval of 0 indicates that ping queue processing is disabled on this host.
-            // This provides a crude  way to disable running the ping queue task on some servers if there are
-            // multiple servers in a cluster sharing a db.  Exclusion should really be handled dynamically but isn't.
-            mLogger.warn("Ping queue processing interval is zero; processing from the ping queue will be disabled on this server.");
-            mLogger.warn("Please make sure that ping queue processing is configured to run on one server in the cluster.");
-            return;
-        }
-        
-        // Set up the task
-        PingQueueTask pingQueueTask = new PingQueueTask();
-        pingQueueTask.init();
-        
-        // Schedule it at the appropriate interval, delay start for one interval.
-        mLogger.info("Scheduling ping queue task to run at " + intervalMins + " minute intervals.");
-        roller.getThreadManager().scheduleFixedRateTimerTask(pingQueueTask, intervalMins, intervalMins);
     }
     
     

Modified: incubator/roller/trunk/src/org/apache/roller/util/DateUtil.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/src/org/apache/roller/util/DateUtil.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/util/DateUtil.java (original)
+++ incubator/roller/trunk/src/org/apache/roller/util/DateUtil.java Fri Oct 13 18:19:17 2006
@@ -73,6 +73,29 @@
     
     
     /**
+     * Returns a Date set to the last possible millisecond of the day, just
+     * before midnight. If a null day is passed in, a new Date is created.
+     * midnight (00m 00h 00s)
+     */
+    public static Date getEndOfHour(Date day) {
+        return getEndOfHour(day, Calendar.getInstance());
+    }
+    
+    
+    public static Date getEndOfHour(Date day, Calendar cal) {
+        if (day == null || cal == null) {
+            return day;
+        }
+        
+        cal.setTime(day);
+        cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
+        cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
+        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
+        return cal.getTime();
+    }
+    
+    
+    /**
      * Returns a Date set to the first possible millisecond of the month, just
      * after midnight. If a null day is passed in, a new Date is created.
      * midnight (00m 00h 00s)

Modified: incubator/roller/trunk/tests/org/apache/roller/business/TaskLockTest.java
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/tests/org/apache/roller/business/TaskLockTest.java?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/tests/org/apache/roller/business/TaskLockTest.java (original)
+++ incubator/roller/trunk/tests/org/apache/roller/business/TaskLockTest.java Fri Oct 13 18:19:17 2006
@@ -18,6 +18,7 @@
 
 package org.apache.roller.business;
 
+import java.util.Date;
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
@@ -89,6 +90,7 @@
     class TestTask extends RollerTask {
         
         public String getName() { return "TestTask"; }
+        public Date getStartTime(Date current) { return current; }
         public int getLeaseTime() { return 300; }
         public int getInterval() { return 1800; }
         public void runTask() { }

Modified: incubator/roller/trunk/web/WEB-INF/classes/roller.properties
URL: http://svn.apache.org/viewvc/incubator/roller/trunk/web/WEB-INF/classes/roller.properties?view=diff&rev=463877&r1=463876&r2=463877
==============================================================================
--- incubator/roller/trunk/web/WEB-INF/classes/roller.properties (original)
+++ incubator/roller/trunk/web/WEB-INF/classes/roller.properties Fri Oct 13 18:19:17 2006
@@ -253,19 +253,47 @@
 plugins.defaultEditor=TextEditor
 
 #----------------------------------
-# scheduled tasks, each is comma separated list of classes
+# Scheduled Background Tasks ... all times are in minutes.
+#
+# Task properties should follow the given format ...
+#     tasks.<taskname>.<prop>=<value>
+#
+# The *enabled* tasks are defined by tasks.enabled=<taskname>[,<taskname>]
+#-----------------------------------
 
-# Comma separated list of task classnames to be executed once per day
-tasks.daily=org.apache.roller.business.runnable.TurnoverReferersTask\
+# Tasks which are enabled.  Only tasks listed here will be run.
+tasks.enabled=TurnoverReferersTask,PingQueueTask
 
-# Daily Planet task: syncs weblog list with Roller, refreshes Technorati stats
-#,org.apache.roller.ui.core.tasks.SyncWebsitesTask
+# Reset referer counts
+tasks.TurnoverReferersTask.class=org.apache.roller.business.runnable.TurnoverReferersTask
+tasks.TurnoverReferersTask.startTime=startOfDay
+tasks.TurnoverReferersTask.interval=1440
+tasks.TurnoverReferersTask.leaseTime=30
 
-# Comma separated list of task classnames to be executed hourly
-tasks.hourly=\
+# Ping processor, does sending of pings
+tasks.PingQueueTask.class=org.apache.roller.business.pings.PingQueueTask
+tasks.PingQueueTask.startTime=immediate
+tasks.PingQueueTask.interval=5
+tasks.PingQueueTask.leaseTime=30
+
+# Sync Roller weblogs with planet
+tasks.SyncWebsitesTask.class=org.apache.roller.planet.tasks.SyncWebsitesTask
+tasks.SyncWebsitesTask.startTime=startOfDay
+tasks.SyncWebsitesTask.interval=1440
+tasks.SyncWebsitesTask.leaseTime=30
+
+# Refresh entries for planet feeds
+tasks.RefreshEntriesTask.class=org.apache.roller.planet.tasks.RefreshEntriesTask
+tasks.RefreshEntriesTask.startTime=startOfHour
+tasks.RefreshEntriesTask.interval=60
+tasks.RefreshEntriesTask.leaseTime=30
+
+# Technorati rankings for planet feeds
+tasks.TechnoratiRankingsTask.class=org.apache.roller.planet.tasks.TechnoratiRankingsTask
+tasks.TechnoratiRankingsTask.startTime=startOfDay
+tasks.TechnoratiRankingsTask.interval=1440
+tasks.TechnoratiRankingsTask.leaseTime=30
 
-# Hourly Planet task: refresh latest entry list from all weblogs in list
-#org.apache.roller.ui.core.tasks.RefreshEntriesTask
 
 #----------------------------------
 # Persistence settings