| Mark Slee | 7eb0d63 | 2007-03-01 00:00:27 +0000 | [diff] [blame] | 1 | // Copyright (c) 2006- Facebook | 
|  | 2 | // Distributed under the Thrift Software License | 
|  | 3 | // | 
|  | 4 | // See accompanying file LICENSE or visit the Thrift site at: | 
|  | 5 | // http://developers.facebook.com/thrift/ | 
|  | 6 |  | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 7 | package com.facebook.thrift.server; | 
|  | 8 |  | 
|  | 9 | import com.facebook.thrift.TException; | 
|  | 10 | import com.facebook.thrift.TProcessor; | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 11 | import com.facebook.thrift.TProcessorFactory; | 
| Mark Slee | 456b7a8 | 2006-10-25 20:53:37 +0000 | [diff] [blame] | 12 | import com.facebook.thrift.protocol.TProtocol; | 
|  | 13 | import com.facebook.thrift.protocol.TProtocolFactory; | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 14 | import com.facebook.thrift.protocol.TBinaryProtocol; | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 15 | import com.facebook.thrift.transport.TServerTransport; | 
|  | 16 | import com.facebook.thrift.transport.TTransport; | 
|  | 17 | import com.facebook.thrift.transport.TTransportException; | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 18 | import com.facebook.thrift.transport.TTransportFactory; | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 19 |  | 
|  | 20 | import java.util.concurrent.ExecutorService; | 
|  | 21 | import java.util.concurrent.LinkedBlockingQueue; | 
|  | 22 | import java.util.concurrent.ThreadPoolExecutor; | 
|  | 23 | import java.util.concurrent.TimeUnit; | 
|  | 24 |  | 
|  | 25 |  | 
|  | 26 | /** | 
|  | 27 | * Server which uses Java's built in ThreadPool management to spawn off | 
|  | 28 | * a worker pool that | 
|  | 29 | * | 
|  | 30 | * @author Mark Slee <mcslee@facebook.com> | 
|  | 31 | */ | 
|  | 32 | public class TThreadPoolServer extends TServer { | 
|  | 33 |  | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 34 | // Executor service for handling client connections | 
|  | 35 | private ExecutorService executorService_; | 
|  | 36 |  | 
|  | 37 | // Customizable server options | 
| Mark Slee | 456b7a8 | 2006-10-25 20:53:37 +0000 | [diff] [blame] | 38 | public static class Options { | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 39 | public int minWorkerThreads = 5; | 
|  | 40 | public int maxWorkerThreads = Integer.MAX_VALUE; | 
|  | 41 | } | 
|  | 42 |  | 
|  | 43 | public TThreadPoolServer(TProcessor processor, | 
|  | 44 | TServerTransport serverTransport) { | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 45 | this(processor, serverTransport, | 
|  | 46 | new TTransportFactory(), new TTransportFactory(), | 
|  | 47 | new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), | 
|  | 48 | new Options()); | 
|  | 49 | } | 
|  | 50 |  | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 51 | public TThreadPoolServer(TProcessorFactory processorFactory, | 
|  | 52 | TServerTransport serverTransport) { | 
|  | 53 | this(processorFactory, serverTransport, | 
|  | 54 | new TTransportFactory(), new TTransportFactory(), | 
|  | 55 | new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), | 
|  | 56 | new Options()); | 
|  | 57 | } | 
|  | 58 |  | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 59 | public TThreadPoolServer(TProcessor processor, | 
|  | 60 | TServerTransport serverTransport, | 
|  | 61 | TTransportFactory transportFactory, | 
|  | 62 | TProtocolFactory protocolFactory) { | 
|  | 63 | this(processor, serverTransport, | 
|  | 64 | transportFactory, transportFactory, | 
|  | 65 | protocolFactory, protocolFactory, | 
|  | 66 | new Options()); | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 67 | } | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 68 |  | 
|  | 69 | public TThreadPoolServer(TProcessorFactory processorFactory, | 
|  | 70 | TServerTransport serverTransport, | 
|  | 71 | TTransportFactory transportFactory, | 
|  | 72 | TProtocolFactory protocolFactory) { | 
|  | 73 | this(processorFactory, serverTransport, | 
|  | 74 | transportFactory, transportFactory, | 
|  | 75 | protocolFactory, protocolFactory, | 
|  | 76 | new Options()); | 
|  | 77 | } | 
|  | 78 |  | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 79 |  | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 80 | public TThreadPoolServer(TProcessor processor, | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 81 | TServerTransport serverTransport, | 
|  | 82 | TTransportFactory inputTransportFactory, | 
|  | 83 | TTransportFactory outputTransportFactory, | 
|  | 84 | TProtocolFactory inputProtocolFactory, | 
|  | 85 | TProtocolFactory outputProtocolFactory, | 
|  | 86 | Options options) { | 
|  | 87 | this(new TProcessorFactory(processor), serverTransport, | 
|  | 88 | inputTransportFactory, outputTransportFactory, | 
|  | 89 | inputProtocolFactory, outputProtocolFactory, | 
|  | 90 | options); | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | public TThreadPoolServer(TProcessorFactory processorFactory, | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 94 | TServerTransport serverTransport, | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 95 | TTransportFactory inputTransportFactory, | 
|  | 96 | TTransportFactory outputTransportFactory, | 
|  | 97 | TProtocolFactory inputProtocolFactory, | 
|  | 98 | TProtocolFactory outputProtocolFactory, | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 99 | Options options) { | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 100 | super(processorFactory, serverTransport, | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 101 | inputTransportFactory, outputTransportFactory, | 
|  | 102 | inputProtocolFactory, outputProtocolFactory); | 
| Mark Slee | 456b7a8 | 2006-10-25 20:53:37 +0000 | [diff] [blame] | 103 |  | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 104 | executorService_ = null; | 
|  | 105 |  | 
|  | 106 | LinkedBlockingQueue<Runnable> executorQueue = | 
|  | 107 | new LinkedBlockingQueue<Runnable>(); | 
|  | 108 |  | 
|  | 109 | executorService_ = new ThreadPoolExecutor(options.minWorkerThreads, | 
|  | 110 | options.maxWorkerThreads, | 
|  | 111 | 60, | 
|  | 112 | TimeUnit.SECONDS, | 
|  | 113 | executorQueue); | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 |  | 
| Mark Slee | 4e755ca | 2006-09-12 00:46:08 +0000 | [diff] [blame] | 117 | public void serve() { | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 118 | try { | 
|  | 119 | serverTransport_.listen(); | 
|  | 120 | } catch (TTransportException ttx) { | 
|  | 121 | ttx.printStackTrace(); | 
|  | 122 | return; | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | while (true) { | 
| Mark Slee | 4e755ca | 2006-09-12 00:46:08 +0000 | [diff] [blame] | 126 | int failureCount = 0; | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 127 | try { | 
|  | 128 | TTransport client = serverTransport_.accept(); | 
|  | 129 | WorkerProcess wp = new WorkerProcess(client); | 
|  | 130 | executorService_.execute(wp); | 
|  | 131 | } catch (TTransportException ttx) { | 
| Mark Slee | 4e755ca | 2006-09-12 00:46:08 +0000 | [diff] [blame] | 132 | ++failureCount; | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 133 | ttx.printStackTrace(); | 
| Mark Slee | 4e755ca | 2006-09-12 00:46:08 +0000 | [diff] [blame] | 134 | } | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 135 | } | 
|  | 136 | } | 
|  | 137 |  | 
|  | 138 | private class WorkerProcess implements Runnable { | 
|  | 139 |  | 
|  | 140 | /** | 
|  | 141 | * Client that this services. | 
|  | 142 | */ | 
|  | 143 | private TTransport client_; | 
|  | 144 |  | 
|  | 145 | /** | 
|  | 146 | * Default constructor. | 
|  | 147 | * | 
|  | 148 | * @param client Transport to process | 
|  | 149 | */ | 
|  | 150 | private WorkerProcess(TTransport client) { | 
|  | 151 | client_ = client; | 
|  | 152 | } | 
|  | 153 |  | 
|  | 154 | /** | 
|  | 155 | * Loops on processing a client forever | 
|  | 156 | */ | 
|  | 157 | public void run() { | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 158 | TProcessor processor = null; | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 159 | TTransport inputTransport = null; | 
|  | 160 | TTransport outputTransport = null; | 
|  | 161 | TProtocol inputProtocol = null; | 
|  | 162 | TProtocol outputProtocol = null; | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 163 | try { | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 164 | processor = processorFactory_.getProcessor(client_); | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 165 | inputTransport = inputTransportFactory_.getTransport(client_); | 
|  | 166 | outputTransport = outputTransportFactory_.getTransport(client_); | 
|  | 167 | inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); | 
|  | 168 | outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); | 
| Mark Slee | 448849d | 2007-05-31 01:30:22 +0000 | [diff] [blame] | 169 | while (processor.process(inputProtocol, outputProtocol)) {} | 
| Mark Slee | ade2c83 | 2006-09-08 03:41:50 +0000 | [diff] [blame] | 170 | } catch (TTransportException ttx) { | 
|  | 171 | // Assume the client died and continue silently | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 172 | } catch (TException tx) { | 
|  | 173 | tx.printStackTrace(); | 
| Mark Slee | ade2c83 | 2006-09-08 03:41:50 +0000 | [diff] [blame] | 174 | } catch (Exception x) { | 
|  | 175 | x.printStackTrace(); | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 176 | } | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 177 |  | 
| Aditya Agarwal | 5a42958 | 2007-02-06 02:51:15 +0000 | [diff] [blame] | 178 | if (inputTransport != null) { | 
|  | 179 | inputTransport.close(); | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | if (outputTransport != null) { | 
|  | 183 | outputTransport.close(); | 
| Mark Slee | d788b2e | 2006-09-07 01:26:35 +0000 | [diff] [blame] | 184 | } | 
| Mark Slee | ffcddd6 | 2006-09-06 20:37:03 +0000 | [diff] [blame] | 185 | } | 
|  | 186 | } | 
|  | 187 | } |