package com.dgrid.transport; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Random; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.dgrid.errors.TransportException; import com.dgrid.gen.Host; import com.dgrid.gen.InvalidApiKey; import com.dgrid.gen.InvalidHost; import com.dgrid.gen.InvalidJobId; import com.dgrid.gen.InvalidJobletId; import com.dgrid.gen.JOB_CALLBACK_TYPES; import com.dgrid.gen.JOB_STATUS; import com.dgrid.gen.Job; import com.dgrid.gen.Joblet; import com.dgrid.gen.JobletResult; import com.dgrid.gen.NoWorkAvailable; import com.dgrid.handlers.CallbackJobletTypeHandler; import com.dgrid.service.DGridClient; import com.dgrid.service.DGridTransport; import com.dgrid.util.io.HostnameDiscovery; public class DGridDummyTransport implements DGridTransport { private Log log = LogFactory.getLog(getClass()); private DGridClient gridClient; private List<Joblet> workQueue = new ArrayList<Joblet>(); private Hashtable<Integer, Joblet> activeQueue = new Hashtable<Integer, Joblet>(); private Hashtable<Integer, Job> jobs = new Hashtable<Integer, Job>(); private Hashtable<Integer, JobletResult> results = new Hashtable<Integer, JobletResult>(); private Hashtable<String, Host> hosts = new Hashtable<String, Host>(); private Random random = new Random(); public void setGridClient(DGridClient gridClient) { this.gridClient = gridClient; } public void setApiKey(String apiKey) { } public void setEndpoint(String endpoint) { } public void setPort(int port) { } public Host registerHost(String hostname) throws TransportException, InvalidApiKey, InvalidHost { Host h = hosts.get(hostname); if (h == null) { h = new Host(random.nextInt(), hostname, new HashMap<String, String>()); hosts.put(hostname, h); } return h; } public Host getHost(int id) throws TransportException, InvalidApiKey, InvalidHost { for (Host h : hosts.values()) { if (h.getId() == id) return h; } throw new InvalidHost(); } public Host getHostByName(String hostname) throws TransportException, InvalidApiKey, InvalidHost { Host h = hosts.get(hostname); if (h == null) throw new InvalidHost(); return h; } public void setHostFacts(int hostid, Map<String, String> facts) throws TransportException, InvalidApiKey, InvalidHost { } public String getHostSetting(int hostid, String name, String defaultValue) throws TransportException, InvalidApiKey, InvalidHost { return defaultValue; } public String getSetting(String name, String defaultValue) throws TransportException, InvalidApiKey { return defaultValue; } public void log(int jobletId, int jobletStatus, String message) throws TransportException, InvalidApiKey, InvalidJobletId { log.info(String.format("log(%1$d, %2$d, %3$s", jobletId, jobletStatus, message)); } public JobletResult gridExecute(Joblet joblet, int retries) throws InvalidApiKey { log.debug("Dummy transport doing gridExecute()"); return gridClient.execute(joblet); } public void completeJoblet(int jobletId, JobletResult result, String message) throws TransportException, InvalidApiKey, InvalidJobletId { Joblet j = activeQueue.get(jobletId); if (j == null) throw new InvalidJobletId(); j.setStatus(result.getStatus()); activeQueue.remove(jobletId); result.setJoblet(j); results.put(jobletId, result); // complete job if all joblets completed Job job = jobs.get(j.getJobId()); boolean finished = true; boolean failed = false; for (Joblet joblet : job.getJoblets()) { if ((joblet.getStatus() == JOB_STATUS.PROCESSING) || (joblet.getStatus() == JOB_STATUS.QUEUED) || (joblet.getStatus() == JOB_STATUS.RECEIVED)) { finished = false; break; } else if (joblet.getStatus() == JOB_STATUS.FAILED) failed = true; } if (finished) { int status = (failed) ? JOB_STATUS.FAILED : JOB_STATUS.COMPLETED; job.setStatus(status); try { if (job.getCallbackType() != 0) executeCallback(job); } catch (InvalidJobId e) { log.warn("Could not call executeCallback()", e); } } } public Job getJob(int jobId) throws TransportException, InvalidApiKey, InvalidJobId { Job j = jobs.get(jobId); if (j == null) throw new InvalidJobId(); return j; } public int getJobletQueueSize() throws TransportException, InvalidApiKey { return workQueue.size(); } public List<Joblet> listActiveJoblets(String submitter, int offset, int limit) throws TransportException, InvalidApiKey { log.trace("getJobletQueueSize()"); List<Joblet> results = new ArrayList<Joblet>(); for (Joblet joblet : workQueue) { if (submitter != null) { if (joblet.getSubmitter().equals(submitter)) results.add(joblet); } else { results.add(joblet); } // don't worry about offset if (results.size() >= limit) break; } return results; } public JobletResult getJobletResult(int jobletId) throws TransportException, InvalidApiKey, InvalidJobletId { JobletResult jr = results.get(jobletId); if (jr == null) throw new InvalidJobletId(); return jr; } public List<JobletResult> getResults(int jobId) throws TransportException, InvalidApiKey, InvalidJobId { List<JobletResult> values = new LinkedList<JobletResult>(); Enumeration<JobletResult> e = results.elements(); while (e.hasMoreElements()) { JobletResult jr = e.nextElement(); if (jr.getJoblet().getJobId() == jobId) values.add(jr); } return values; } public Joblet getWork() throws TransportException, InvalidApiKey, InvalidHost, NoWorkAvailable { try { Joblet joblet = workQueue.remove(0); activeQueue.put(joblet.getId(), joblet); return joblet; } catch (IndexOutOfBoundsException e) { throw new NoWorkAvailable(); } } public void releaseJoblet(int jobletId) throws InvalidApiKey, TransportException, InvalidJobletId { Joblet j = activeQueue.get(jobletId); if (j == null) throw new InvalidJobletId(); j.setStatus(JOB_STATUS.QUEUED); workQueue.add(j); } public Job submitHostJob(String hostname, Job job) throws TransportException, InvalidHost, InvalidApiKey { return submitJob(job); } public Joblet submitHostJoblet(String hostname, Joblet joblet, int jobId, int callbackType, String callbackAddress, String callbackContent) throws TransportException, InvalidApiKey, InvalidJobId, InvalidHost { return submitJoblet(joblet, jobId, callbackType, callbackAddress, callbackContent); } public Job submitJob(Job job) throws TransportException, InvalidApiKey { job.setId(random.nextInt()); jobs.put(job.getId(), job); for (Joblet joblet : job.getJoblets()) { joblet.setId(random.nextInt()); joblet.setJobId(job.getId()); workQueue.add(joblet); } return job; } public Joblet submitJoblet(Joblet joblet, int jobId, int callbackType, String callbackAddress, String callbackContent) throws TransportException, InvalidApiKey, InvalidJobId { Job j = null; if (jobId != 0) { j = getJob(jobId); } else { j = new Job(random.nextInt(), 0l, joblet.getSubmitter(), joblet .getDescription(), new ArrayList<Joblet>(1), 0, "", "", JOB_STATUS.QUEUED); joblet.setJobId(j.getId()); jobs.put(j.getId(), j); } joblet.setJobId(j.getId()); joblet.setId(random.nextInt()); j.getJoblets().add(joblet); workQueue.add(joblet); return joblet; } private void executeCallback(Job job) throws TransportException, InvalidApiKey, InvalidJobId { Map<String, String> params = new HashMap<String, String>(); params.put("jobId", Integer.toString(job.getId())); params.put("jobStatus", Integer.toString(job.getStatus())); params.put("callbackType", Integer.toString(job.getCallbackType())); params.put("callbackAddress", job.getCallbackAddress()); Joblet callbackJoblet = new Joblet(0, 0l, 0, 0, job.getSubmitter(), 2, CallbackJobletTypeHandler.TYPE, "Completion callback", params, "", job.getStatus()); this.submitJoblet(callbackJoblet, 0, JOB_CALLBACK_TYPES.NONE, "", ""); } private String getHostname() { return HostnameDiscovery.getHostname(); } }