| package com.facebook.thrift.server; | 
 |  | 
 | import com.facebook.thrift.TException; | 
 | import com.facebook.thrift.TProcessor; | 
 | import com.facebook.thrift.transport.TServerTransport; | 
 | import com.facebook.thrift.transport.TTransport; | 
 | import com.facebook.thrift.transport.TTransportException; | 
 | import com.facebook.thrift.transport.TTransportFactory; | 
 | import com.facebook.thrift.transport.TBaseTransportFactory; | 
 |  | 
 | import java.util.concurrent.ExecutorService; | 
 | import java.util.concurrent.LinkedBlockingQueue; | 
 | import java.util.concurrent.ThreadPoolExecutor; | 
 | import java.util.concurrent.TimeUnit; | 
 |  | 
 |  | 
 | /** | 
 |  * Server which uses Java's built in ThreadPool management to spawn off | 
 |  * a worker pool that  | 
 |  * | 
 |  * @author Mark Slee <mcslee@facebook.com> | 
 |  */ | 
 | public class TThreadPoolServer extends TServer { | 
 |  | 
 |   // Executor service for handling client connections | 
 |   private ExecutorService executorService_; | 
 |  | 
 |   // Customizable server options | 
 |   public static class Options extends TServer.Options { | 
 |     public int minWorkerThreads = 5; | 
 |     public int maxWorkerThreads = Integer.MAX_VALUE; | 
 |   } | 
 |  | 
 |   public TThreadPoolServer(TProcessor processor, | 
 |                            TServerTransport serverTransport) { | 
 |     this(processor, | 
 |          serverTransport, | 
 |          new TBaseTransportFactory(), | 
 |          new Options()); | 
 |   } | 
 |    | 
 |   public TThreadPoolServer(TProcessor processor, | 
 |                            TServerTransport serverTransport, | 
 |                            TTransportFactory transportFactory, | 
 |                            Options options) { | 
 |     super(processor, serverTransport, transportFactory, options); | 
 |     serverTransport_ = serverTransport; | 
 |     executorService_ = null; | 
 |  | 
 |     LinkedBlockingQueue<Runnable> executorQueue = | 
 |       new LinkedBlockingQueue<Runnable>(); | 
 |  | 
 |     executorService_ = new ThreadPoolExecutor(options.minWorkerThreads, | 
 |                                               options.maxWorkerThreads, | 
 |                                               60, | 
 |                                               TimeUnit.SECONDS, | 
 |                                               executorQueue); | 
 |   } | 
 |  | 
 |  | 
 |   public void run() { | 
 |     try { | 
 |       serverTransport_.listen(); | 
 |     } catch (TTransportException ttx) { | 
 |       ttx.printStackTrace(); | 
 |       return; | 
 |     } | 
 |  | 
 |     while (true) { | 
 |       try { | 
 |         TTransport client = serverTransport_.accept(); | 
 |         WorkerProcess wp = new WorkerProcess(client); | 
 |         executorService_.execute(wp); | 
 |       } catch (TTransportException ttx) { | 
 |         ttx.printStackTrace(); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   private class WorkerProcess implements Runnable { | 
 |  | 
 |     /** | 
 |      * Client that this services. | 
 |      */ | 
 |     private TTransport client_; | 
 |  | 
 |     /** | 
 |      * Default constructor. | 
 |      * | 
 |      * @param client Transport to process | 
 |      */ | 
 |     private WorkerProcess(TTransport client) { | 
 |       client_ = client; | 
 |     } | 
 |  | 
 |     /** | 
 |      * Loops on processing a client forever | 
 |      */ | 
 |     public void run() { | 
 |       TTransport[] io = null; | 
 |       try { | 
 |         io = transportFactory_.getIOTransports(client_); | 
 |         while (processor_.process(io[0], io[1])) {} | 
 |       } catch (TTransportException ttx) { | 
 |         // Assume the client died and continue silently | 
 |       } catch (TException tx) { | 
 |         tx.printStackTrace(); | 
 |       } catch (Exception x) { | 
 |         x.printStackTrace(); | 
 |       } | 
 |  | 
 |       if (io != null) { | 
 |         if (io[0] != null) { | 
 |           io[0].close(); | 
 |         } | 
 |         if (io[1] != null) { | 
 |           io[1].close(); | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 | } |