package com.stella.framework.scheduler;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import com.stella.framework.job.Job;
import com.stella.framework.job.JobStatus;
import com.stella.framework.queue.JobReadyQueue;
public class RunSchedulerImpl implements RunScheduler {
private static final Logger logger = Logger.getLogger(RunSchedulerImpl.class);
private Set<Job> jobs;
private RunSchedulerQueue runQueue;
private JobReadyQueue readyQueue;
public RunSchedulerImpl(JobReadyQueue jobQueue) {
jobs = new HashSet<Job>();
readyQueue = jobQueue;
}
public void notifyJobCompletion(Job job) {
runQueue.removeRunningJob(job);
if(logger.isDebugEnabled()) {
dumpStatus();
dumpReadyQueue();
}
}
public void notifyJobReady(Job job) {
readyQueue.addJob(job);
job.setStatus(JobStatus.QUEUED);
if(logger.isDebugEnabled()) {
dumpStatus();
dumpReadyQueue();
}
}
public Collection<Job> getJobs() {
return Collections.unmodifiableCollection(jobs);
}
public synchronized void addJob(Job job) {
job.setRunScheduler(this);
jobs.add(job);
}
public synchronized int numberOfJobs() {
return jobs.size();
}
private void dumpStatus() {
logger.debug("-----------------JOB_STATUS-----------------");
for(Job job : jobs) {
logger.debug(job.getName() + " = " + job.getStatus());
}
logger.debug("---------------------------------------------");
}
private void dumpReadyQueue() {
logger.debug("-----------------READY_QUEUE-----------------");
for(Job job : readyQueue.peekAtJobs()) {
logger.debug(job.getName() + " = " + job.getStatus());
}
logger.debug("---------------------------------------------");
}
private boolean checkIfAnyJobIsReady() {
for(Job job : jobs) {
if(job.getStatus() == JobStatus.READY ||
job.getStatus() == JobStatus.QUEUED) {
return true;
}
}
return false;
}
public synchronized void runBatch(final int numberOfConcurrentJobsAllowed) {
runQueue = new RunSchedulerQueue(this, numberOfConcurrentJobsAllowed);
// prime the ready queue
for(Job job : jobs) {
if(job.getStatus() == JobStatus.READY) {
notifyJobReady(job);
}
}
boolean batchIsExhausted = false;
while(batchIsExhausted != true) {
// TODO: make this use a semaphore
Job job = readyQueue.getNextJob();
if(job == null) {
if(runQueue.getRunningJobCount() <= 0) {
if(checkIfAnyJobIsReady() == false) {
logger.info("all queues exhausted.");
batchIsExhausted = true;
}
}
} else {
// this is blocking
if(runQueue.hasCapacity()) {
runQueue.addJob(job);
} else {
logger.error("*** WE SHOULD NEVER GET HERE** [" + job.getName() + "]");
}
}
}
runQueue.waitForCompletion();
dumpStatus();
}
}