blob: 0252f10d3046f6bbaafea3d92fe10ef9b4621aa1 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +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 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
Mark Slee2f6404d2006-10-10 01:37:40 +000020#ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_
21#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1
22
Mark Slee4af6ed72006-10-25 19:02:49 +000023#include <Thrift.h>
24#include <server/TServer.h>
David Reiss28f298d2008-05-01 06:17:36 +000025#include <transport/TBufferTransports.h>
David Reiss105961d2010-10-06 17:10:17 +000026#include <transport/TSocket.h>
Mark Sleee02385b2007-06-09 01:21:16 +000027#include <concurrency/ThreadManager.h>
David Reiss01fe1532010-03-09 05:19:25 +000028#include <climits>
Mark Slee2f6404d2006-10-10 01:37:40 +000029#include <stack>
David Reiss9b209552008-04-08 06:26:05 +000030#include <string>
31#include <errno.h>
David Reissd7a16f42008-02-19 22:47:29 +000032#include <cstdlib>
David Reiss5105b2e2009-05-21 02:28:27 +000033#include <unistd.h>
Mark Slee2f6404d2006-10-10 01:37:40 +000034#include <event.h>
35
T Jake Lucianib5e62212009-01-31 22:36:20 +000036namespace apache { namespace thrift { namespace server {
Mark Slee2f6404d2006-10-10 01:37:40 +000037
T Jake Lucianib5e62212009-01-31 22:36:20 +000038using apache::thrift::transport::TMemoryBuffer;
David Reiss105961d2010-10-06 17:10:17 +000039using apache::thrift::transport::TSocket;
T Jake Lucianib5e62212009-01-31 22:36:20 +000040using apache::thrift::protocol::TProtocol;
41using apache::thrift::concurrency::Runnable;
42using apache::thrift::concurrency::ThreadManager;
Mark Slee2f6404d2006-10-10 01:37:40 +000043
44// Forward declaration of class
45class TConnection;
46
47/**
48 * This is a non-blocking server in C++ for high performance that operates a
49 * single IO thread. It assumes that all incoming requests are framed with a
50 * 4 byte length indicator and writes out responses using the same framing.
51 *
52 * It does not use the TServerTransport framework, but rather has socket
53 * operations hardcoded for use with select.
54 *
Mark Slee2f6404d2006-10-10 01:37:40 +000055 */
David Reiss01fe1532010-03-09 05:19:25 +000056
57
58/// Overload condition actions.
59enum TOverloadAction {
60 T_OVERLOAD_NO_ACTION, ///< Don't handle overload */
61 T_OVERLOAD_CLOSE_ON_ACCEPT, ///< Drop new connections immediately */
62 T_OVERLOAD_DRAIN_TASK_QUEUE ///< Drop some tasks from head of task queue */
63};
64
Mark Slee2f6404d2006-10-10 01:37:40 +000065class TNonblockingServer : public TServer {
66 private:
David Reiss01fe1532010-03-09 05:19:25 +000067 /// Listen backlog
Mark Slee2f6404d2006-10-10 01:37:40 +000068 static const int LISTEN_BACKLOG = 1024;
69
David Reiss01fe1532010-03-09 05:19:25 +000070 /// Default limit on size of idle connection pool
Kevin Clarkcbcd63a2009-03-19 03:50:05 +000071 static const size_t CONNECTION_STACK_LIMIT = 1024;
72
David Reiss01fe1532010-03-09 05:19:25 +000073 /// Default limit on total number of connected sockets
74 static const int MAX_CONNECTIONS = INT_MAX;
75
76 /// Default limit on connections in handler/task processing
77 static const int MAX_ACTIVE_PROCESSORS = INT_MAX;
78
David Reiss89a12942010-10-06 17:10:52 +000079 /// Default size of write buffer
80 static const int WRITE_BUFFER_DEFAULT_SIZE = 1024;
81
David Reiss54bec5d2010-10-06 17:10:45 +000082 /// Maximum size of read buffer allocated to idle connection (0 = unlimited)
83 static const int IDLE_READ_BUFFER_LIMIT = 1024;
84
85 /// Maximum size of write buffer allocated to idle connection (0 = unlimited)
86 static const int IDLE_WRITE_BUFFER_LIMIT = 1024;
87
88 /// # of calls before resizing oversized buffers (0 = check only on close)
89 static const int RESIZE_BUFFER_EVERY_N = 512;
90
David Reiss01fe1532010-03-09 05:19:25 +000091 /// Server socket file descriptor
Mark Slee2f6404d2006-10-10 01:37:40 +000092 int serverSocket_;
93
David Reiss01fe1532010-03-09 05:19:25 +000094 /// Port server runs on
Mark Slee2f6404d2006-10-10 01:37:40 +000095 int port_;
96
David Reiss01fe1532010-03-09 05:19:25 +000097 /// For processing via thread pool, may be NULL
Mark Sleee02385b2007-06-09 01:21:16 +000098 boost::shared_ptr<ThreadManager> threadManager_;
99
David Reiss01fe1532010-03-09 05:19:25 +0000100 /// Is thread pool processing?
Mark Sleee02385b2007-06-09 01:21:16 +0000101 bool threadPoolProcessing_;
102
David Reiss01fe1532010-03-09 05:19:25 +0000103 /// The event base for libevent
Mark Slee79b16942007-11-26 19:05:29 +0000104 event_base* eventBase_;
105
David Reiss01fe1532010-03-09 05:19:25 +0000106 /// Event struct, used with eventBase_ for connection events
Mark Slee79b16942007-11-26 19:05:29 +0000107 struct event serverEvent_;
108
David Reiss01fe1532010-03-09 05:19:25 +0000109 /// Event struct, used with eventBase_ for task completion notification
110 struct event notificationEvent_;
111
112 /// Number of TConnection object we've created
David Reiss1997f102008-04-29 00:29:41 +0000113 size_t numTConnections_;
114
David Reiss9e8073c2010-03-09 05:19:39 +0000115 /// Number of Connections processing or waiting to process
David Reiss01fe1532010-03-09 05:19:25 +0000116 size_t numActiveProcessors_;
117
118 /// Limit for how many TConnection objects to cache
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000119 size_t connectionStackLimit_;
120
David Reiss01fe1532010-03-09 05:19:25 +0000121 /// Limit for number of connections processing or waiting to process
122 size_t maxActiveProcessors_;
123
124 /// Limit for number of open connections
125 size_t maxConnections_;
126
David Reiss068f4162010-03-09 05:19:45 +0000127 /// Time in milliseconds before an unperformed task expires (0 == infinite).
128 int64_t taskExpireTime_;
129
David Reiss01fe1532010-03-09 05:19:25 +0000130 /**
131 * Hysteresis for overload state. This is the fraction of the overload
132 * value that needs to be reached before the overload state is cleared;
133 * must be <= 1.0.
134 */
135 double overloadHysteresis_;
136
137 /// Action to take when we're overloaded.
138 TOverloadAction overloadAction_;
139
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000140 /**
David Reiss89a12942010-10-06 17:10:52 +0000141 * The write buffer is initialized (and when idleWriteBufferLimit_ is checked
142 * and found to be exceeded, reinitialized) to this size.
143 */
144 size_t writeBufferDefaultSize_;
145
146 /**
David Reiss54bec5d2010-10-06 17:10:45 +0000147 * Max read buffer size for an idle TConnection. When we place an idle
148 * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls,
David Reiss89a12942010-10-06 17:10:52 +0000149 * we will free the buffer (such that it will be reinitialized by the next
150 * received frame) if it has exceeded this limit. 0 disables this check.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000151 */
David Reiss54bec5d2010-10-06 17:10:45 +0000152 size_t idleReadBufferLimit_;
153
154 /**
155 * Max write buffer size for an idle connection. When we place an idle
156 * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls,
157 * we insure that its write buffer is <= to this size; otherwise we
David Reiss89a12942010-10-06 17:10:52 +0000158 * replace it with a new one of writeBufferDefaultSize_ bytes to insure that
159 * idle connections don't hog memory. 0 disables this check.
David Reiss54bec5d2010-10-06 17:10:45 +0000160 */
161 size_t idleWriteBufferLimit_;
162
163 /**
164 * Every N calls we check the buffer size limits on a connected TConnection.
165 * 0 disables (i.e. the checks are only done when a connection closes).
166 */
167 int32_t resizeBufferEveryN_;
David Reiss01fe1532010-03-09 05:19:25 +0000168
169 /// Set if we are currently in an overloaded state.
170 bool overloaded_;
171
172 /// Count of connections dropped since overload started
173 uint32_t nConnectionsDropped_;
174
175 /// Count of connections dropped on overload since server started
176 uint64_t nTotalConnectionsDropped_;
177
178 /// File descriptors for pipe used for task completion notification.
179 int notificationPipeFDs_[2];
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000180
Mark Slee2f6404d2006-10-10 01:37:40 +0000181 /**
182 * This is a stack of all the objects that have been created but that
183 * are NOT currently in use. When we close a connection, we place it on this
184 * stack so that the object can be reused later, rather than freeing the
185 * memory and reallocating a new object later.
186 */
187 std::stack<TConnection*> connectionStack_;
188
David Reiss01fe1532010-03-09 05:19:25 +0000189 /**
190 * Called when server socket had something happen. We accept all waiting
191 * client connections on listen socket fd and assign TConnection objects
192 * to handle those requests.
193 *
194 * @param fd the listen socket.
195 * @param which the event flag that triggered the handler.
196 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000197 void handleEvent(int fd, short which);
198
199 public:
Mark Slee5ea15f92007-03-05 22:55:59 +0000200 TNonblockingServer(boost::shared_ptr<TProcessor> processor,
Mark Sleef9373392007-01-24 19:41:57 +0000201 int port) :
202 TServer(processor),
Mark Slee79b16942007-11-26 19:05:29 +0000203 serverSocket_(-1),
Mark Sleef9373392007-01-24 19:41:57 +0000204 port_(port),
dweatherford58985992007-06-19 23:10:19 +0000205 threadPoolProcessing_(false),
David Reiss1997f102008-04-29 00:29:41 +0000206 eventBase_(NULL),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000207 numTConnections_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000208 numActiveProcessors_(0),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000209 connectionStackLimit_(CONNECTION_STACK_LIMIT),
David Reiss01fe1532010-03-09 05:19:25 +0000210 maxActiveProcessors_(MAX_ACTIVE_PROCESSORS),
211 maxConnections_(MAX_CONNECTIONS),
David Reiss068f4162010-03-09 05:19:45 +0000212 taskExpireTime_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000213 overloadHysteresis_(0.8),
214 overloadAction_(T_OVERLOAD_NO_ACTION),
David Reiss89a12942010-10-06 17:10:52 +0000215 writeBufferDefaultSize_(WRITE_BUFFER_DEFAULT_SIZE),
David Reiss54bec5d2010-10-06 17:10:45 +0000216 idleReadBufferLimit_(IDLE_READ_BUFFER_LIMIT),
217 idleWriteBufferLimit_(IDLE_WRITE_BUFFER_LIMIT),
218 resizeBufferEveryN_(RESIZE_BUFFER_EVERY_N),
David Reiss01fe1532010-03-09 05:19:25 +0000219 overloaded_(false),
220 nConnectionsDropped_(0),
221 nTotalConnectionsDropped_(0) {}
Mark Sleef9373392007-01-24 19:41:57 +0000222
Mark Slee79b16942007-11-26 19:05:29 +0000223 TNonblockingServer(boost::shared_ptr<TProcessor> processor,
Mark Slee5ea15f92007-03-05 22:55:59 +0000224 boost::shared_ptr<TProtocolFactory> protocolFactory,
Mark Sleee02385b2007-06-09 01:21:16 +0000225 int port,
226 boost::shared_ptr<ThreadManager> threadManager = boost::shared_ptr<ThreadManager>()) :
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000227 TServer(processor),
Mark Slee79b16942007-11-26 19:05:29 +0000228 serverSocket_(-1),
Mark Slee92f00fb2006-10-25 01:28:17 +0000229 port_(port),
Mark Slee79b16942007-11-26 19:05:29 +0000230 threadManager_(threadManager),
David Reiss1997f102008-04-29 00:29:41 +0000231 eventBase_(NULL),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000232 numTConnections_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000233 numActiveProcessors_(0),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000234 connectionStackLimit_(CONNECTION_STACK_LIMIT),
David Reiss01fe1532010-03-09 05:19:25 +0000235 maxActiveProcessors_(MAX_ACTIVE_PROCESSORS),
236 maxConnections_(MAX_CONNECTIONS),
David Reiss068f4162010-03-09 05:19:45 +0000237 taskExpireTime_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000238 overloadHysteresis_(0.8),
239 overloadAction_(T_OVERLOAD_NO_ACTION),
David Reiss89a12942010-10-06 17:10:52 +0000240 writeBufferDefaultSize_(WRITE_BUFFER_DEFAULT_SIZE),
David Reiss54bec5d2010-10-06 17:10:45 +0000241 idleReadBufferLimit_(IDLE_READ_BUFFER_LIMIT),
242 idleWriteBufferLimit_(IDLE_WRITE_BUFFER_LIMIT),
243 resizeBufferEveryN_(RESIZE_BUFFER_EVERY_N),
David Reiss01fe1532010-03-09 05:19:25 +0000244 overloaded_(false),
245 nConnectionsDropped_(0),
246 nTotalConnectionsDropped_(0) {
Mark Slee5ea15f92007-03-05 22:55:59 +0000247 setInputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
248 setOutputTransportFactory(boost::shared_ptr<TTransportFactory>(new TTransportFactory()));
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000249 setInputProtocolFactory(protocolFactory);
250 setOutputProtocolFactory(protocolFactory);
Mark Sleee02385b2007-06-09 01:21:16 +0000251 setThreadManager(threadManager);
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000252 }
Aditya Agarwal1ea90522007-01-19 02:02:12 +0000253
Mark Slee5ea15f92007-03-05 22:55:59 +0000254 TNonblockingServer(boost::shared_ptr<TProcessor> processor,
255 boost::shared_ptr<TTransportFactory> inputTransportFactory,
256 boost::shared_ptr<TTransportFactory> outputTransportFactory,
257 boost::shared_ptr<TProtocolFactory> inputProtocolFactory,
258 boost::shared_ptr<TProtocolFactory> outputProtocolFactory,
Mark Sleee02385b2007-06-09 01:21:16 +0000259 int port,
260 boost::shared_ptr<ThreadManager> threadManager = boost::shared_ptr<ThreadManager>()) :
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000261 TServer(processor),
David Reiss01fe1532010-03-09 05:19:25 +0000262 serverSocket_(-1),
Aditya Agarwal1ea90522007-01-19 02:02:12 +0000263 port_(port),
Mark Slee5d1784a2007-12-05 23:20:54 +0000264 threadManager_(threadManager),
David Reiss1997f102008-04-29 00:29:41 +0000265 eventBase_(NULL),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000266 numTConnections_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000267 numActiveProcessors_(0),
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000268 connectionStackLimit_(CONNECTION_STACK_LIMIT),
David Reiss01fe1532010-03-09 05:19:25 +0000269 maxActiveProcessors_(MAX_ACTIVE_PROCESSORS),
270 maxConnections_(MAX_CONNECTIONS),
David Reiss068f4162010-03-09 05:19:45 +0000271 taskExpireTime_(0),
David Reiss01fe1532010-03-09 05:19:25 +0000272 overloadHysteresis_(0.8),
273 overloadAction_(T_OVERLOAD_NO_ACTION),
David Reiss89a12942010-10-06 17:10:52 +0000274 writeBufferDefaultSize_(WRITE_BUFFER_DEFAULT_SIZE),
David Reiss54bec5d2010-10-06 17:10:45 +0000275 idleReadBufferLimit_(IDLE_READ_BUFFER_LIMIT),
276 idleWriteBufferLimit_(IDLE_WRITE_BUFFER_LIMIT),
277 resizeBufferEveryN_(RESIZE_BUFFER_EVERY_N),
David Reiss01fe1532010-03-09 05:19:25 +0000278 overloaded_(false),
279 nConnectionsDropped_(0),
David Reiss068f4162010-03-09 05:19:45 +0000280 nTotalConnectionsDropped_(0) {
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000281 setInputTransportFactory(inputTransportFactory);
282 setOutputTransportFactory(outputTransportFactory);
283 setInputProtocolFactory(inputProtocolFactory);
284 setOutputProtocolFactory(outputProtocolFactory);
Mark Sleee02385b2007-06-09 01:21:16 +0000285 setThreadManager(threadManager);
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000286 }
Mark Slee79b16942007-11-26 19:05:29 +0000287
David Reiss8ede8182010-09-02 15:26:28 +0000288 ~TNonblockingServer();
Mark Slee2f6404d2006-10-10 01:37:40 +0000289
David Reiss068f4162010-03-09 05:19:45 +0000290 void setThreadManager(boost::shared_ptr<ThreadManager> threadManager);
Mark Sleee02385b2007-06-09 01:21:16 +0000291
David Reiss1997f102008-04-29 00:29:41 +0000292 boost::shared_ptr<ThreadManager> getThreadManager() {
293 return threadManager_;
294 }
295
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000296 /**
297 * Get the maximum number of unused TConnection we will hold in reserve.
298 *
299 * @return the current limit on TConnection pool size.
300 */
David Reiss260fa932009-04-02 23:51:39 +0000301 size_t getConnectionStackLimit() const {
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000302 return connectionStackLimit_;
303 }
304
305 /**
306 * Set the maximum number of unused TConnection we will hold in reserve.
307 *
308 * @param sz the new limit for TConnection pool size.
309 */
David Reiss260fa932009-04-02 23:51:39 +0000310 void setConnectionStackLimit(size_t sz) {
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000311 connectionStackLimit_ = sz;
312 }
313
Mark Slee79b16942007-11-26 19:05:29 +0000314 bool isThreadPoolProcessing() const {
Mark Sleee02385b2007-06-09 01:21:16 +0000315 return threadPoolProcessing_;
316 }
317
318 void addTask(boost::shared_ptr<Runnable> task) {
David Reiss068f4162010-03-09 05:19:45 +0000319 threadManager_->add(task, 0LL, taskExpireTime_);
Mark Sleee02385b2007-06-09 01:21:16 +0000320 }
321
Mark Slee79b16942007-11-26 19:05:29 +0000322 event_base* getEventBase() const {
323 return eventBase_;
324 }
325
David Reiss01fe1532010-03-09 05:19:25 +0000326 /// Increment our count of the number of connected sockets.
David Reissc17fe6b2008-04-29 00:29:43 +0000327 void incrementNumConnections() {
328 ++numTConnections_;
329 }
330
David Reiss01fe1532010-03-09 05:19:25 +0000331 /// Decrement our count of the number of connected sockets.
David Reissc17fe6b2008-04-29 00:29:43 +0000332 void decrementNumConnections() {
333 --numTConnections_;
David Reiss1997f102008-04-29 00:29:41 +0000334 }
335
David Reiss01fe1532010-03-09 05:19:25 +0000336 /**
337 * Return the count of sockets currently connected to.
338 *
339 * @return count of connected sockets.
340 */
341 size_t getNumConnections() const {
David Reiss1997f102008-04-29 00:29:41 +0000342 return numTConnections_;
343 }
344
David Reiss01fe1532010-03-09 05:19:25 +0000345 /**
346 * Return the count of connection objects allocated but not in use.
347 *
348 * @return count of idle connection objects.
349 */
350 size_t getNumIdleConnections() const {
David Reiss1997f102008-04-29 00:29:41 +0000351 return connectionStack_.size();
352 }
353
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000354 /**
David Reiss01fe1532010-03-09 05:19:25 +0000355 * Return count of number of connections which are currently processing.
356 * This is defined as a connection where all data has been received and
357 * either assigned a task (when threading) or passed to a handler (when
358 * not threading), and where the handler has not yet returned.
359 *
360 * @return # of connections currently processing.
361 */
362 size_t getNumActiveProcessors() const {
363 return numActiveProcessors_;
364 }
365
366 /// Increment the count of connections currently processing.
367 void incrementActiveProcessors() {
368 ++numActiveProcessors_;
369 }
370
371 /// Decrement the count of connections currently processing.
372 void decrementActiveProcessors() {
373 if (numActiveProcessors_ > 0) {
374 --numActiveProcessors_;
375 }
376 }
377
378 /**
379 * Get the maximum # of connections allowed before overload.
380 *
381 * @return current setting.
382 */
383 size_t getMaxConnections() const {
384 return maxConnections_;
385 }
386
387 /**
388 * Set the maximum # of connections allowed before overload.
389 *
390 * @param maxConnections new setting for maximum # of connections.
391 */
392 void setMaxConnections(size_t maxConnections) {
393 maxConnections_ = maxConnections;
394 }
395
396 /**
397 * Get the maximum # of connections waiting in handler/task before overload.
398 *
399 * @return current setting.
400 */
401 size_t getMaxActiveProcessors() const {
402 return maxActiveProcessors_;
403 }
404
405 /**
406 * Set the maximum # of connections waiting in handler/task before overload.
407 *
408 * @param maxActiveProcessors new setting for maximum # of active processes.
409 */
410 void setMaxActiveProcessors(size_t maxActiveProcessors) {
411 maxActiveProcessors_ = maxActiveProcessors;
412 }
413
414 /**
415 * Get fraction of maximum limits before an overload condition is cleared.
416 *
417 * @return hysteresis fraction
418 */
419 double getOverloadHysteresis() const {
420 return overloadHysteresis_;
421 }
422
423 /**
424 * Set fraction of maximum limits before an overload condition is cleared.
425 * A good value would probably be between 0.5 and 0.9.
426 *
427 * @param hysteresisFraction fraction <= 1.0.
428 */
429 void setOverloadHysteresis(double hysteresisFraction) {
430 if (hysteresisFraction <= 1.0 && hysteresisFraction > 0.0) {
431 overloadHysteresis_ = hysteresisFraction;
432 }
433 }
434
435 /**
436 * Get the action the server will take on overload.
437 *
438 * @return a TOverloadAction enum value for the currently set action.
439 */
440 TOverloadAction getOverloadAction() const {
441 return overloadAction_;
442 }
443
444 /**
445 * Set the action the server is to take on overload.
446 *
447 * @param overloadAction a TOverloadAction enum value for the action.
448 */
449 void setOverloadAction(TOverloadAction overloadAction) {
450 overloadAction_ = overloadAction;
451 }
452
453 /**
David Reiss068f4162010-03-09 05:19:45 +0000454 * Get the time in milliseconds after which a task expires (0 == infinite).
455 *
456 * @return a 64-bit time in milliseconds.
457 */
458 int64_t getTaskExpireTime() const {
459 return taskExpireTime_;
460 }
461
462 /**
463 * Set the time in milliseconds after which a task expires (0 == infinite).
464 *
465 * @param taskExpireTime a 64-bit time in milliseconds.
466 */
467 void setTaskExpireTime(int64_t taskExpireTime) {
468 taskExpireTime_ = taskExpireTime;
469 }
470
471 /**
David Reiss01fe1532010-03-09 05:19:25 +0000472 * Determine if the server is currently overloaded.
473 * This function checks the maximums for open connections and connections
474 * currently in processing, and sets an overload condition if they are
475 * exceeded. The overload will persist until both values are below the
476 * current hysteresis fraction of their maximums.
477 *
478 * @return true if an overload condition exists, false if not.
479 */
480 bool serverOverloaded();
481
482 /** Pop and discard next task on threadpool wait queue.
483 *
484 * @return true if a task was discarded, false if the wait queue was empty.
485 */
486 bool drainPendingTask();
487
488 /**
David Reiss89a12942010-10-06 17:10:52 +0000489 * Get the starting size of a TConnection object's write buffer.
490 *
491 * @return # bytes we initialize a TConnection object's write buffer to.
492 */
493 size_t getWriteBufferDefaultSize() const {
494 return writeBufferDefaultSize_;
495 }
496
497 /**
498 * Set the starting size of a TConnection object's write buffer.
499 *
500 * @param size # bytes we initialize a TConnection object's write buffer to.
501 */
502 void setWriteBufferDefaultSize(size_t size) {
503 writeBufferDefaultSize_ = size;
504 }
505
506 /**
David Reiss54bec5d2010-10-06 17:10:45 +0000507 * Get the maximum size of read buffer allocated to idle TConnection objects.
508 *
David Reiss89a12942010-10-06 17:10:52 +0000509 * @return # bytes beyond which we will dealloc idle buffer.
David Reiss54bec5d2010-10-06 17:10:45 +0000510 */
511 size_t getIdleReadBufferLimit() const {
512 return idleReadBufferLimit_;
513 }
514
515 /**
516 * [NOTE: This is for backwards compatibility, use getIdleReadBufferLimit().]
517 * Get the maximum size of read buffer allocated to idle TConnection objects.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000518 *
David Reiss89a12942010-10-06 17:10:52 +0000519 * @return # bytes beyond which we will dealloc idle buffer.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000520 */
521 size_t getIdleBufferMemLimit() const {
David Reiss54bec5d2010-10-06 17:10:45 +0000522 return idleReadBufferLimit_;
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000523 }
524
525 /**
David Reiss54bec5d2010-10-06 17:10:45 +0000526 * Set the maximum size read buffer allocated to idle TConnection objects.
527 * If a TConnection object is found (either on connection close or between
528 * calls when resizeBufferEveryN_ is set) with more than this much memory
David Reiss89a12942010-10-06 17:10:52 +0000529 * allocated to its read buffer, we free it and allow it to be reinitialized
530 * on the next received frame.
David Reiss54bec5d2010-10-06 17:10:45 +0000531 *
532 * @param limit of bytes beyond which we will shrink buffers when checked.
533 */
534 void setIdleReadBufferLimit(size_t limit) {
535 idleReadBufferLimit_ = limit;
536 }
537
538 /**
539 * [NOTE: This is for backwards compatibility, use setIdleReadBufferLimit().]
540 * Set the maximum size read buffer allocated to idle TConnection objects.
541 * If a TConnection object is found (either on connection close or between
542 * calls when resizeBufferEveryN_ is set) with more than this much memory
David Reiss89a12942010-10-06 17:10:52 +0000543 * allocated to its read buffer, we free it and allow it to be reinitialized
544 * on the next received frame.
David Reiss54bec5d2010-10-06 17:10:45 +0000545 *
546 * @param limit of bytes beyond which we will shrink buffers when checked.
547 */
548 void setIdleBufferMemLimit(size_t limit) {
549 idleReadBufferLimit_ = limit;
550 }
551
552
553
554 /**
555 * Get the maximum size of write buffer allocated to idle TConnection objects.
556 *
557 * @return # bytes beyond which we will reallocate buffers when checked.
558 */
559 size_t getIdleWriteBufferLimit() const {
560 return idleWriteBufferLimit_;
561 }
562
563 /**
564 * Set the maximum size write buffer allocated to idle TConnection objects.
565 * If a TConnection object is found (either on connection close or between
566 * calls when resizeBufferEveryN_ is set) with more than this much memory
David Reiss89a12942010-10-06 17:10:52 +0000567 * allocated to its write buffer, we destroy and construct that buffer with
568 * writeBufferDefaultSize_ bytes.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000569 *
570 * @param limit of bytes beyond which we will shrink buffers when idle.
571 */
David Reiss54bec5d2010-10-06 17:10:45 +0000572 void setIdleWriteBufferLimit(size_t limit) {
573 idleWriteBufferLimit_ = limit;
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000574 }
575
David Reiss01fe1532010-03-09 05:19:25 +0000576 /**
David Reiss54bec5d2010-10-06 17:10:45 +0000577 * Get # of calls made between buffer size checks. 0 means disabled.
578 *
579 * @return # of calls between buffer size checks.
580 */
581 int32_t getResizeBufferEveryN() const {
582 return resizeBufferEveryN_;
583 }
584
585 /**
586 * Check buffer sizes every "count" calls. This allows buffer limits
587 * to be enforced for persistant connections with a controllable degree
588 * of overhead. 0 disables checks except at connection close.
589 *
590 * @param count the number of calls between checks, or 0 to disable
591 */
592 void setResizeBufferEveryN(int32_t count) {
593 resizeBufferEveryN_ = count;
594 }
595
596
597
598 /**
David Reiss01fe1532010-03-09 05:19:25 +0000599 * Return an initialized connection object. Creates or recovers from
600 * pool a TConnection and initializes it with the provided socket FD
601 * and flags.
602 *
603 * @param socket FD of socket associated with this connection.
604 * @param flags initial lib_event flags for this connection.
David Reiss105961d2010-10-06 17:10:17 +0000605 * @param addr the sockaddr of the client
606 * @param addrLen the length of addr
David Reiss01fe1532010-03-09 05:19:25 +0000607 * @return pointer to initialized TConnection object.
608 */
David Reiss105961d2010-10-06 17:10:17 +0000609 TConnection* createConnection(int socket, short flags,
610 const sockaddr* addr, socklen_t addrLen);
Mark Slee2f6404d2006-10-10 01:37:40 +0000611
David Reiss01fe1532010-03-09 05:19:25 +0000612 /**
613 * Returns a connection to pool or deletion. If the connection pool
614 * (a stack) isn't full, place the connection object on it, otherwise
615 * just delete it.
616 *
617 * @param connection the TConection being returned.
618 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000619 void returnConnection(TConnection* connection);
620
David Reiss01fe1532010-03-09 05:19:25 +0000621 /**
David Reiss068f4162010-03-09 05:19:45 +0000622 * Callback function that the threadmanager calls when a task reaches
623 * its expiration time. It is needed to clean up the expired connection.
624 *
625 * @param task the runnable associated with the expired task.
626 */
627 void expireClose(boost::shared_ptr<Runnable> task);
628
629 /**
David Reiss01fe1532010-03-09 05:19:25 +0000630 * C-callable event handler for listener events. Provides a callback
631 * that libevent can understand which invokes server->handleEvent().
632 *
633 * @param fd the descriptor the event occured on.
634 * @param which the flags associated with the event.
635 * @param v void* callback arg where we placed TNonblockingServer's "this".
636 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000637 static void eventHandler(int fd, short which, void* v) {
638 ((TNonblockingServer*)v)->handleEvent(fd, which);
639 }
640
David Reiss01fe1532010-03-09 05:19:25 +0000641 /// Creates a socket to listen on and binds it to the local port.
Mark Slee79b16942007-11-26 19:05:29 +0000642 void listenSocket();
643
David Reiss01fe1532010-03-09 05:19:25 +0000644 /**
645 * Takes a socket created by listenSocket() and sets various options on it
646 * to prepare for use in the server.
647 *
648 * @param fd descriptor of socket to be initialized/
649 */
Mark Slee79b16942007-11-26 19:05:29 +0000650 void listenSocket(int fd);
651
David Reiss01fe1532010-03-09 05:19:25 +0000652 /// Create the pipe used to notify I/O process of task completion.
653 void createNotificationPipe();
654
655 /**
656 * Get notification pipe send descriptor.
657 *
658 * @return write fd for pipe.
659 */
660 int getNotificationSendFD() const {
661 return notificationPipeFDs_[1];
662 }
663
664 /**
665 * Get notification pipe receive descriptor.
666 *
667 * @return read fd of pipe.
668 */
669 int getNotificationRecvFD() const {
670 return notificationPipeFDs_[0];
671 }
672
673 /**
674 * Register the core libevent events onto the proper base.
675 *
676 * @param base pointer to the event base to be initialized.
677 */
Mark Slee79b16942007-11-26 19:05:29 +0000678 void registerEvents(event_base* base);
679
David Reiss01fe1532010-03-09 05:19:25 +0000680 /**
681 * Main workhorse function, starts up the server listening on a port and
682 * loops over the libevent handler.
683 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000684 void serve();
685};
686
David Reiss89a12942010-10-06 17:10:52 +0000687/// Three states for sockets: recv frame size, recv data, and send mode
Mark Slee2f6404d2006-10-10 01:37:40 +0000688enum TSocketState {
David Reiss89a12942010-10-06 17:10:52 +0000689 SOCKET_RECV_FRAMING,
Mark Slee2f6404d2006-10-10 01:37:40 +0000690 SOCKET_RECV,
691 SOCKET_SEND
692};
693
694/**
David Reiss01fe1532010-03-09 05:19:25 +0000695 * Five states for the nonblocking servr:
Mark Slee2f6404d2006-10-10 01:37:40 +0000696 * 1) initialize
697 * 2) read 4 byte frame size
698 * 3) read frame of data
699 * 4) send back data (if any)
David Reiss01fe1532010-03-09 05:19:25 +0000700 * 5) force immediate connection close
Mark Slee2f6404d2006-10-10 01:37:40 +0000701 */
702enum TAppState {
703 APP_INIT,
704 APP_READ_FRAME_SIZE,
705 APP_READ_REQUEST,
Mark Sleee02385b2007-06-09 01:21:16 +0000706 APP_WAIT_TASK,
David Reiss01fe1532010-03-09 05:19:25 +0000707 APP_SEND_RESULT,
708 APP_CLOSE_CONNECTION
Mark Slee2f6404d2006-10-10 01:37:40 +0000709};
710
711/**
712 * Represents a connection that is handled via libevent. This connection
713 * essentially encapsulates a socket that has some associated libevent state.
714 */
David Reiss54bec5d2010-10-06 17:10:45 +0000715class TConnection {
Mark Slee2f6404d2006-10-10 01:37:40 +0000716 private:
717
David Reiss01fe1532010-03-09 05:19:25 +0000718 /// Server handle
Mark Slee2f6404d2006-10-10 01:37:40 +0000719 TNonblockingServer* server_;
720
David Reiss105961d2010-10-06 17:10:17 +0000721 /// Object wrapping network socket
722 boost::shared_ptr<TSocket> tSocket_;
Mark Slee2f6404d2006-10-10 01:37:40 +0000723
David Reiss01fe1532010-03-09 05:19:25 +0000724 /// Libevent object
Mark Slee2f6404d2006-10-10 01:37:40 +0000725 struct event event_;
726
David Reiss01fe1532010-03-09 05:19:25 +0000727 /// Libevent flags
Mark Slee2f6404d2006-10-10 01:37:40 +0000728 short eventFlags_;
729
David Reiss01fe1532010-03-09 05:19:25 +0000730 /// Socket mode
Mark Slee2f6404d2006-10-10 01:37:40 +0000731 TSocketState socketState_;
732
David Reiss01fe1532010-03-09 05:19:25 +0000733 /// Application state
Mark Slee2f6404d2006-10-10 01:37:40 +0000734 TAppState appState_;
735
David Reiss01fe1532010-03-09 05:19:25 +0000736 /// How much data needed to read
Mark Slee2f6404d2006-10-10 01:37:40 +0000737 uint32_t readWant_;
738
David Reiss01fe1532010-03-09 05:19:25 +0000739 /// Where in the read buffer are we
Mark Slee2f6404d2006-10-10 01:37:40 +0000740 uint32_t readBufferPos_;
741
David Reiss01fe1532010-03-09 05:19:25 +0000742 /// Read buffer
Mark Slee2f6404d2006-10-10 01:37:40 +0000743 uint8_t* readBuffer_;
744
David Reiss01fe1532010-03-09 05:19:25 +0000745 /// Read buffer size
Mark Slee2f6404d2006-10-10 01:37:40 +0000746 uint32_t readBufferSize_;
747
David Reiss01fe1532010-03-09 05:19:25 +0000748 /// Write buffer
Mark Slee2f6404d2006-10-10 01:37:40 +0000749 uint8_t* writeBuffer_;
Mark Slee79b16942007-11-26 19:05:29 +0000750
David Reiss01fe1532010-03-09 05:19:25 +0000751 /// Write buffer size
Mark Slee2f6404d2006-10-10 01:37:40 +0000752 uint32_t writeBufferSize_;
753
David Reiss01fe1532010-03-09 05:19:25 +0000754 /// How far through writing are we?
Mark Slee2f6404d2006-10-10 01:37:40 +0000755 uint32_t writeBufferPos_;
756
David Reiss54bec5d2010-10-06 17:10:45 +0000757 /// Largest size of write buffer seen since buffer was constructed
758 size_t largestWriteBufferSize_;
759
760 /// Count of the number of calls for use with getResizeBufferEveryN().
761 int32_t callsForResize_;
762
David Reiss01fe1532010-03-09 05:19:25 +0000763 /// Task handle
Mark Sleee02385b2007-06-09 01:21:16 +0000764 int taskHandle_;
765
David Reiss01fe1532010-03-09 05:19:25 +0000766 /// Task event
Mark Sleee02385b2007-06-09 01:21:16 +0000767 struct event taskEvent_;
768
David Reiss01fe1532010-03-09 05:19:25 +0000769 /// Transport to read from
Mark Slee5ea15f92007-03-05 22:55:59 +0000770 boost::shared_ptr<TMemoryBuffer> inputTransport_;
Mark Slee2f6404d2006-10-10 01:37:40 +0000771
David Reiss01fe1532010-03-09 05:19:25 +0000772 /// Transport that processor writes to
Mark Slee5ea15f92007-03-05 22:55:59 +0000773 boost::shared_ptr<TMemoryBuffer> outputTransport_;
Mark Slee2f6404d2006-10-10 01:37:40 +0000774
David Reiss01fe1532010-03-09 05:19:25 +0000775 /// extra transport generated by transport factory (e.g. BufferedRouterTransport)
Mark Slee5ea15f92007-03-05 22:55:59 +0000776 boost::shared_ptr<TTransport> factoryInputTransport_;
777 boost::shared_ptr<TTransport> factoryOutputTransport_;
Mark Slee4af6ed72006-10-25 19:02:49 +0000778
David Reiss01fe1532010-03-09 05:19:25 +0000779 /// Protocol decoder
Mark Slee5ea15f92007-03-05 22:55:59 +0000780 boost::shared_ptr<TProtocol> inputProtocol_;
Aditya Agarwal9abb0d62007-01-24 22:53:54 +0000781
David Reiss01fe1532010-03-09 05:19:25 +0000782 /// Protocol encoder
Mark Slee5ea15f92007-03-05 22:55:59 +0000783 boost::shared_ptr<TProtocol> outputProtocol_;
Mark Slee79b16942007-11-26 19:05:29 +0000784
David Reiss105961d2010-10-06 17:10:17 +0000785 /// Server event handler, if any
786 boost::shared_ptr<TServerEventHandler> serverEventHandler_;
787
788 /// Thrift call context, if any
789 void *connectionContext_;
790
David Reiss01fe1532010-03-09 05:19:25 +0000791 /// Go into read mode
Mark Slee2f6404d2006-10-10 01:37:40 +0000792 void setRead() {
793 setFlags(EV_READ | EV_PERSIST);
794 }
795
David Reiss01fe1532010-03-09 05:19:25 +0000796 /// Go into write mode
Mark Slee2f6404d2006-10-10 01:37:40 +0000797 void setWrite() {
798 setFlags(EV_WRITE | EV_PERSIST);
799 }
800
David Reiss01fe1532010-03-09 05:19:25 +0000801 /// Set socket idle
Mark Slee402ee282007-08-23 01:43:20 +0000802 void setIdle() {
803 setFlags(0);
804 }
805
David Reiss01fe1532010-03-09 05:19:25 +0000806 /**
807 * Set event flags for this connection.
808 *
809 * @param eventFlags flags we pass to libevent for the connection.
810 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000811 void setFlags(short eventFlags);
812
David Reiss01fe1532010-03-09 05:19:25 +0000813 /**
814 * Libevent handler called (via our static wrapper) when the connection
815 * socket had something happen. Rather than use the flags libevent passed,
816 * we use the connection state to determine whether we need to read or
817 * write the socket.
818 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000819 void workSocket();
820
David Reiss01fe1532010-03-09 05:19:25 +0000821 /// Close this connection and free or reset its resources.
Mark Slee2f6404d2006-10-10 01:37:40 +0000822 void close();
823
824 public:
825
David Reiss01fe1532010-03-09 05:19:25 +0000826 class Task;
827
828 /// Constructor
David Reiss105961d2010-10-06 17:10:17 +0000829 TConnection(int socket, short eventFlags, TNonblockingServer *s,
830 const sockaddr* addr, socklen_t addrLen) {
David Reiss89a12942010-10-06 17:10:52 +0000831 readBuffer_ = NULL;
832 readBufferSize_ = 0;
Mark Slee79b16942007-11-26 19:05:29 +0000833
Mark Slee2f6404d2006-10-10 01:37:40 +0000834 // Allocate input and output tranpsorts
Mark Slee79b16942007-11-26 19:05:29 +0000835 // these only need to be allocated once per TConnection (they don't need to be
Aditya Agarwal1ea90522007-01-19 02:02:12 +0000836 // reallocated on init() call)
Mark Slee5ea15f92007-03-05 22:55:59 +0000837 inputTransport_ = boost::shared_ptr<TMemoryBuffer>(new TMemoryBuffer(readBuffer_, readBufferSize_));
David Reiss89a12942010-10-06 17:10:52 +0000838 outputTransport_ = boost::shared_ptr<TMemoryBuffer>(new TMemoryBuffer(s->getWriteBufferDefaultSize()));
David Reiss105961d2010-10-06 17:10:17 +0000839 tSocket_.reset(new TSocket());
Mark Slee79b16942007-11-26 19:05:29 +0000840
David Reiss105961d2010-10-06 17:10:17 +0000841 init(socket, eventFlags, s, addr, addrLen);
David Reiss1997f102008-04-29 00:29:41 +0000842 server_->incrementNumConnections();
843 }
844
845 ~TConnection() {
David Reiss472fffb2010-03-09 05:20:24 +0000846 std::free(readBuffer_);
David Reissc17fe6b2008-04-29 00:29:43 +0000847 server_->decrementNumConnections();
Mark Slee2f6404d2006-10-10 01:37:40 +0000848 }
849
David Reiss54bec5d2010-10-06 17:10:45 +0000850 /**
851 * Check buffers against any size limits and shrink it if exceeded.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000852 *
David Reiss54bec5d2010-10-06 17:10:45 +0000853 * @param readLimit we reduce read buffer size to this (if nonzero).
854 * @param writeLimit if nonzero and write buffer is larger, replace it.
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000855 */
David Reiss54bec5d2010-10-06 17:10:45 +0000856 void checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit);
Kevin Clarkcbcd63a2009-03-19 03:50:05 +0000857
David Reiss01fe1532010-03-09 05:19:25 +0000858 /// Initialize
David Reiss105961d2010-10-06 17:10:17 +0000859 void init(int socket, short eventFlags, TNonblockingServer *s,
860 const sockaddr* addr, socklen_t addrLen);
Mark Slee2f6404d2006-10-10 01:37:40 +0000861
David Reiss01fe1532010-03-09 05:19:25 +0000862 /**
863 * This is called when the application transitions from one state into
864 * another. This means that it has finished writing the data that it needed
865 * to, or finished receiving the data that it needed to.
866 */
Mark Slee2f6404d2006-10-10 01:37:40 +0000867 void transition();
868
David Reiss01fe1532010-03-09 05:19:25 +0000869 /**
870 * C-callable event handler for connection events. Provides a callback
871 * that libevent can understand which invokes connection_->workSocket().
872 *
873 * @param fd the descriptor the event occured on.
874 * @param which the flags associated with the event.
875 * @param v void* callback arg where we placed TConnection's "this".
876 */
Mark Sleea8de4892008-02-09 00:02:26 +0000877 static void eventHandler(int fd, short /* which */, void* v) {
David Reiss105961d2010-10-06 17:10:17 +0000878 assert(fd == ((TConnection*)v)->getTSocket()->getSocketFD());
Mark Slee2f6404d2006-10-10 01:37:40 +0000879 ((TConnection*)v)->workSocket();
880 }
Mark Slee79b16942007-11-26 19:05:29 +0000881
David Reiss01fe1532010-03-09 05:19:25 +0000882 /**
883 * C-callable event handler for signaling task completion. Provides a
884 * callback that libevent can understand that will read a connection
885 * object's address from a pipe and call connection->transition() for
886 * that object.
887 *
888 * @param fd the descriptor the event occured on.
889 */
890 static void taskHandler(int fd, short /* which */, void* /* v */) {
891 TConnection* connection;
David Reiss83b8fda2010-03-09 05:19:34 +0000892 ssize_t nBytes;
893 while ((nBytes = read(fd, (void*)&connection, sizeof(TConnection*)))
894 == sizeof(TConnection*)) {
895 connection->transition();
Mark Sleee02385b2007-06-09 01:21:16 +0000896 }
David Reiss83b8fda2010-03-09 05:19:34 +0000897 if (nBytes > 0) {
898 throw TException("TConnection::taskHandler unexpected partial read");
899 }
900 if (errno != EWOULDBLOCK && errno != EAGAIN) {
901 GlobalOutput.perror("TConnection::taskHandler read failed, resource leak", errno);
902 }
Mark Sleee02385b2007-06-09 01:21:16 +0000903 }
904
David Reiss01fe1532010-03-09 05:19:25 +0000905 /**
906 * Notification to server that processing has ended on this request.
907 * Can be called either when processing is completed or when a waiting
908 * task has been preemptively terminated (on overload).
909 *
David Reiss9e8073c2010-03-09 05:19:39 +0000910 * @return true if successful, false if unable to notify (check errno).
David Reiss01fe1532010-03-09 05:19:25 +0000911 */
912 bool notifyServer() {
913 TConnection* connection = this;
914 if (write(server_->getNotificationSendFD(), (const void*)&connection,
915 sizeof(TConnection*)) != sizeof(TConnection*)) {
916 return false;
917 }
918
919 return true;
920 }
921
922 /// Force connection shutdown for this connection.
923 void forceClose() {
924 appState_ = APP_CLOSE_CONNECTION;
925 if (!notifyServer()) {
926 throw TException("TConnection::forceClose: failed write on notify pipe");
927 }
928 }
929
930 /// return the server this connection was initialized for.
931 TNonblockingServer* getServer() {
932 return server_;
933 }
934
935 /// get state of connection.
936 TAppState getState() {
937 return appState_;
938 }
David Reiss105961d2010-10-06 17:10:17 +0000939
940 /// return the TSocket transport wrapping this network connection
941 boost::shared_ptr<TSocket> getTSocket() const {
942 return tSocket_;
943 }
944
945 /// return the server event handler if any
946 boost::shared_ptr<TServerEventHandler> getServerEventHandler() {
947 return serverEventHandler_;
948 }
949
950 /// return the Thrift connection context if any
951 void* getConnectionContext() {
952 return connectionContext_;
953 }
954
Mark Slee2f6404d2006-10-10 01:37:40 +0000955};
956
T Jake Lucianib5e62212009-01-31 22:36:20 +0000957}}} // apache::thrift::server
Mark Slee2f6404d2006-10-10 01:37:40 +0000958
959#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_