blob: efc71f01efbc34c93245fa163ed70eddeb17ac97 [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.
18 */
19
David Reiss7f42bcf2008-01-11 20:59:12 +000020using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000021using System.Threading;
22using Thrift.Protocol;
23using Thrift.Transport;
24
25namespace Thrift.Server
26{
27 /// <summary>
28 /// Server that uses C# built-in ThreadPool to spawn threads when handling requests
29 /// </summary>
30 public class TThreadPoolServer : TServer
31 {
32 private const int DEFAULT_MIN_THREADS = 10;
33 private const int DEFAULT_MAX_THREADS = 100;
David Reissdc815f52008-03-02 00:58:04 +000034 private volatile bool stop = false;
David Reiss7f42bcf2008-01-11 20:59:12 +000035
36 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
37 :this(processor, serverTransport,
38 new TTransportFactory(), new TTransportFactory(),
39 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
David Reiss63191332009-01-06 19:49:22 +000040 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000041 {
42 }
43
David Reiss63191332009-01-06 19:49:22 +000044 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
45 : this(processor, serverTransport,
46 new TTransportFactory(), new TTransportFactory(),
47 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
48 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, logDelegate)
49 {
50 }
51
52
David Reiss7f42bcf2008-01-11 20:59:12 +000053 public TThreadPoolServer(TProcessor processor,
54 TServerTransport serverTransport,
55 TTransportFactory transportFactory,
56 TProtocolFactory protocolFactory)
57 :this(processor, serverTransport,
58 transportFactory, transportFactory,
59 protocolFactory, protocolFactory,
David Reiss63191332009-01-06 19:49:22 +000060 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000061 {
62 }
63
64 public TThreadPoolServer(TProcessor processor,
65 TServerTransport serverTransport,
66 TTransportFactory inputTransportFactory,
67 TTransportFactory outputTransportFactory,
68 TProtocolFactory inputProtocolFactory,
69 TProtocolFactory outputProtocolFactory,
David Reiss63191332009-01-06 19:49:22 +000070 int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000071 :base(processor, serverTransport, inputTransportFactory, outputTransportFactory,
David Reiss63191332009-01-06 19:49:22 +000072 inputProtocolFactory, outputProtocolFactory, logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000073 {
74 if (!ThreadPool.SetMinThreads(minThreadPoolThreads, minThreadPoolThreads))
75 {
76 throw new Exception("Error: could not SetMinThreads in ThreadPool");
77 }
78 if (!ThreadPool.SetMaxThreads(maxThreadPoolThreads, maxThreadPoolThreads))
79 {
80 throw new Exception("Error: could not SetMaxThreads in ThreadPool");
81 }
David Reiss7f42bcf2008-01-11 20:59:12 +000082 }
83
84 /// <summary>
85 /// Use new ThreadPool thread for each new client connection
86 /// </summary>
87 public override void Serve()
88 {
89 try
90 {
91 serverTransport.Listen();
92 }
93 catch (TTransportException ttx)
94 {
David Reiss63191332009-01-06 19:49:22 +000095 logDelegate("Error, could not listen on ServerTransport: " + ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +000096 return;
97 }
98
David Reissdc815f52008-03-02 00:58:04 +000099 while (!stop)
David Reiss7f42bcf2008-01-11 20:59:12 +0000100 {
101 int failureCount = 0;
102 try
103 {
104 TTransport client = serverTransport.Accept();
105 ThreadPool.QueueUserWorkItem(this.Execute, client);
106 }
107 catch (TTransportException ttx)
108 {
David Reiss63191332009-01-06 19:49:22 +0000109 if (stop)
110 {
111 logDelegate("TThreadPoolServer was shutting down, caught " + ttx.GetType().Name);
112 }
113 else
114 {
115 ++failureCount;
116 logDelegate(ttx.ToString());
117 }
118
David Reiss7f42bcf2008-01-11 20:59:12 +0000119 }
120 }
David Reissdc815f52008-03-02 00:58:04 +0000121
122 if (stop)
123 {
124 try
125 {
126 serverTransport.Close();
127 }
128 catch (TTransportException ttx)
129 {
David Reiss63191332009-01-06 19:49:22 +0000130 logDelegate("TServerTransport failed on close: " + ttx.Message);
David Reissdc815f52008-03-02 00:58:04 +0000131 }
132 stop = false;
133 }
134 }
135
David Reiss7f42bcf2008-01-11 20:59:12 +0000136 /// <summary>
137 /// Loops on processing a client forever
138 /// threadContext will be a TTransport instance
139 /// </summary>
140 /// <param name="threadContext"></param>
141 private void Execute(Object threadContext)
142 {
143 TTransport client = (TTransport)threadContext;
144 TTransport inputTransport = null;
145 TTransport outputTransport = null;
146 TProtocol inputProtocol = null;
147 TProtocol outputProtocol = null;
148 try
149 {
150 inputTransport = inputTransportFactory.GetTransport(client);
151 outputTransport = outputTransportFactory.GetTransport(client);
152 inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
153 outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
David Reiss0c90f6f2008-02-06 22:18:40 +0000154 while (processor.Process(inputProtocol, outputProtocol))
David Reiss7f42bcf2008-01-11 20:59:12 +0000155 {
156 //keep processing requests until client disconnects
157 }
158 }
David Reisscee1e082008-04-02 22:10:09 +0000159 catch (TTransportException)
David Reiss7f42bcf2008-01-11 20:59:12 +0000160 {
161 // Assume the client died and continue silently
David Reiss63191332009-01-06 19:49:22 +0000162 //Console.WriteLine(ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +0000163 }
164
165 catch (Exception x)
166 {
David Reiss63191332009-01-06 19:49:22 +0000167 logDelegate("Error: " + x);
David Reiss7f42bcf2008-01-11 20:59:12 +0000168 }
169
170 if (inputTransport != null)
171 {
172 inputTransport.Close();
173 }
174 if (outputTransport != null)
175 {
176 outputTransport.Close();
177 }
178 }
David Reiss63191332009-01-06 19:49:22 +0000179
180 public override void Stop()
181 {
182 stop = true;
183 serverTransport.Close();
184 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000185 }
186}