package com.dgrid.service.impl; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; 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.Joblet; import com.dgrid.gen.NoWorkAvailable; import com.dgrid.service.DGridClient; import com.dgrid.service.DGridExecutorService; import com.dgrid.service.DGridPluginManager; import com.dgrid.service.DGridProcessor; import com.dgrid.threads.DGridRunnable; import com.dgrid.threads.DGridTaskListener; import com.dgrid.util.io.HostnameDiscovery; public class DGridProcessorImpl implements Runnable, DGridProcessor, DGridTaskListener { private Log log = LogFactory.getLog(getClass()); private DGridExecutorService executor; private DGridClient client; private DGridPluginManager pluginMgr; private int threadsPerCore = 1; private int maxCpuCores = 0; private int threadCount = 1; private long sleepTime = 30000; private Object lock = new Object(); public void setPluginManager(DGridPluginManager mgr) { this.pluginMgr = mgr; } public void setGridClient(DGridClient client) { this.client = client; } public void setThreadPool(DGridExecutorService service) { this.executor = service; } public void setSleepTime(long sleepTimeMillis) { this.sleepTime = sleepTimeMillis; } public void setThreadsPerCore(int threadsPerCore) { this.threadsPerCore = threadsPerCore; } public void setMaxCpuCores(int maxCpuCores) { this.maxCpuCores = maxCpuCores; } public void init() throws Exception { log.trace("init()"); this.threadCount = getThreadCount(); // call this before initializing plugins // want to guarantee that getHost() returns a valid host Host host = client.registerHost(HostnameDiscovery.getHostname()); Map<String, String> facts = new HashMap<String, String>(1); facts.put("threads.total", Integer.toString(threadCount)); facts.put("threads.perCore", Integer.toString(threadsPerCore)); client.setHostFacts(host.getId(), facts); pluginMgr.init(); pluginMgr.start(); executor.addListener(this); } public void stop() { log.trace("stop()"); try { executor.shutdown(); // Disable new tasks from being submitted // Wait a while for existing tasks to terminate log.info("Waiting two minutes for existing tasks to stop"); if (!executor.awaitTermination(120, TimeUnit.SECONDS)) { // Cancel currently executing tasks executor.shutdownNow(); log.info("Waiting for tasks to cancel"); // Wait a while for tasks to respond to being cancelled if (!executor.awaitTermination(60, TimeUnit.SECONDS)) log.error("Pool did not terminate"); } } catch (InterruptedException ie) { // (Re-)Cancel if current thread also interrupted executor.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } pluginMgr.stop(); } public void run() { log.trace("run()"); for (;;) { try { synchronized (lock) { int activeCount = executor.getActiveCount(); if (activeCount >= threadCount) { if (log.isDebugEnabled()) { log.debug(String.format( "activeCount (%1$d) >= threadCount (%2$d)", activeCount, threadCount)); } if (log.isDebugEnabled()) log.debug("Calling wait() on lock object"); try { lock.wait(sleepTime); if (log.isDebugEnabled()) log.debug("wait() ended"); } catch (IllegalMonitorStateException e) { log .warn( "IllegalMonitorStateException caught calling wait()", e); } catch (InterruptedException e) { log.warn("InterruptedException calling wait()", e); } continue; } } Joblet joblet = client.getWork(); DGridRunnable r = new DGridRunnable(client, joblet); executor.submit(r); } catch (NoWorkAvailable e) { if (log.isDebugEnabled()) { log.debug("No work available"); } sleep(); } catch (TransportException e) { log.error("TransportException in run() loop", e); sleep(); } catch (Exception e) { log.error("Exception in run() loop", e); } } } public void beforeExecute(Thread t, Runnable r, int activeThreadCount, int maxThreadCount) { log.trace("beforeExecute()"); } public void afterExecute(Runnable r, Throwable t, int activeThreadCount, int maxThreadCount) { log.trace("afterExecute()"); synchronized (lock) { try { lock.notify(); } catch (IllegalMonitorStateException e) { log .warn( "IllegalMonitorStateException caught in taskCompleted()", e); } } } public DGridClient getGridClient() { log.trace("getGridClient()"); return client; } private int getThreadCount() { if (maxCpuCores > 0) { return maxCpuCores * threadsPerCore; } else { return Runtime.getRuntime().availableProcessors() * threadsPerCore; } } private void sleep() { log.trace("sleep()"); if (log.isDebugEnabled()) { log.debug(String.format("Sleeping for %1$d millis", sleepTime)); } try { Thread.sleep(sleepTime); } catch (InterruptedException e) { log.warn("InterruptedException in sleep()", e); } } }