org.dashbuilder.scheduler.Scheduler Maven / Gradle / Ivy
/**
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "AS IS" 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.
*/
package org.dashbuilder.scheduler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Task scheduler component.
* It uses internally an instance of java.util.concurrent.ScheduledThreadPoolExecutor
* which provides a thread pool and the delayed task execution capability.
*/
public class Scheduler {
private Logger log = LoggerFactory.getLogger(Scheduler.class);
protected PausableThreadPoolExecutor executor;
protected ThreadFactory threadFactory;
protected Map scheduledTasks = Collections.synchronizedMap(new HashMap());
protected int maxThreadPoolSize;
public void init(int maxThreadPoolSize) {
this.maxThreadPoolSize = maxThreadPoolSize;
this.threadFactory = new SchedulerThreadFactory();
this.executor = new PausableThreadPoolExecutor(maxThreadPoolSize, threadFactory);
this.executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
this.executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
log.debug("Scheduler started [pool size=" + maxThreadPoolSize + "].");
}
public void shutdown() {
log.debug("Scheduler shutdown started.");
executor.shutdown();
log.debug("Scheduler shutdown completed.");
}
public int getMaxThreadPoolSize() {
return maxThreadPoolSize;
}
public void setMaxThreadPoolSize(int maxThreadPoolSize) {
this.maxThreadPoolSize = maxThreadPoolSize;
if (executor != null) executor.setCorePoolSize(maxThreadPoolSize);
}
public int getThreadPoolSize() {
return executor.getPoolSize();
}
public ThreadFactory getThreadFactory() {
return threadFactory;
}
public void setThreadFactory(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
}
public int getNumberOfScheduledTasks() {
return scheduledTasks.size();
}
public int getNumberOfScheduledTasksInQueue() {
return executor.getQueue().size();
}
public SchedulerTask getTaskByKey(String key) {
for (SchedulerTask task : scheduledTasks.values()) {
if (task.getKey().equals(key)) {
return task;
}
}
return null;
}
public List getScheduledTasks() {
return new ArrayList(scheduledTasks.values());
}
public List getRunningTasks() {
List result = new ArrayList();
for (SchedulerTask task : scheduledTasks.values()) {
if (task.isRunning()) result.add(task);
}
return result;
}
public List getMisfiredTasks() {
List result = new ArrayList();
for (SchedulerTask task : scheduledTasks.values()) {
if (task.isMisfired()) result.add(task);
}
return result;
}
public List getWaitingTasks() {
List result = new ArrayList();
for (SchedulerTask task : scheduledTasks.values()) {
if (!task.isDone() && !task.isRunning() && !task.isMisfired()) result.add(task);
}
return result;
}
// Transactional operations
public void pause() {
executor.pause();
}
public void resume() {
executor.resume();
}
public boolean isPaused() {
return executor.isPaused();
}
public synchronized void execute(SchedulerTask task) {
try {
_schedule(task, null);
} catch (Exception e) {
log.error("Execute call failed for task: " + task.getKey(), e);
}
}
public synchronized void schedule(SchedulerTask task, Date date) {
try {
_schedule(task, date);
} catch (Exception e) {
log.error("Schedule call failed for task: " + task.getKey(), e);
}
}
public synchronized void schedule(SchedulerTask task, long seconds) {
try {
_schedule(task, seconds);
} catch (Exception e) {
log.error("Schedule call failed for task: " + task.getKey(), e);
}
}
public synchronized void unschedule(final String key) {
try {
_unschedule(key);
} catch (Exception e) {
log.error("Unschedule call failed for task: " + key, e);
}
}
public synchronized void unscheduleAll() {
try {
_unscheduleAll();
} catch (Exception e) {
log.error("Unschedule all call failed.", e);
}
}
public synchronized void fireTask(String key) {
SchedulerTask task = scheduledTasks.get(key);
if (task != null && !task.isDone() && !task.isRunning()) {
try {
task.run();
log.debug("Task " + task + " executed.");
} finally {
scheduledTasks.remove(key);
task.cancel();
_purge();
// Re-schedule fixed delay (repetitive) tasks after issue a fire.
if (task.isFixedDelay()) {
schedule(task, task.getFixedDelaySeconds());
}
}
}
}
// Scheduler business logic
protected void _schedule(SchedulerTask task, Date date) {
// Calculate the delay.
// Never use a delay=0 in order to force the task to be launched in a separated thread.
long delay = 10000;
if (date != null) {
Date now = new Date();
delay = date.getTime() - now.getTime();
if (delay <= 0) throw new IllegalArgumentException("Delay is negative. The task can not be scheduled [" + task.toString() + "] Date=" + date);
}
// Remove any old task (if any)
_unschedule(task.getKey());
// Register the new task.
task.future = executor.schedule(task, delay, TimeUnit.MILLISECONDS);
scheduledTasks.put(task.getKey(), task);
if (date == null) log.debug("Task " + task + " execution requested.");
else log.debug("Task " + task + " scheduled to: " + date);
}
protected void _schedule(SchedulerTask task, long seconds) {
// Remove any old task (if any)
_unschedule(task.getKey());
// Register the new task.
task.fixedDelay = true;
task.fixedDelaySeconds = seconds;
task.future = executor.scheduleWithFixedDelay(task, seconds, seconds, TimeUnit.SECONDS);
scheduledTasks.put(task.getKey(), task);
log.debug("Task " + task + " scheduled every " + seconds + " seconds.");
}
protected void _unschedule(String key) {
SchedulerTask task = scheduledTasks.remove(key);
if (task != null && !task.isDone() && !task.isRunning()) {
task.cancel();
_purge();
log.debug("Task " + task + " unscheduled.");
}
}
public void _unscheduleAll() {
Collection tasks = scheduledTasks.values();
for (SchedulerTask task : tasks) {
if (task != null && !task.isDone() && !task.isRunning()) {
task.cancel();
}
}
executor.purge();
scheduledTasks.clear();
log.debug("All tasks unscheduled.");
}
protected void _purge() {
executor.purge();
Iterator it = scheduledTasks.values().iterator();
while (it.hasNext()) {
SchedulerTask task = it.next();
if (task.isDone()) {
it.remove();
log.debug("Task " + task + " purged.");
}
}
}
public String printScheduledTasksReport() {
Map
© 2015 - 2024 Weber Informatics LLC | Privacy Policy