blob: eed34697839406eece2110139ad6be0d69512ac3 [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
Konrad Grochowski74260aa2014-11-13 15:33:38 +010029namespace apache {
30namespace thrift {
31namespace test {
Roger Meier2be7f242012-05-10 09:01:45 +000032
33/**
34 * A helper class to tell ServerThread how to create the server
35 */
36class ServerState {
Konrad Grochowski74260aa2014-11-13 15:33:38 +010037public:
Roger Meier2be7f242012-05-10 09:01:45 +000038 virtual ~ServerState() {}
39
40 /**
41 * Create a server to listen on the specified port.
42 *
43 * If the server returned fails to bind to the specified port when serve() is
44 * called on it, createServer() may be called again on a different port.
45 */
46 virtual boost::shared_ptr<server::TServer> createServer(uint16_t port) = 0;
47
48 /**
49 * Get the TServerEventHandler to set on the server.
50 *
51 * This is only called after the server successfully binds and is about to
52 * start serving traffic. It is invoked from the server thread, rather than
53 * the main thread.
54 */
Konrad Grochowski74260aa2014-11-13 15:33:38 +010055 virtual boost::shared_ptr<server::TServerEventHandler> getServerEventHandler() {
Roger Meier2be7f242012-05-10 09:01:45 +000056 return boost::shared_ptr<server::TServerEventHandler>();
57 }
58
59 /**
60 * This method is called in the server thread after server binding succeeds.
61 *
62 * Subclasses may override this method if they wish to record the final
63 * port that was used for the server.
64 */
Konrad Grochowski74260aa2014-11-13 15:33:38 +010065 virtual void bindSuccessful(uint16_t /*port*/) {}
Roger Meier2be7f242012-05-10 09:01:45 +000066};
67
68/**
69 * ServerThread starts a thrift server running in a separate thread.
70 */
71class ServerThread {
Konrad Grochowski74260aa2014-11-13 15:33:38 +010072public:
73 ServerThread(const boost::shared_ptr<ServerState>& state, bool autoStart)
74 : helper_(new Helper(this)),
Roger Meier2be7f242012-05-10 09:01:45 +000075 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
Konrad Grochowski74260aa2014-11-13 15:33:38 +010088 uint16_t getPort() const { return port_; }
Roger Meier2be7f242012-05-10 09:01:45 +000089
90 ~ServerThread() {
91 if (running_) {
92 try {
93 stop();
94 } catch (...) {
95 GlobalOutput.printf("error shutting down server");
96 }
97 }
98 }
99
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100100protected:
Roger Meier2be7f242012-05-10 09:01:45 +0000101 // Annoying. thrift forces us to use shared_ptr, so we have to use
102 // a helper class that we can allocate on the heap and give to thrift.
103 // It would be simpler if we could just make Runnable and TServerEventHandler
104 // private base classes of ServerThread.
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100105 class Helper : public concurrency::Runnable, public server::TServerEventHandler {
106 public:
107 Helper(ServerThread* serverThread) : serverThread_(serverThread) {}
Roger Meier2be7f242012-05-10 09:01:45 +0000108
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100109 void run() { serverThread_->run(); }
Roger Meier2be7f242012-05-10 09:01:45 +0000110
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100111 void preServe() { serverThread_->preServe(); }
Roger Meier2be7f242012-05-10 09:01:45 +0000112
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100113 private:
Roger Meier2be7f242012-05-10 09:01:45 +0000114 ServerThread* serverThread_;
115 };
116
117 void run();
118 void preServe();
119
120 boost::shared_ptr<Helper> helper_;
121
122 uint16_t port_;
123 bool running_;
124 bool serving_;
125 bool error_;
126 concurrency::Monitor serverMonitor_;
127
128 boost::shared_ptr<ServerState> serverState_;
129 boost::shared_ptr<server::TServer> server_;
130 boost::shared_ptr<concurrency::Thread> thread_;
131};
Konrad Grochowski74260aa2014-11-13 15:33:38 +0100132}
133}
134} // apache::thrift::test
Roger Meier2be7f242012-05-10 09:01:45 +0000135
136#endif // _THRIFT_TEST_SERVERTHREAD_H_