blob: 16e3041e9e6d698dc3732a9dcc547b9aff6ab8e8 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang=""><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>AbstractSchedulerService.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Turbine</a> &gt; <a href="index.source.html" class="el_package">org.apache.turbine.services.schedule</a> &gt; <span class="el_source">AbstractSchedulerService.java</span></div><h1>AbstractSchedulerService.java</h1><pre class="source lang-java linenums">package org.apache.turbine.services.schedule;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* &quot;License&quot;); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.turbine.services.InitializationException;
import org.apache.turbine.services.TurbineBaseService;
import org.apache.turbine.util.TurbineException;
/**
* Service for a cron like scheduler.
*
* @author &lt;a href=&quot;mailto:mbryson@mont.mindspring.com&quot;&gt;Dave Bryson&lt;/a&gt;
* @author &lt;a href=&quot;mailto:quintonm@bellsouth.net&quot;&gt;Quinton McCombs&lt;/a&gt;
* @version $Id: TorqueSchedulerService.java 534527 2007-05-02 16:10:59Z tv $
*/
<span class="nc" id="L41">public abstract class AbstractSchedulerService extends TurbineBaseService implements ScheduleService</span>
{
/** Logging */
<span class="nc" id="L44"> protected static final Logger log = LogManager.getLogger(ScheduleService.LOGGER_NAME);</span>
/** The queue */
<span class="nc" id="L47"> protected JobQueue&lt;JobEntry&gt; scheduleQueue = null;</span>
/** Current status of the scheduler */
<span class="nc" id="L50"> private AtomicBoolean enabled = new AtomicBoolean(false);</span>
/** The housekeeping thread. */
protected Thread houseKeepingThread;
/** The thread pool used to process jobs. */
protected ExecutorService threadPool;
/**
* Initializes the SchedulerService.
*
* @throws InitializationException
* Something went wrong in the init stage
*/
@Override
public void init() throws InitializationException
{
try
{
<span class="nc" id="L69"> setEnabled(getConfiguration().getBoolean(&quot;enabled&quot;, true));</span>
<span class="nc" id="L70"> scheduleQueue = new JobQueue&lt;&gt;();</span>
<span class="nc" id="L71"> threadPool = Executors.newCachedThreadPool(</span>
new BasicThreadFactory.Builder()
<span class="nc" id="L73"> .namingPattern(&quot;Turbine-ScheduledJob-&quot;)</span>
<span class="nc" id="L74"> .daemon(true)</span>
<span class="nc" id="L75"> .build());</span>
@SuppressWarnings(&quot;unchecked&quot;) // Why is this cast necessary?
<span class="nc" id="L78"> List&lt;JobEntry&gt; jobs = (List&lt;JobEntry&gt;)loadJobs();</span>
<span class="nc" id="L79"> scheduleQueue.batchLoad(jobs);</span>
<span class="nc" id="L80"> restart();</span>
<span class="nc" id="L82"> setInit(true);</span>
}
<span class="nc" id="L84"> catch (Exception e)</span>
{
<span class="nc" id="L86"> throw new InitializationException(&quot;Could not initialize the scheduler service&quot;, e);</span>
<span class="nc" id="L87"> }</span>
<span class="nc" id="L88"> }</span>
/**
* Load all jobs from configuration storage
*
* @return the list of pre-configured jobs
* @throws TurbineException if jobs could not be loaded
*/
protected abstract List&lt;? extends JobEntry&gt; loadJobs() throws TurbineException;
/**
* Shutdowns the service.
* &lt;p&gt;
* This methods interrupts the housekeeping thread.
*/
@Override
public void shutdown()
{
<span class="nc bnc" id="L106" title="All 2 branches missed."> if (getThread() != null)</span>
{
<span class="nc" id="L108"> getThread().interrupt();</span>
}
<span class="nc" id="L111"> threadPool.shutdownNow();</span>
<span class="nc" id="L112"> }</span>
/**
* @see org.apache.turbine.services.schedule.ScheduleService#newJob(int, int, int, int, int, java.lang.String)
*/
@Override
public abstract JobEntry newJob(int sec, int min, int hour, int wd, int day_mo, String task) throws TurbineException;
/**
* Get a specific Job from Storage.
*
* @param oid
* The int id for the job.
* @return A JobEntry.
* @throws TurbineException
* job could not be retrieved.
*/
@Override
public abstract JobEntry getJob(int oid) throws TurbineException;
/**
* Add a new job to the queue.
*
* @param je
* A JobEntry with the job to add.
* @throws TurbineException
* job could not be added
*/
@Override
public void addJob(JobEntry je) throws TurbineException
{
<span class="nc" id="L143"> updateJob(je);</span>
<span class="nc" id="L144"> }</span>
/**
* Remove a job from the queue.
*
* @param je
* A JobEntry with the job to remove.
* @throws TurbineException
* job could not be removed
*/
@Override
public abstract void removeJob(JobEntry je) throws TurbineException;
/**
* Add or update a job.
*
* @param je
* A JobEntry with the job to modify
* @throws TurbineException
* job could not be updated
*/
@Override
public abstract void updateJob(JobEntry je) throws TurbineException;
/**
* List jobs in the queue. This is used by the scheduler UI.
*
* @return A List of jobs.
*/
@Override
public List&lt;JobEntry&gt; listJobs()
{
<span class="nc" id="L176"> return scheduleQueue.list();</span>
}
/**
* Sets the enabled status of the scheduler
*
* @param enabled true to enable the scheduler
*
*/
protected void setEnabled(boolean enabled)
{
<span class="nc" id="L187"> this.enabled.set(enabled);</span>
<span class="nc" id="L188"> }</span>
/**
* Determines if the scheduler service is currently enabled.
*
* @return Status of the scheduler service.
*/
@Override
public boolean isEnabled()
{
<span class="nc" id="L198"> return enabled.get();</span>
}
/**
* Starts or restarts the scheduler if not already running.
*/
@Override
public synchronized void startScheduler()
{
<span class="nc" id="L207"> setEnabled(true);</span>
<span class="nc" id="L208"> restart();</span>
<span class="nc" id="L209"> }</span>
/**
* Stops the scheduler if it is currently running.
*/
@Override
public synchronized void stopScheduler()
{
<span class="nc" id="L217"> log.info(&quot;Stopping job scheduler&quot;);</span>
<span class="nc" id="L218"> Thread thread = getThread();</span>
<span class="nc bnc" id="L219" title="All 2 branches missed."> if (thread != null)</span>
{
<span class="nc" id="L221"> thread.interrupt();</span>
}
<span class="nc" id="L223"> setEnabled(false);</span>
<span class="nc" id="L224"> }</span>
/**
* Return the thread being used to process commands, or null if there is no
* such thread. You can use this to invoke any special methods on the
* thread, for example, to interrupt it.
*
* @return A Thread.
*/
public synchronized Thread getThread()
{
<span class="nc" id="L235"> return houseKeepingThread;</span>
}
/**
* Set thread to null to indicate termination.
*/
protected synchronized void clearThread()
{
<span class="nc" id="L243"> houseKeepingThread = null;</span>
<span class="nc" id="L244"> }</span>
/**
* Start (or restart) a thread to process commands, or wake up an existing
* thread if one is already running. This method can be invoked if the
* background thread crashed due to an unrecoverable exception in an
* executed command.
*/
public synchronized void restart()
{
<span class="nc bnc" id="L254" title="All 2 branches missed."> if (enabled.get())</span>
{
<span class="nc" id="L256"> log.info(&quot;Starting job scheduler&quot;);</span>
<span class="nc bnc" id="L257" title="All 2 branches missed."> if (houseKeepingThread == null)</span>
{
// Create the the housekeeping thread of the scheduler. It will
// wait for the time when the next task needs to be started,
// and then launch a worker thread to execute the task.
<span class="nc" id="L262"> houseKeepingThread = new Thread(this::houseKeeping, ScheduleService.SERVICE_NAME);</span>
// Indicate that this is a system thread. JVM will quit only
// when there are no more enabled user threads. Settings threads
// spawned internally by Turbine as daemons allows commandline
// applications using Turbine to terminate in an orderly manner.
<span class="nc" id="L267"> houseKeepingThread.setDaemon(true);</span>
<span class="nc" id="L268"> houseKeepingThread.start();</span>
}
else
{
<span class="nc" id="L272"> notify();</span>
}
}
<span class="nc" id="L275"> }</span>
/**
* Return the next Job to execute, or null if thread is interrupted.
*
* @return A JobEntry.
* @throws TurbineException
* a generic exception.
*/
protected synchronized JobEntry nextJob() throws TurbineException
{
try
{
<span class="nc bnc" id="L288" title="All 2 branches missed."> while (!Thread.interrupted())</span>
{
// Grab the next job off the queue.
//JobEntry je = scheduleQueue.getNext();
<span class="nc" id="L292"> JobEntry je = scheduleQueue.getFirst();</span>
<span class="nc bnc" id="L294" title="All 2 branches missed."> if (je == null)</span>
{
// Queue must be empty. Wait on it.
<span class="nc" id="L297"> wait();</span>
}
else
{
<span class="nc" id="L301"> long now = System.currentTimeMillis();</span>
<span class="nc" id="L302"> long when = je.getNextRuntime();</span>
<span class="nc bnc" id="L304" title="All 2 branches missed."> if (when &gt; now)</span>
{
// Wait till next runtime.
<span class="nc" id="L307"> wait(when - now);</span>
}
else
{
// Update the next runtime for the job.
<span class="nc" id="L312"> scheduleQueue.updateQueue(je);</span>
// Return the job to run it.
<span class="nc" id="L314"> return je;</span>
}
}
<span class="nc" id="L317"> }</span>
}
<span class="nc" id="L319"> catch (InterruptedException ex)</span>
{
// ignore
<span class="nc" id="L322"> }</span>
// On interrupt.
<span class="nc" id="L325"> return null;</span>
}
/**
* Create the the housekeeping thread of the scheduler. It will
* wait for the time when the next task needs to be started,
* and then launch a worker thread to execute the task.
*/
private void houseKeeping()
{
<span class="nc" id="L335"> String taskName = null;</span>
try
{
<span class="nc bnc" id="L338" title="All 2 branches missed."> while (enabled.get())</span>
{
<span class="nc" id="L340"> JobEntry je = nextJob();</span>
<span class="nc bnc" id="L341" title="All 2 branches missed."> if (je != null)</span>
{
<span class="nc" id="L343"> taskName = je.getTask();</span>
// Get a thread to run the job.
<span class="nc" id="L346"> threadPool.execute(new WorkerThread(je));</span>
}
else
{
break;
}
<span class="nc" id="L352"> }</span>
}
<span class="nc" id="L354"> catch (Exception e)</span>
{
<span class="nc" id="L356"> log.error(&quot;Error running a Scheduled Job: {}&quot;, taskName, e);</span>
<span class="nc" id="L357"> setEnabled(false);</span>
}
finally
{
<span class="nc" id="L361"> clearThread();</span>
}
<span class="nc" id="L363"> }</span>
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.12.202403310830</span></div></body></html>