blob: cf8354e9f89b3fd6b9fe6b921487609e216d5ad5 [file] [log] [blame]
Kevin Clarkab4460d2009-03-20 02:28:41 +00001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Todd Lipcon53ae9f32009-12-07 00:42:38 +000018 *
19 * Contains some contributions under the Thrift Software License.
20 * Please see doc/old-thrift-license.txt in the Thrift distribution for
21 * details.
Kevin Clarkab4460d2009-03-20 02:28:41 +000022 */
23
David Reiss7f42bcf2008-01-11 20:59:12 +000024using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000025using System.Threading;
26using Thrift.Protocol;
27using Thrift.Transport;
28
29namespace Thrift.Server
30{
31 /// <summary>
32 /// Server that uses C# built-in ThreadPool to spawn threads when handling requests
33 /// </summary>
34 public class TThreadPoolServer : TServer
35 {
36 private const int DEFAULT_MIN_THREADS = 10;
37 private const int DEFAULT_MAX_THREADS = 100;
David Reissdc815f52008-03-02 00:58:04 +000038 private volatile bool stop = false;
David Reiss7f42bcf2008-01-11 20:59:12 +000039
40 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
41 :this(processor, serverTransport,
42 new TTransportFactory(), new TTransportFactory(),
43 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
David Reiss63191332009-01-06 19:49:22 +000044 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000045 {
46 }
47
David Reiss63191332009-01-06 19:49:22 +000048 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
49 : this(processor, serverTransport,
50 new TTransportFactory(), new TTransportFactory(),
51 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
52 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, logDelegate)
53 {
54 }
55
56
David Reiss7f42bcf2008-01-11 20:59:12 +000057 public TThreadPoolServer(TProcessor processor,
58 TServerTransport serverTransport,
59 TTransportFactory transportFactory,
60 TProtocolFactory protocolFactory)
61 :this(processor, serverTransport,
62 transportFactory, transportFactory,
63 protocolFactory, protocolFactory,
David Reiss63191332009-01-06 19:49:22 +000064 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000065 {
66 }
67
68 public TThreadPoolServer(TProcessor processor,
69 TServerTransport serverTransport,
70 TTransportFactory inputTransportFactory,
71 TTransportFactory outputTransportFactory,
72 TProtocolFactory inputProtocolFactory,
73 TProtocolFactory outputProtocolFactory,
David Reiss63191332009-01-06 19:49:22 +000074 int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000075 :base(processor, serverTransport, inputTransportFactory, outputTransportFactory,
David Reiss63191332009-01-06 19:49:22 +000076 inputProtocolFactory, outputProtocolFactory, logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000077 {
78 if (!ThreadPool.SetMinThreads(minThreadPoolThreads, minThreadPoolThreads))
79 {
80 throw new Exception("Error: could not SetMinThreads in ThreadPool");
81 }
82 if (!ThreadPool.SetMaxThreads(maxThreadPoolThreads, maxThreadPoolThreads))
83 {
84 throw new Exception("Error: could not SetMaxThreads in ThreadPool");
85 }
David Reiss7f42bcf2008-01-11 20:59:12 +000086 }
87
88 /// <summary>
89 /// Use new ThreadPool thread for each new client connection
90 /// </summary>
91 public override void Serve()
92 {
93 try
94 {
95 serverTransport.Listen();
96 }
97 catch (TTransportException ttx)
98 {
David Reiss63191332009-01-06 19:49:22 +000099 logDelegate("Error, could not listen on ServerTransport: " + ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +0000100 return;
101 }
102
David Reissdc815f52008-03-02 00:58:04 +0000103 while (!stop)
David Reiss7f42bcf2008-01-11 20:59:12 +0000104 {
105 int failureCount = 0;
106 try
107 {
108 TTransport client = serverTransport.Accept();
109 ThreadPool.QueueUserWorkItem(this.Execute, client);
110 }
111 catch (TTransportException ttx)
112 {
David Reiss63191332009-01-06 19:49:22 +0000113 if (stop)
114 {
115 logDelegate("TThreadPoolServer was shutting down, caught " + ttx.GetType().Name);
116 }
117 else
118 {
119 ++failureCount;
120 logDelegate(ttx.ToString());
121 }
122
David Reiss7f42bcf2008-01-11 20:59:12 +0000123 }
124 }
David Reissdc815f52008-03-02 00:58:04 +0000125
126 if (stop)
127 {
128 try
129 {
130 serverTransport.Close();
131 }
132 catch (TTransportException ttx)
133 {
David Reiss63191332009-01-06 19:49:22 +0000134 logDelegate("TServerTransport failed on close: " + ttx.Message);
David Reissdc815f52008-03-02 00:58:04 +0000135 }
136 stop = false;
137 }
138 }
139
David Reiss7f42bcf2008-01-11 20:59:12 +0000140 /// <summary>
141 /// Loops on processing a client forever
142 /// threadContext will be a TTransport instance
143 /// </summary>
144 /// <param name="threadContext"></param>
145 private void Execute(Object threadContext)
146 {
147 TTransport client = (TTransport)threadContext;
148 TTransport inputTransport = null;
149 TTransport outputTransport = null;
150 TProtocol inputProtocol = null;
151 TProtocol outputProtocol = null;
152 try
153 {
154 inputTransport = inputTransportFactory.GetTransport(client);
155 outputTransport = outputTransportFactory.GetTransport(client);
156 inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
157 outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
David Reiss0c90f6f2008-02-06 22:18:40 +0000158 while (processor.Process(inputProtocol, outputProtocol))
David Reiss7f42bcf2008-01-11 20:59:12 +0000159 {
160 //keep processing requests until client disconnects
161 }
162 }
David Reisscee1e082008-04-02 22:10:09 +0000163 catch (TTransportException)
David Reiss7f42bcf2008-01-11 20:59:12 +0000164 {
165 // Assume the client died and continue silently
David Reiss63191332009-01-06 19:49:22 +0000166 //Console.WriteLine(ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +0000167 }
168
169 catch (Exception x)
170 {
David Reiss63191332009-01-06 19:49:22 +0000171 logDelegate("Error: " + x);
David Reiss7f42bcf2008-01-11 20:59:12 +0000172 }
173
174 if (inputTransport != null)
175 {
176 inputTransport.Close();
177 }
178 if (outputTransport != null)
179 {
180 outputTransport.Close();
181 }
182 }
David Reiss63191332009-01-06 19:49:22 +0000183
184 public override void Stop()
185 {
186 stop = true;
187 serverTransport.Close();
188 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000189 }
190}