/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_SERVERTHREAD_H_ #define _THRIFT_TEST_SERVERTHREAD_H_ 1 #include #include #include #include #include "EventLog.h" namespace apache { namespace thrift { namespace test { /** * A helper class to tell ServerThread how to create the server */ class ServerState { public: virtual ~ServerState() = default; /** * Create a server to listen on the specified port. * * If the server returned fails to bind to the specified port when serve() is * called on it, createServer() may be called again on a different port. */ virtual std::shared_ptr createServer(uint16_t port) = 0; /** * Get the TServerEventHandler to set on the server. * * This is only called after the server successfully binds and is about to * start serving traffic. It is invoked from the server thread, rather than * the main thread. */ virtual std::shared_ptr getServerEventHandler() { return std::shared_ptr(); } /** * This method is called in the server thread after server binding succeeds. * * Subclasses may override this method if they wish to record the final * port that was used for the server. */ virtual void bindSuccessful(uint16_t /*port*/) {} }; /** * ServerThread starts a thrift server running in a separate thread. */ class ServerThread { public: ServerThread(const std::shared_ptr& state, bool autoStart) : port_(0), running_(false), serving_(false), error_(false), serverState_(state) { if (autoStart) { start(); } } void start(); void stop(); uint16_t getPort() const { return port_; } ~ServerThread() { if (running_) { try { stop(); } catch (...) { GlobalOutput.printf("error shutting down server"); } } } protected: // Annoying. thrift forces us to use shared_ptr, so we have to use // a helper class that we can allocate on the heap and give to thrift. // It would be simpler if we could just make Runnable and TServerEventHandler // private base classes of ServerThread. class Helper : public concurrency::Runnable, public server::TServerEventHandler { public: Helper(ServerThread* serverThread) : serverThread_(serverThread) {} void run() override { serverThread_->run(); } void preServe() override { serverThread_->preServe(); } private: ServerThread* serverThread_; }; void run(); void preServe(); std::shared_ptr helper_; uint16_t port_; bool running_; bool serving_; bool error_; concurrency::Monitor serverMonitor_; std::shared_ptr serverState_; std::shared_ptr server_; std::shared_ptr thread_; }; } } } // apache::thrift::test #endif // _THRIFT_TEST_SERVERTHREAD_H_