/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
* *************************************************************************************
*/
package com.espertech.esper.core.thread;
import com.espertech.esper.client.ConfigurationEngineDefaults;
import com.espertech.esper.core.service.EPRuntimeImpl;
import com.espertech.esper.core.service.EPServicesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.concurrent.*;
/**
* Implementation for engine-level threading.
*/
public class ThreadingServiceImpl implements ThreadingService
{
private static final Log log = LogFactory.getLog(ThreadingServiceImpl.class);
private final ConfigurationEngineDefaults.Threading config;
private final boolean isTimerThreading;
private final boolean isInboundThreading;
private final boolean isRouteThreading;
private final boolean isOutboundThreading;
private BlockingQueue<Runnable> timerQueue;
private BlockingQueue<Runnable> inboundQueue;
private BlockingQueue<Runnable> routeQueue;
private BlockingQueue<Runnable> outboundQueue;
private ThreadPoolExecutor timerThreadPool;
private ThreadPoolExecutor inboundThreadPool;
private ThreadPoolExecutor routeThreadPool;
private ThreadPoolExecutor outboundThreadPool;
/**
* Ctor.
* @param threadingConfig configuration
*/
public ThreadingServiceImpl(ConfigurationEngineDefaults.Threading threadingConfig)
{
this.config = threadingConfig;
if (ThreadingOption.isThreadingEnabled())
{
isTimerThreading = threadingConfig.isThreadPoolTimerExec();
isInboundThreading = threadingConfig.isThreadPoolInbound();
isRouteThreading = threadingConfig.isThreadPoolRouteExec();
isOutboundThreading = threadingConfig.isThreadPoolOutbound();
}
else
{
isTimerThreading = false;
isInboundThreading = false;
isRouteThreading = false;
isOutboundThreading = false;
}
}
public boolean isRouteThreading()
{
return isRouteThreading;
}
public boolean isInboundThreading()
{
return isInboundThreading;
}
public boolean isTimerThreading()
{
return isTimerThreading;
}
public boolean isOutboundThreading()
{
return isOutboundThreading;
}
public void initThreading(EPServicesContext services, EPRuntimeImpl runtime)
{
if (isInboundThreading)
{
inboundQueue = makeQueue(config.getThreadPoolInboundCapacity());
inboundThreadPool = getThreadPool(services.getEngineURI(), "Inbound", inboundQueue, config.getThreadPoolInboundNumThreads());
}
if (isTimerThreading)
{
timerQueue = makeQueue(config.getThreadPoolTimerExecCapacity());
timerThreadPool = getThreadPool(services.getEngineURI(), "TimerExec", timerQueue, config.getThreadPoolTimerExecNumThreads());
}
if (isRouteThreading)
{
routeQueue = makeQueue(config.getThreadPoolRouteExecCapacity());
routeThreadPool = getThreadPool(services.getEngineURI(), "RouteExec", routeQueue, config.getThreadPoolRouteExecNumThreads());
}
if (isOutboundThreading)
{
outboundQueue = makeQueue(config.getThreadPoolOutboundCapacity());
outboundThreadPool = getThreadPool(services.getEngineURI(), "Outbound", outboundQueue, config.getThreadPoolOutboundNumThreads());
}
}
private BlockingQueue<Runnable> makeQueue(Integer threadPoolTimerExecCapacity)
{
if ((threadPoolTimerExecCapacity == null) ||
(threadPoolTimerExecCapacity <= 0) ||
(threadPoolTimerExecCapacity == Integer.MAX_VALUE))
{
return new LinkedBlockingQueue<Runnable>();
}
else
{
return new ArrayBlockingQueue<Runnable>(threadPoolTimerExecCapacity);
}
}
public void submitRoute(RouteUnitRunnable unit)
{
try
{
routeQueue.put(unit);
}
catch (InterruptedException e)
{
log.info("Submit interrupted:" + e);
}
}
public void submitInbound(InboundUnitRunnable unit)
{
try
{
inboundQueue.put(unit);
}
catch (InterruptedException e)
{
log.info("Submit interrupted:" + e);
}
}
public void submitOutbound(OutboundUnitRunnable unit)
{
try
{
outboundQueue.put(unit);
}
catch (InterruptedException e)
{
log.info("Submit interrupted:" + e);
}
}
public void submitTimerWork(TimerUnit unit)
{
try
{
timerQueue.put(unit);
}
catch (InterruptedException e)
{
log.info("Submit interrupted:" + e);
}
}
public BlockingQueue<Runnable> getOutboundQueue()
{
return outboundQueue;
}
public ThreadPoolExecutor getOutboundThreadPool()
{
return outboundThreadPool;
}
public BlockingQueue<Runnable> getRouteQueue()
{
return routeQueue;
}
public ThreadPoolExecutor getRouteThreadPool()
{
return routeThreadPool;
}
public BlockingQueue<Runnable> getTimerQueue()
{
return timerQueue;
}
public ThreadPoolExecutor getTimerThreadPool()
{
return timerThreadPool;
}
public BlockingQueue<Runnable> getInboundQueue()
{
return inboundQueue;
}
public ThreadPoolExecutor getInboundThreadPool()
{
return inboundThreadPool;
}
public void destroy()
{
if (timerThreadPool != null)
{
stopPool(timerThreadPool, timerQueue, "TimerExec");
}
if (routeThreadPool != null)
{
stopPool(routeThreadPool, routeQueue, "RouteExec");
}
if (outboundThreadPool != null)
{
stopPool(outboundThreadPool, outboundQueue, "Outbound");
}
if (inboundThreadPool != null)
{
stopPool(inboundThreadPool, inboundQueue, "Inbound");
}
}
private ThreadPoolExecutor getThreadPool(String engineURI, String name, BlockingQueue<Runnable> queue, int numThreads)
{
if (log.isInfoEnabled())
{
log.info("Starting pool " + name + " with " + numThreads + " threads");
}
if (engineURI == null)
{
engineURI = "default";
}
String threadGroupName = "com.espertech.esper." + engineURI + "-" + name;
ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
ThreadPoolExecutor pool = new ThreadPoolExecutor(numThreads, numThreads, 1, TimeUnit.SECONDS, queue, new EngineThreadFactory(engineURI, name, threadGroup, Thread.NORM_PRIORITY));
pool.prestartAllCoreThreads();
return pool;
}
public Thread makeEventSourceThread(String engineURI, String sourceName, Runnable runnable) {
if (engineURI == null)
{
engineURI = "default";
}
String threadGroupName = "com.espertech.esper." + engineURI + "-source-" + sourceName;
ThreadGroup threadGroup = new ThreadGroup(threadGroupName);
return new Thread(threadGroup, runnable);
}
private void stopPool(ThreadPoolExecutor threadPool, BlockingQueue<Runnable> queue, String name)
{
if (log.isInfoEnabled())
{
log.info("Shutting down pool " + name);
}
queue.clear();
threadPool.shutdown();
try
{
threadPool.awaitTermination(10, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
log.error("Interruped awaiting termination", e);
}
}
}