/*
* File: BasicJobManager.java
* Author: Daniel Rogers
* Created on Jan 4, 2010
*
*/
package gri.tasks.managers;
import gri.tasks.TaskDef;
import gri.tasks.AsyncTask;
import gri.tasks.AsyncTaskController;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
/**
* Basic implementation of a JobManager which exposes tasks from
* a TaskManager. The job manager allows these jobs to be executed
* asynchronously. Job ID's are created and stored here along with
* other information on running jobs.
*
* @author rogersda
*/
public class BasicJobManager implements JobManager {
TaskManager tasks;
Map jobs;
// --------------------------------------------- Constructors
public BasicJobManager(TaskManager tasks) {
this.tasks = tasks;
this.jobs = new HashMap(100);
}
public BasicJobManager(TaskCollection tasks) {
this(new BasicTaskManager(tasks));
}
// ------------------------------------------------ Accessors
public TaskManager getTaskManager() {return tasks;}
// -------------------------------------------------- JobInfo
public String [] getTaskIds() {
return tasks.getTaskIds();
}
public TaskDescription getTaskDescription(String id) {
return tasks.getTaskDescription(id);
}
public TaskDef getTaskDefinition(String id) {
return tasks.getTaskDefinition(id);
}
// --------------------------------------------- Running Jobs
public String submitJob(JobSubmission submission) throws Exception {
AsyncTask task = tasks.getAsyncTask(submission.getTaskId());
//NOTE: This is first so that we can easily throw UnknownTaskExceptions
String jobId = createJobId(); //TODO: synchronize and error check until jobs.put()?
AsyncTaskController controller = task.start(
submission.getInputs(),
submission.getEventHandler());
JobEntry jobEntry = new JobEntry(jobId, submission, controller);
jobs.put(jobId, jobEntry);
return jobId;
}
public JobEntry getJobEntry(String jobId) throws UnknownJobException {
JobEntry entry = (JobEntry)jobs.get(jobId);
if (entry == null)
throw new UnknownJobException(jobId);
return entry;
}
public AsyncTaskController getJobController(String jobId) throws UnknownJobException {
JobEntry entry = getJobEntry(jobId);
return entry.getController();
}
public JobInfo getJobInfo(String jobId) throws UnknownJobException {
JobEntry entry = getJobEntry(jobId);
return entry.getJobInfo();
}
public JobInfo [] listJobs() {
List list = new ArrayList(jobs.size());
Iterator iJobEntries = jobs.entrySet().iterator();
JobEntry jobEntry;
while (iJobEntries.hasNext()) {
jobEntry = (JobEntry)iJobEntries.next();
list.add(jobEntry.getJobInfo());
}
return (JobInfo [])list.toArray(new JobInfo [list.size()]);
}
/**
* Frees the job. This calls "free()" on the task controller and
* will delete our reference to the job.
*/
public void freeJob(String jobId) throws UnknownJobException {
JobEntry entry = getJobEntry(jobId);
entry.getController().free();
jobs.remove(entry); //TODO: optimize this
}
/**
* Creates a unique job ID from the system's current time.
* TODO: make this better, ensure no collisions
*
* NOTE: The id is added to the job map with a NULL value.
* If the job is not actually submitted successfuly we
* need to free this id.
*/
protected String createJobId() {
long time = System.currentTimeMillis();
String id = String.valueOf(time);
while (jobs.containsKey(id)) {
time++;
id = String.valueOf(time);
}
jobs.put(id, null);
return id;
}
// -------------------------------------------- Inner Classes
static class JobEntry {
String jobId;
JobSubmission submission;
AsyncTaskController controller;
public JobEntry(String jobId, JobSubmission submission, AsyncTaskController controller) {
this.jobId = jobId;
this.submission = submission;
this.controller = controller;
}
public String getJobId() {return jobId;}
public JobSubmission getJobSubmission() {return submission;}
public AsyncTaskController getController() {return controller;}
public JobInfo getJobInfo() {
return new JobInfo(
getJobId(),
getJobSubmission().getTaskId(),
controller.getStatus());
}
}
}