/**
* Copyright (c) 2008--2015 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.satellite.search.scheduler;
import com.redhat.satellite.search.config.Configuration;
import com.redhat.satellite.search.db.DatabaseManager;
import com.redhat.satellite.search.index.builder.BuilderFactory;
import com.redhat.satellite.search.index.IndexManager;
import com.redhat.satellite.search.scheduler.tasks.IndexErrataTask;
import com.redhat.satellite.search.scheduler.tasks.IndexPackagesTask;
import com.redhat.satellite.search.scheduler.tasks.IndexSnapshotTagsTask;
import com.redhat.satellite.search.scheduler.tasks.IndexServerCustomInfoTask;
import com.redhat.satellite.search.scheduler.tasks.IndexSystemsTask;
import com.redhat.satellite.search.scheduler.tasks.IndexHardwareDevicesTask;
import com.redhat.satellite.search.scheduler.tasks.IndexXccdfIdentTask;
import org.apache.log4j.Logger;
import org.picocontainer.Startable;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import java.util.Date;
/**
* Manages all scheduled tasks for the search server
* Right now all tasks are hardcoded -- this should be
* changed to be more config file driven
*
* @version $Rev $
*/
public class ScheduleManager implements Startable {
private static Logger log = Logger.getLogger(ScheduleManager.class);
private Scheduler scheduler;
private DatabaseManager databaseManager;
private IndexManager indexManager;
private final String updateIndexGroupName = "updateIndex";
/**
* Constructor
* @param dbmgr allows ScheduleManager to access the database.
* @param idxmgr allows the ScheduleManager to access the indexer.
*/
public ScheduleManager(DatabaseManager dbmgr, IndexManager idxmgr) {
databaseManager = dbmgr;
indexManager = idxmgr;
try {
scheduler = StdSchedulerFactory.getDefaultScheduler();
}
catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
private void scheduleJob(Scheduler sched, String name,
int mode, long interval, Class task, JobDataMap data)
throws SchedulerException {
Trigger t = createTrigger(name, updateIndexGroupName, mode, interval);
JobDetail d = new JobDetail(name, updateIndexGroupName, task);
d.setJobDataMap(data);
sched.scheduleJob(d, t);
}
private Trigger createTrigger(String name, String group, int mode,
long interval) {
Trigger trigger = new SimpleTrigger(name, "default", name, group,
new Date(), null, mode, interval);
trigger.setMisfireInstruction(
SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT);
return trigger;
}
/**
* {@inheritDoc}
*/
public void start() {
try {
Configuration config = new Configuration();
long interval = config.getInt("search.schedule.interval", 300000);
log.info("ScheduleManager task interval is set to " + interval);
int mode = SimpleTrigger.REPEAT_INDEFINITELY;
if (System.getProperties().get("isTesting") != null) {
interval = 100;
mode = 0;
}
JobDataMap jobData = new JobDataMap();
jobData.put("indexManager", indexManager);
jobData.put("databaseManager", databaseManager);
jobData.put("configuration", new Configuration());
scheduleJob(scheduler, BuilderFactory.PACKAGES_TYPE,
mode, interval,
IndexPackagesTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.ERRATA_TYPE,
mode, interval,
IndexErrataTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.SERVER_TYPE,
mode, interval,
IndexSystemsTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.HARDWARE_DEVICE_TYPE,
mode, interval,
IndexHardwareDevicesTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.SNAPSHOT_TAG_TYPE,
mode, interval,
IndexSnapshotTagsTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.SERVER_CUSTOM_INFO_TYPE,
mode, interval,
IndexServerCustomInfoTask.class, jobData);
scheduleJob(scheduler, BuilderFactory.XCCDF_IDENT_TYPE,
mode, interval,
IndexXccdfIdentTask.class, jobData);
scheduler.start();
}
catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
/**
* {@inheritDoc}
*/
public void stop() {
try {
scheduler.shutdown();
}
catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
private boolean isSupported(String indexName) {
if (BuilderFactory.ERRATA_TYPE.equals(indexName) ||
BuilderFactory.HARDWARE_DEVICE_TYPE.equals(indexName) ||
BuilderFactory.PACKAGES_TYPE.equals(indexName) ||
BuilderFactory.SERVER_CUSTOM_INFO_TYPE.equals(indexName) ||
BuilderFactory.SERVER_TYPE.equals(indexName) ||
BuilderFactory.SNAPSHOT_TAG_TYPE.equals(indexName) ||
BuilderFactory.XCCDF_IDENT_TYPE.equals(indexName)) {
return true;
}
else if (BuilderFactory.DOCS_TYPE.equals(indexName)) {
log.info("Index updates for " + BuilderFactory.DOCS_TYPE +
" are not supported.");
return false;
}
log.info("Unknown index: " + indexName);
return false;
}
/**
* Will create/schedule a trigger for the passed in indexName.
* Note: Only one trigger per indexName is allowed, if subsequent calls
* are made before the current trigger finishes completion, this request
* will be dropped.
* @param indexName
* @return
*/
public boolean triggerIndexTask(String indexName) {
if (!isSupported(indexName)) {
log.info(indexName + " is not a supported for scheduler modifications.");
return false;
}
// Define a Trigger that will fire "now" and associate it with the existing job
Trigger trigger = new SimpleTrigger("immediateTrigger-" + indexName,
"group1", new Date());
trigger.setJobName(indexName);
trigger.setJobGroup(updateIndexGroupName);
try {
// Schedule the trigger
log.info("Scheduling trigger: " + trigger);
scheduler.scheduleJob(trigger);
}
catch (SchedulerException e) {
log.warn("Scheduling trigger: " + trigger + " failed.");
log.warn("Exception was caught: ", e);
return false;
}
return true;
}
}