package org.apache.thrift.server;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.thrift.TException;
import org.apache.thrift.TProcessor;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.TTransportFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cloudera.flume.handlers.thrift.TStatsTransport;
private static final Logger LOGGER = LoggerFactory
.getLogger(TSaneThreadPoolServer.class);
private Object maplock = new Object();
private Map<Long, WorkerProcess> map = new HashMap<Long, WorkerProcess>();
private long doneBytesRead = 0;
private long doneBytesWritten = 0;
protected TProcessorFactory processorFactory_;
protected TServerTransport serverTransport_;
protected TTransportFactory inputTransportFactory_;
protected TTransportFactory outputTransportFactory_;
protected TProtocolFactory inputProtocolFactory_;
protected TProtocolFactory outputProtocolFactory_;
private ExecutorService executorService_;
private volatile boolean stopped_;
private Options options_;
public int minWorkerThreads = 5;
public int maxWorkerThreads = Integer.MAX_VALUE;
public int stopTimeoutVal = 1;
public TimeUnit stopTimeoutUnit = TimeUnit.SECONDS;
}
TServerTransport serverTransport, TProtocolFactory protocolFactory) {
this(new TProcessorFactory(processor), serverTransport,
new TTransportFactory(), new TTransportFactory(), protocolFactory,
protocolFactory);
}
TServerTransport serverTransport,
TTransportFactory inputTransportFactory,
TTransportFactory outputTransportFactory,
TProtocolFactory inputProtocolFactory,
TProtocolFactory outputProtocolFactory) {
processorFactory_ = processorFactory;
serverTransport_ = serverTransport;
inputTransportFactory_ = inputTransportFactory;
outputTransportFactory_ = outputTransportFactory;
inputProtocolFactory_ = inputProtocolFactory;
outputProtocolFactory_ = outputProtocolFactory;
options_ = new Options();
executorService_ = Executors.newCachedThreadPool();
}
try {
serverTransport_.listen();
stopped_ = false;
} catch (TTransportException ttx) {
LOGGER.error("Error occurred during listening.", ttx);
return;
}
new Thread("Thrift server:" + processorFactory_.getClass() + " on "
+ serverTransport_.getClass()) {
while (!stopped_) {
int failureCount = 0;
try {
TTransport client = serverTransport_.accept();
TStatsTransport stats = new TStatsTransport(client);
WorkerProcess wp = new WorkerProcess(stats);
executorService_.execute(wp);
} catch (TTransportException ttx) {
if (!stopped_) {
++failureCount;
LOGGER
.warn(
"Transport error occurred during acceptance of message.",
ttx);
}
}
}
}
}.start();
}
stopped_ = true;
serverTransport_.interrupt();
executorService_.shutdown();
long timeoutMS = options_.stopTimeoutUnit.toMillis(options_.stopTimeoutVal);
long now = System.currentTimeMillis();
while (timeoutMS >= 0) {
try {
executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS);
break;
} catch (InterruptedException ix) {
long newnow = System.currentTimeMillis();
timeoutMS -= (newnow - now);
now = newnow;
}
}
}
synchronized (maplock) {
long total = doneBytesWritten;
for (WorkerProcess wp : map.values()) {
total += wp.client_.getBytesWritten();
}
return total;
}
}
synchronized (maplock) {
long total = doneBytesRead;
for (WorkerProcess wp : map.values()) {
total += wp.client_.getBytesRead();
}
return total;
}
}
private TStatsTransport client_;
client_ = client;
}
TProcessor processor = null;
TTransport inputTransport = null;
TTransport outputTransport = null;
TProtocol inputProtocol = null;
TProtocol outputProtocol = null;
try {
processor = processorFactory_.getProcessor(client_);
inputTransport = inputTransportFactory_.getTransport(client_);
outputTransport = outputTransportFactory_.getTransport(client_);
inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
synchronized (maplock) {
map.put(Thread.currentThread().getId(), this);
}
while (!stopped_ && processor.process(inputProtocol, outputProtocol)) {
}
} catch (TTransportException ttx) {
} catch (TException tx) {
LOGGER.error("Thrift error occurred during processing of message.", tx);
} catch (Exception x) {
LOGGER.error("Error occurred during processing of message.", x);
} finally {
synchronized (maplock) {
map.remove(Thread.currentThread().getId());
doneBytesWritten += this.client_.getBytesWritten();
doneBytesRead += this.client_.getBytesRead();
}
}
if (inputTransport != null) {
inputTransport.close();
}
if (outputTransport != null) {
outputTransport.close();
}
}
}
}