blob: f7fa0d5fb0c164c63a2d8a9964350f2c055dddb0 [file] [log] [blame]
Roger Meier2be7f242012-05-10 09:01:45 +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#ifndef _THRIFT_TEST_SERVERTHREAD_H_
20#define _THRIFT_TEST_SERVERTHREAD_H_ 1
21
Roger Meier2b1a5282012-05-11 10:12:39 +000022#include <thrift/TProcessor.h>
23#include <thrift/protocol/TProtocol.h>
24#include <thrift/server/TServer.h>
25#include <thrift/transport/TTransport.h>
Roger Meier2be7f242012-05-10 09:01:45 +000026
Roger Meier2b1a5282012-05-11 10:12:39 +000027#include "EventLog.h"
Roger Meier2be7f242012-05-10 09:01:45 +000028
29namespace apache { namespace thrift { namespace test {
30
31/**
32 * A helper class to tell ServerThread how to create the server
33 */
34class ServerState {
35 public:
36 virtual ~ServerState() {}
37
38 /**
39 * Create a server to listen on the specified port.
40 *
41 * If the server returned fails to bind to the specified port when serve() is
42 * called on it, createServer() may be called again on a different port.
43 */
44 virtual boost::shared_ptr<server::TServer> createServer(uint16_t port) = 0;
45
46 /**
47 * Get the TServerEventHandler to set on the server.
48 *
49 * This is only called after the server successfully binds and is about to
50 * start serving traffic. It is invoked from the server thread, rather than
51 * the main thread.
52 */
53 virtual boost::shared_ptr<server::TServerEventHandler>
54 getServerEventHandler() {
55 return boost::shared_ptr<server::TServerEventHandler>();
56 }
57
58 /**
59 * This method is called in the server thread after server binding succeeds.
60 *
61 * Subclasses may override this method if they wish to record the final
62 * port that was used for the server.
63 */
Konrad Grochowskib3f5ffc2014-11-06 19:32:59 +010064 virtual void bindSuccessful(uint16_t /*port*/) {
Roger Meier2be7f242012-05-10 09:01:45 +000065 }
66};
67
68/**
69 * ServerThread starts a thrift server running in a separate thread.
70 */
71class ServerThread {
72 public:
73 ServerThread(const boost::shared_ptr<ServerState>& state, bool autoStart) :
74 helper_(new Helper(this)),
75 port_(0),
76 running_(false),
77 serving_(false),
78 error_(false),
79 serverState_(state) {
80 if (autoStart) {
81 start();
82 }
83 }
84
85 void start();
86 void stop();
87
88 uint16_t getPort() const {
89 return port_;
90 }
91
92 ~ServerThread() {
93 if (running_) {
94 try {
95 stop();
96 } catch (...) {
97 GlobalOutput.printf("error shutting down server");
98 }
99 }
100 }
101
102 protected:
103 // Annoying. thrift forces us to use shared_ptr, so we have to use
104 // a helper class that we can allocate on the heap and give to thrift.
105 // It would be simpler if we could just make Runnable and TServerEventHandler
106 // private base classes of ServerThread.
107 class Helper : public concurrency::Runnable,
108 public server::TServerEventHandler {
109 public:
110 Helper(ServerThread* serverThread)
111 : serverThread_(serverThread) {}
112
113 void run() {
114 serverThread_->run();
115 }
116
117 void preServe() {
118 serverThread_->preServe();
119 }
120
121 private:
122 ServerThread* serverThread_;
123 };
124
125 void run();
126 void preServe();
127
128 boost::shared_ptr<Helper> helper_;
129
130 uint16_t port_;
131 bool running_;
132 bool serving_;
133 bool error_;
134 concurrency::Monitor serverMonitor_;
135
136 boost::shared_ptr<ServerState> serverState_;
137 boost::shared_ptr<server::TServer> server_;
138 boost::shared_ptr<concurrency::Thread> thread_;
139};
140
141}}} // apache::thrift::test
142
143#endif // _THRIFT_TEST_SERVERTHREAD_H_