You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2013/10/07 15:14:36 UTC

svn commit: r1529835 - in /sling/trunk/bundles/extensions/event/src: main/java/org/apache/sling/event/impl/jobs/ main/java/org/apache/sling/event/impl/support/ main/java/org/apache/sling/event/jobs/ test/java/org/apache/sling/event/impl/jobs/

Author: cziegeler
Date: Mon Oct  7 13:14:35 2013
New Revision: 1529835

URL: http://svn.apache.org/r1529835
Log:
SLING-3139 : Provide a way to schedule jobs
SLING-3138 : Add fluent api to create new jobs

Modified:
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfo.java
    sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/Job.java
    sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/InstanceDescriptionComparatorTest.java

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobImpl.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobImpl.java Mon Oct  7 13:14:35 2013
@@ -272,7 +272,7 @@ public class JobImpl implements Job {
         return new String[] {Job.PROPERTY_JOB_PROGRESS_ETA, PROPERTY_JOB_PROGRESS_STEPS};
     }
 
-    public String setProgress(final int step) {
+    public String[] setProgress(final int step) {
         final int steps = this.getProperty(Job.PROPERTY_JOB_PROGRESS_STEPS, -1);
         if ( steps > 0 && step > 0 ) {
             int current = this.getProperty(Job.PROPERTY_JOB_PROGRESS_STEP, 0);
@@ -282,8 +282,13 @@ public class JobImpl implements Job {
             }
             this.setProperty(Job.PROPERTY_JOB_PROGRESS_STEP, current);
 
-            // TODO - recalculate ETA
-            return Job.PROPERTY_JOB_PROGRESS_STEP;
+            final Calendar now = Calendar.getInstance();
+            final long elapsed = now.getTimeInMillis() - this.getProcessingStarted().getTimeInMillis();
+
+            final long eta = elapsed * steps / step;
+            now.setTimeInMillis(eta);
+            this.setProperty(Job.PROPERTY_JOB_PROGRESS_ETA, now);
+            return new String[] {Job.PROPERTY_JOB_PROGRESS_STEP, Job.PROPERTY_JOB_PROGRESS_ETA};
         }
         return null;
     }
@@ -318,7 +323,9 @@ public class JobImpl implements Job {
     public JobType getJobType() {
         final String enumValue = this.getProperty(JobImpl.PROPERTY_FINISHED_STATE, String.class);
         if ( enumValue == null ) {
-            // TODO - find out active
+            if ( this.getProcessingStarted() != null ) {
+                return JobType.ACTIVE;
+            }
             return JobType.QUEUED;
         }
         return JobType.valueOf(enumValue);
@@ -360,7 +367,7 @@ public class JobImpl implements Job {
      * @see org.apache.sling.event.jobs.Job#getCurrentProgressStep()
      */
     @Override
-    public int getCurrentProgressStep() {
+    public int getFinishedProgressStep() {
         return this.getProperty(Job.PROPERTY_JOB_PROGRESS_STEP, 0);
     }
 

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java Mon Oct  7 13:14:35 2013
@@ -1441,16 +1441,20 @@ public class JobManagerImpl
         return new JobBuilderImpl(this, this.logger, topic);
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.JobManager#getScheduledJobs()
+     */
     @Override
     public Collection<ScheduledJobInfo> getScheduledJobs() {
-        // TODO Auto-generated method stub
-        return null;
+        return this.jobScheduler.getScheduledJobs();
     }
 
+    /**
+     * @see org.apache.sling.event.jobs.JobManager#getScheduledJob(java.lang.String)
+     */
     @Override
-    public ScheduledJobInfo getScheduledJob(String name) {
-        // TODO Auto-generated method stub
-        return null;
+    public ScheduledJobInfo getScheduledJob(final String name) {
+        return this.jobScheduler.getScheduledJob(name);
     }
 
     public boolean addScheduledJob(final String topic,

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobSchedulerImpl.java Mon Oct  7 13:14:35 2013
@@ -21,6 +21,7 @@ package org.apache.sling.event.impl.jobs
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
@@ -65,14 +66,10 @@ import org.slf4j.LoggerFactory;
 /**
  * A scheduler for scheduling jobs
  *
- * TODO check handling of running and active flag
  */
 public class JobSchedulerImpl
     implements EventHandler, TopologyEventListener, org.apache.sling.commons.scheduler.Job {
 
-    /** We use the same resource type as for timed events. */
-    private static final String SCHEDULED_JOB_RESOURCE_TYPE = "slingevent:TimedEvent";
-
     private static final String TOPIC_READ_JOB = "org/apache/sling/event/impl/jobs/READSCHEDULEDJOB";
 
     private static final String PROPERTY_READ_JOB = "properties";
@@ -111,6 +108,21 @@ public class JobSchedulerImpl
         this.scheduler = scheduler;
         this.running = true;
         this.jobManager = jobManager;
+
+        final long now = System.currentTimeMillis();
+        final Thread backgroundThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                loadScheduledJobs(now);
+                try {
+                    runInBackground();
+                } catch (final Throwable t) { //NOSONAR
+                    logger.error("Background thread stopped with exception: " + t.getMessage(), t);
+                    running = false;
+                }
+            }
+        });
+        backgroundThread.start();
     }
 
     /**
@@ -119,25 +131,6 @@ public class JobSchedulerImpl
     public void deactivate() {
         this.running = false;
         this.stopScheduling();
-    }
-
-    private void stopScheduling() {
-        if ( this.active ) {
-            final List<ScheduledJobInfoImpl> jobs = new ArrayList<ScheduledJobInfoImpl>();
-            synchronized ( this.scheduledJobs ) {
-                for(final ScheduledJobInfoImpl job : this.scheduledJobs.values() ) {
-                    jobs.add(job);
-                }
-            }
-            for(final ScheduledJobInfoImpl info : jobs) {
-                try {
-                    logger.debug("Stopping scheduled job : {}", info.getName());
-                    this.scheduler.removeJob(info.getSchedulerJobId());
-                } catch ( final NoSuchElementException nsee ) {
-                    this.ignoreException(nsee);
-                }
-            }
-        }
         synchronized ( this.scheduledJobs ) {
             this.scheduledJobs.clear();
         }
@@ -151,21 +144,27 @@ public class JobSchedulerImpl
         }
     }
 
-    private void startScheduling() {
-        final long now = System.currentTimeMillis();
-        final Thread backgroundThread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                loadScheduledJobs(now);
+    private void stopScheduling() {
+        if ( this.active ) {
+            final Collection<ScheduledJobInfo> jobs = this.getScheduledJobs();
+            for(final ScheduledJobInfo info : jobs) {
                 try {
-                    runInBackground();
-                } catch (final Throwable t) { //NOSONAR
-                    logger.error("Background thread stopped with exception: " + t.getMessage(), t);
-                    running = false;
+                    logger.debug("Stopping scheduled job : {}", info.getName());
+                    this.scheduler.removeJob(((ScheduledJobInfoImpl)info).getSchedulerJobId());
+                } catch ( final NoSuchElementException nsee ) {
+                    this.ignoreException(nsee);
                 }
             }
-        });
-        backgroundThread.start();
+        }
+    }
+
+    private void startScheduling() {
+        if ( this.active ) {
+            final Collection<ScheduledJobInfo> jobs = this.getScheduledJobs();
+            for(final ScheduledJobInfo info : jobs) {
+                this.startScheduledJob(((ScheduledJobInfoImpl)info));
+            }
+        }
     }
 
     /**
@@ -199,7 +198,7 @@ public class JobSchedulerImpl
                     final String schedulerName = (String) properties.remove(ResourceHelper.PROPERTY_SCHEDULER_NAME);
                     final ScheduleInfo scheduleInfo = (ScheduleInfo)  properties.remove(ResourceHelper.PROPERTY_SCHEDULER_INFO);
 
-                    // and now schedule (TODO)
+                    // and now schedule
                     final ScheduledJobInfoImpl info = new ScheduledJobInfoImpl(this, jobTopic, jobName, properties, schedulerName, scheduleInfo);
                     synchronized ( this.scheduledJobs ) {
                         this.scheduledJobs.put(ResourceHelper.filterName(schedulerName), info);
@@ -266,7 +265,8 @@ public class JobSchedulerImpl
         try {
             switch ( info.getScheduleType() ) {
                 case DAILY:
-                    // TODO
+                case WEEKLY:
+                    this.scheduler.addJob(info.getSchedulerJobId(), this, config, info.getCronExpression(), false);
                     break;
                 case DATE:
                     this.scheduler.fireJobAt(info.getSchedulerJobId(), this, config, info.getNextScheduledExecution());
@@ -274,9 +274,6 @@ public class JobSchedulerImpl
                 case PERIODICALLY:
                     this.scheduler.addPeriodicJob(info.getSchedulerJobId(), this, config, info.getPeriod() * 1000, false);
                     break;
-                case WEEKLY:
-                    // TODO
-                    break;
                 }
         } catch (final Exception e) {
             // we ignore it if scheduled fails...
@@ -414,7 +411,7 @@ public class JobSchedulerImpl
             final StringBuilder buf = new StringBuilder(64);
 
             buf.append("//element(*,");
-            buf.append(SCHEDULED_JOB_RESOURCE_TYPE);
+            buf.append(ResourceHelper.RESOURCE_TYPE_SCHEDULED_JOB);
             buf.append(")[@");
             buf.append(ISO9075.encode(org.apache.sling.event.jobs.Job.PROPERTY_JOB_CREATED));
             buf.append(" < xs:dateTime('");
@@ -595,4 +592,20 @@ public class JobSchedulerImpl
         final JobBuilder builder = this.jobManager.createJob(info.getJobTopic()).name(info.getJobTopic()).properties(info.getJobProperties());
         return builder.schedule(info.getName());
     }
+
+    public Collection<ScheduledJobInfo> getScheduledJobs() {
+        final List<ScheduledJobInfo> jobs = new ArrayList<ScheduledJobInfo>();
+        synchronized ( this.scheduledJobs ) {
+            for(final ScheduledJobInfoImpl job : this.scheduledJobs.values() ) {
+                jobs.add(job);
+            }
+        }
+        return jobs;
+    }
+
+    public ScheduledJobInfo getScheduledJob(final String name) {
+        synchronized ( this.scheduledJobs ) {
+            return this.scheduledJobs.get(ResourceHelper.filterName(name));
+        }
+    }
 }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/ScheduledJobInfoImpl.java Mon Oct  7 13:14:35 2013
@@ -126,4 +126,27 @@ public class ScheduledJobInfoImpl implem
     public String getSchedulerJobId() {
         return Job.class.getName() + ":" + this.scheduleName;
     }
+
+    /**
+     * If the job is scheduled daily or weekly, return the cron expression
+     */
+    public String getCronExpression() {
+        if ( this.scheduleInfo.getScheduleType() == ScheduleType.DAILY ) {
+            final StringBuilder sb = new StringBuilder("0 ");
+            sb.append(this.scheduleInfo.getMinuteOfHour());
+            sb.append(' ');
+            sb.append(this.scheduleInfo.getHourOfDay());
+            sb.append(" * * *");
+            return sb.toString();
+        } else if ( this.scheduleInfo.getScheduleType() == ScheduleType.WEEKLY ) {
+            final StringBuilder sb = new StringBuilder("0 ");
+            sb.append(this.scheduleInfo.getMinuteOfHour());
+            sb.append(' ');
+            sb.append(this.scheduleInfo.getHourOfDay());
+            sb.append(" * * ");
+            sb.append(this.scheduleInfo.getDayOfWeek());
+            return sb.toString();
+        }
+        return null;
+    }
 }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfo.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfo.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ScheduleInfo.java Mon Oct  7 13:14:35 2013
@@ -18,16 +18,19 @@
  */
 package org.apache.sling.event.impl.support;
 
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.Date;
 
 import org.apache.sling.event.jobs.ScheduledJobInfo.ScheduleType;
 
-// TODO - implement serializing
 public class ScheduleInfo implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    /** Serialization version. */
+    private static final int VERSION = 1;
+
     public static ScheduleInfo PERIODIC(final int minutes) {
         return new ScheduleInfo(ScheduleType.PERIODICALLY, minutes, -1, -1, -1, null);
     }
@@ -44,17 +47,17 @@ public class ScheduleInfo implements Ser
         return new ScheduleInfo(ScheduleType.DAILY, -1, -1, hour, minute, null);
     }
 
-    private final ScheduleType scheduleType;
+    private ScheduleType scheduleType;
 
-    private final int period;
+    private int period;
 
-    private final int dayOfWeek;
+    private int dayOfWeek;
 
-    private final int hourOfDay;
+    private int hourOfDay;
 
-    private final int minuteOfHour;
+    private int minuteOfHour;
 
-    private final Date at;
+    private Date at;
 
     private ScheduleInfo(final ScheduleType scheduleType,
             final int period,
@@ -70,6 +73,43 @@ public class ScheduleInfo implements Ser
         this.at = at;
     }
 
+    /**
+     * Serialize the object
+     * - write version id
+     * - serialize each entry
+     * @param out Object output stream
+     * @throws IOException
+     */
+    private void writeObject(final java.io.ObjectOutputStream out)
+            throws IOException {
+        out.writeInt(VERSION);
+        out.writeObject(this.scheduleType.name());
+        out.writeInt(this.period);
+        out.writeInt(this.dayOfWeek);
+        out.writeInt(this.hourOfDay);
+        out.writeInt(this.minuteOfHour);
+        out.writeObject(this.at);
+    }
+
+    /**
+     * Deserialize the object
+     * - read version id
+     * - deserialize each entry
+     */
+    private void readObject(final java.io.ObjectInputStream in)
+    throws IOException, ClassNotFoundException {
+        final int version = in.readInt();
+        if ( version < 1 || version > VERSION ) {
+            throw new ClassNotFoundException(this.getClass().getName());
+        }
+        this.scheduleType = ScheduleType.valueOf((String)in.readObject());
+        this.period = in.readInt();
+        this.dayOfWeek = in.readInt();
+        this.hourOfDay = in.readInt();
+        this.minuteOfHour = in.readInt();
+        this.at = (Date) in.readObject();
+    }
+
     public Date getAt() {
         return this.at;
     }

Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/Job.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/Job.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/Job.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/jobs/Job.java Mon Oct  7 13:14:35 2013
@@ -311,26 +311,38 @@ public interface Job {
     String getResultMessage();
 
     /**
-     * TODO
+     * This method returns the optional progress log from the last job
+     * processing. The log is optional and can be set by a job consumer.
+     * @return The log or <code>null</code>
      * @since 1.3
      */
     String[] getProgressLog();
 
     /**
-     * TODO
+     * If the job is in processing, return the optional progress step
+     * count if available. The progress information is optional and
+     * can be set by a job consumer.
+     * @return The progress step count or <code>-1</code>.
      * @since 1.3
      */
     int getProgressStepCount();
 
     /**
-     * TODO
+     * If the job is in processing, return the optional information
+     * about the finished steps. This progress information is optional
+     * and can be set by a job consumer.
+     * In combination with {@link #getProgressStepCount()} this can
+     * be used to calculate a progress bar.
+     * @return The number of the finished progress step or <code>0</code>
      * @since 1.3
      */
-    int getCurrentProgressStep();
+    int getFinishedProgressStep();
 
     /**
-     * TODO
+     * If the job is in processing, return the optional ETA for this job.
+     * The progress information is optional and can be set by a job consumer.
      * @since 1.3
+     * @return The estimated ETA or <code>null</code>
      */
     Calendar getProgressETA();
 }

Modified: sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/InstanceDescriptionComparatorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/InstanceDescriptionComparatorTest.java?rev=1529835&r1=1529834&r2=1529835&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/InstanceDescriptionComparatorTest.java (original)
+++ sling/trunk/bundles/extensions/event/src/test/java/org/apache/sling/event/impl/jobs/InstanceDescriptionComparatorTest.java Mon Oct  7 13:14:35 2013
@@ -155,13 +155,11 @@ public class InstanceDescriptionComparat
 
                 @Override
                 public InstanceDescription getLeader() {
-                    // TODO Auto-generated method stub
                     return null;
                 }
 
                 @Override
                 public List<InstanceDescription> getInstances() {
-                    // TODO Auto-generated method stub
                     return null;
                 }
 
@@ -189,13 +187,11 @@ public class InstanceDescriptionComparat
 
         @Override
         public String getProperty(String name) {
-            // TODO Auto-generated method stub
             return null;
         }
 
         @Override
         public Map<String, String> getProperties() {
-            // TODO Auto-generated method stub
             return null;
         }
     }