blob: e3c5cded1f40425641b06560206c73cd749199f2 [file] [log] [blame]
David Reiss7f42bcf2008-01-11 20:59:12 +00001//
2// TThreadPoolServer.cs
3//
4// Begin: Dec 3, 2007
David Reiss0c90f6f2008-02-06 22:18:40 +00005// Authors:
David Reiss7f42bcf2008-01-11 20:59:12 +00006// Will Palmeri <wpalmeri@imeem.com>
7//
8// Distributed under the Thrift Software License
9//
10// See accompanying file LICENSE or visit the Thrift site at:
11// http://developers.facebook.com/thrift/using
12using System;
David Reiss7f42bcf2008-01-11 20:59:12 +000013using System.Threading;
14using Thrift.Protocol;
15using Thrift.Transport;
16
17namespace Thrift.Server
18{
19 /// <summary>
20 /// Server that uses C# built-in ThreadPool to spawn threads when handling requests
21 /// </summary>
22 public class TThreadPoolServer : TServer
23 {
24 private const int DEFAULT_MIN_THREADS = 10;
25 private const int DEFAULT_MAX_THREADS = 100;
David Reissdc815f52008-03-02 00:58:04 +000026 private volatile bool stop = false;
David Reiss7f42bcf2008-01-11 20:59:12 +000027
28 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
29 :this(processor, serverTransport,
30 new TTransportFactory(), new TTransportFactory(),
31 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
David Reiss63191332009-01-06 19:49:22 +000032 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000033 {
34 }
35
David Reiss63191332009-01-06 19:49:22 +000036 public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
37 : this(processor, serverTransport,
38 new TTransportFactory(), new TTransportFactory(),
39 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
40 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, logDelegate)
41 {
42 }
43
44
David Reiss7f42bcf2008-01-11 20:59:12 +000045 public TThreadPoolServer(TProcessor processor,
46 TServerTransport serverTransport,
47 TTransportFactory transportFactory,
48 TProtocolFactory protocolFactory)
49 :this(processor, serverTransport,
50 transportFactory, transportFactory,
51 protocolFactory, protocolFactory,
David Reiss63191332009-01-06 19:49:22 +000052 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS, DefaultLogDelegate)
David Reiss7f42bcf2008-01-11 20:59:12 +000053 {
54 }
55
56 public TThreadPoolServer(TProcessor processor,
57 TServerTransport serverTransport,
58 TTransportFactory inputTransportFactory,
59 TTransportFactory outputTransportFactory,
60 TProtocolFactory inputProtocolFactory,
61 TProtocolFactory outputProtocolFactory,
David Reiss63191332009-01-06 19:49:22 +000062 int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000063 :base(processor, serverTransport, inputTransportFactory, outputTransportFactory,
David Reiss63191332009-01-06 19:49:22 +000064 inputProtocolFactory, outputProtocolFactory, logDel)
David Reiss7f42bcf2008-01-11 20:59:12 +000065 {
66 if (!ThreadPool.SetMinThreads(minThreadPoolThreads, minThreadPoolThreads))
67 {
68 throw new Exception("Error: could not SetMinThreads in ThreadPool");
69 }
70 if (!ThreadPool.SetMaxThreads(maxThreadPoolThreads, maxThreadPoolThreads))
71 {
72 throw new Exception("Error: could not SetMaxThreads in ThreadPool");
73 }
David Reiss7f42bcf2008-01-11 20:59:12 +000074 }
75
76 /// <summary>
77 /// Use new ThreadPool thread for each new client connection
78 /// </summary>
79 public override void Serve()
80 {
81 try
82 {
83 serverTransport.Listen();
84 }
85 catch (TTransportException ttx)
86 {
David Reiss63191332009-01-06 19:49:22 +000087 logDelegate("Error, could not listen on ServerTransport: " + ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +000088 return;
89 }
90
David Reissdc815f52008-03-02 00:58:04 +000091 while (!stop)
David Reiss7f42bcf2008-01-11 20:59:12 +000092 {
93 int failureCount = 0;
94 try
95 {
96 TTransport client = serverTransport.Accept();
97 ThreadPool.QueueUserWorkItem(this.Execute, client);
98 }
99 catch (TTransportException ttx)
100 {
David Reiss63191332009-01-06 19:49:22 +0000101 if (stop)
102 {
103 logDelegate("TThreadPoolServer was shutting down, caught " + ttx.GetType().Name);
104 }
105 else
106 {
107 ++failureCount;
108 logDelegate(ttx.ToString());
109 }
110
David Reiss7f42bcf2008-01-11 20:59:12 +0000111 }
112 }
David Reissdc815f52008-03-02 00:58:04 +0000113
114 if (stop)
115 {
116 try
117 {
118 serverTransport.Close();
119 }
120 catch (TTransportException ttx)
121 {
David Reiss63191332009-01-06 19:49:22 +0000122 logDelegate("TServerTransport failed on close: " + ttx.Message);
David Reissdc815f52008-03-02 00:58:04 +0000123 }
124 stop = false;
125 }
126 }
127
David Reiss7f42bcf2008-01-11 20:59:12 +0000128 /// <summary>
129 /// Loops on processing a client forever
130 /// threadContext will be a TTransport instance
131 /// </summary>
132 /// <param name="threadContext"></param>
133 private void Execute(Object threadContext)
134 {
135 TTransport client = (TTransport)threadContext;
136 TTransport inputTransport = null;
137 TTransport outputTransport = null;
138 TProtocol inputProtocol = null;
139 TProtocol outputProtocol = null;
140 try
141 {
142 inputTransport = inputTransportFactory.GetTransport(client);
143 outputTransport = outputTransportFactory.GetTransport(client);
144 inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
145 outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
David Reiss0c90f6f2008-02-06 22:18:40 +0000146 while (processor.Process(inputProtocol, outputProtocol))
David Reiss7f42bcf2008-01-11 20:59:12 +0000147 {
148 //keep processing requests until client disconnects
149 }
150 }
David Reisscee1e082008-04-02 22:10:09 +0000151 catch (TTransportException)
David Reiss7f42bcf2008-01-11 20:59:12 +0000152 {
153 // Assume the client died and continue silently
David Reiss63191332009-01-06 19:49:22 +0000154 //Console.WriteLine(ttx);
David Reiss7f42bcf2008-01-11 20:59:12 +0000155 }
156
157 catch (Exception x)
158 {
David Reiss63191332009-01-06 19:49:22 +0000159 logDelegate("Error: " + x);
David Reiss7f42bcf2008-01-11 20:59:12 +0000160 }
161
162 if (inputTransport != null)
163 {
164 inputTransport.Close();
165 }
166 if (outputTransport != null)
167 {
168 outputTransport.Close();
169 }
170 }
David Reiss63191332009-01-06 19:49:22 +0000171
172 public override void Stop()
173 {
174 stop = true;
175 serverTransport.Close();
176 }
David Reiss7f42bcf2008-01-11 20:59:12 +0000177 }
178}