/* * $Id$ * * Copyright 2007 Glencoe Software, Inc. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.services.procs; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import ome.api.JobHandle; import ome.model.IObject; import ome.model.jobs.Job; import ome.model.jobs.JobStatus; import ome.parameters.Parameters; import ome.security.SecureAction; import ome.security.SecuritySystem; import ome.services.sessions.SessionManager; import ome.services.util.ExecutionThread; import ome.services.util.Executor; import ome.system.Principal; import ome.system.ServiceFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.hibernate.Session; /** * * @author Josh Moore, josh at glencoesoftware.com * @since 3.0-Beta2 */ public class ProcessManager extends ExecutionThread implements IProcessManager { /** * Task performed by the {@link ProcessManager} on each invocation of * {@link ProcessManager#run()}. */ public static class Work implements Executor.Work { /** * processors available for processing. This array will never be null. */ final protected List<Processor> processors; /** * {@link SecuritySystem} in order to perform a secure save on the * {@link Job} instance. */ final protected SecuritySystem sec; /** * Map of all active {@link Process processes}. */ protected Map<Long, Process> procMap = Collections .synchronizedMap(new HashMap<Long, Process>()); public Work(SecuritySystem sec, Processor... procs) { this.sec = sec; if (procs == null) { this.processors = new ArrayList<Processor>(); } else { this.processors = Arrays.asList(procs); } } public String description() { return "ProcessManager"; } public List<Job> doWork(Session session, ServiceFactory sf) { final List<Job> jobs = sf.getQueryService().findAllByQuery( "select j from Job j where status.id = :id", new Parameters().addId(getSubmittedStatus(sf).getId())); for (Job job : jobs) { startProcess(sf, job.getId()); } return null; } /** * */ public void startProcess(final ServiceFactory sf, final long jobId) { Process p = null; for (Processor proc : processors) { p = proc.process(jobId); // Take first processor if (p != null) { break; } } if (p == null) { if (log.isWarnEnabled()) { log.warn("No processor found for job:" + jobId); } Job job = job(sf, jobId); job.setStatus(getWaitingStatus(sf)); job.setMessage("No processor found for job."); sec.doAction(new SecureAction() { public <T extends IObject> T updateObject(T... objs) { return sf.getUpdateService().saveAndReturnObject( objs[0]); } }, job); } else { procMap.put(jobId, p); } } // Helpers ~ // ========================================================================= protected Job job(ServiceFactory sf, long id) { Job job = sf.getQueryService().find(Job.class, id); return job; } private JobStatus getStatus(ServiceFactory sf, String status) { JobStatus statusObj = sf.getTypesService().getEnumeration( JobStatus.class, status); return statusObj; } private JobStatus getSubmittedStatus(ServiceFactory sf) { return getStatus(sf, JobHandle.SUBMITTED); } private JobStatus getWaitingStatus(ServiceFactory sf) { return getStatus(sf, JobHandle.WAITING); } } // End Work // // ProcessManager // private static Logger log = LoggerFactory.getLogger(ProcessManager.class); private static Principal PRINCIPAL = new Principal("root", "user", "Processing"); /** * main constructor which takes a non-null array of {@link Processor} * instances as its only argument. This array is copied, so modifications * will not be noticed. * * @param manager * Reference to the session manager. * @param sec * Reference to the security manager * @param executor * The executor. * @param procs * Array of Processors. Not null. */ public ProcessManager(SessionManager manager, SecuritySystem sec, Executor executor, Processor... procs) { super(manager, executor, new Work(sec, procs), PRINCIPAL); } // Main methods ~ // ========================================================================= @Override @SuppressWarnings("unchecked") public void doRun() { if (log.isDebugEnabled()) { log.debug("Starting processing..."); } try { this.executor.execute(getPrincipal(), this.work); } catch (Exception e) { if (log.isErrorEnabled()) { log.error("Error while processing", e); } } if (log.isDebugEnabled()) { log.debug("Finished processing..."); } } public Process runningProcess(long jobId) { Process p = ((Work) work).procMap.get(jobId); return p; } }