diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 80c7c41982a..9713333cf5b 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -365,9 +365,11 @@ class ServerCompletionQueue : public CompletionQueue { public: bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; } + protected: + /// Default constructor + ServerCompletionQueue() {} + private: - grpc_cq_polling_type polling_type_; - friend class ServerBuilder; /// \param is_frequently_polled Informs the GRPC library about whether the /// server completion queue would be actively polled (by calling Next() or /// AsyncNext()). By default all server completion queues are assumed to be @@ -376,6 +378,9 @@ class ServerCompletionQueue : public CompletionQueue { : CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, polling_type}), polling_type_(polling_type) {} + + grpc_cq_polling_type polling_type_; + friend class ServerBuilder; }; } // namespace grpc diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f99a6c26b4c..e88e7966dc5 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -49,7 +49,7 @@ class ServerInitializer; /// /// Use a \a grpc::ServerBuilder to create, configure, and start /// \a Server instances. -class Server final : public ServerInterface, private GrpcLibraryCodegen { +class Server : public ServerInterface, private GrpcLibraryCodegen { public: ~Server(); @@ -87,7 +87,8 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// application and is shared among all \a Server objects. static void SetGlobalCallbacks(GlobalCallbacks* callbacks); - // Returns a \em raw pointer to the underlying \a grpc_server instance. + /// Returns a \em raw pointer to the underlying \a grpc_server instance. + /// EXPERIMENTAL: for internal/test use only grpc_server* c_server(); /// Returns the health check service. @@ -98,24 +99,26 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// Establish a channel for in-process communication std::shared_ptr InProcessChannel(const ChannelArguments& args); - private: - friend class AsyncGenericService; - friend class ServerBuilder; - friend class ServerInitializer; - - class SyncRequest; - class AsyncRequest; - class ShutdownRequest; - - /// SyncRequestThreadManager is an implementation of ThreadManager. This class - /// is responsible for polling for incoming RPCs and calling the RPC handlers. - /// This is only used in case of a Sync server (i.e a server exposing a sync - /// interface) - class SyncRequestThreadManager; + protected: + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the Server instance. + bool RegisterService(const grpc::string* host, Service* service) override; - class UnimplementedAsyncRequestContext; - class UnimplementedAsyncRequest; - class UnimplementedAsyncResponse; + /// Try binding the server to the given \a addr endpoint + /// (port, and optionally including IP address to bind to). + /// + /// It can be invoked multiple times. Should be used before + /// starting the server. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// + /// \return bound port number on success, 0 on failure. + /// + /// \warning It is an error to call this method on an already started server. + int AddListeningPort(const grpc::string& addr, + ServerCredentials* creds) override; /// Server constructors. To be used by \a ServerBuilder only. /// @@ -143,30 +146,6 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { sync_server_cqs, int min_pollers, int max_pollers, int sync_cq_timeout_msec); - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the Server instance. - bool RegisterService(const grpc::string* host, Service* service) override; - - /// Register a generic service. This call does not take ownership of the - /// service. The service must exist for the lifetime of the Server instance. - void RegisterAsyncGenericService(AsyncGenericService* service) override; - - /// Try binding the server to the given \a addr endpoint - /// (port, and optionally including IP address to bind to). - /// - /// It can be invoked multiple times. Should be used before - /// starting the server. - /// - /// \param addr The address to try to bind to the server (eg, localhost:1234, - /// 192.168.1.1:31416, [::1]:27182, etc.). - /// \param creds The credentials associated with the server. - /// - /// \return bound port number on success, 0 on failure. - /// - /// \warning It is an error to call this method on an already started server. - int AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) override; - /// Start the server. /// /// \param cqs Completion queues for handling asynchronous services. The @@ -175,6 +154,31 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// \param num_cqs How many completion queues does \a cqs hold. void Start(ServerCompletionQueue** cqs, size_t num_cqs) override; + grpc_server* server() override { return server_; }; + + private: + friend class AsyncGenericService; + friend class ServerBuilder; + friend class ServerInitializer; + + class SyncRequest; + class AsyncRequest; + class ShutdownRequest; + + /// SyncRequestThreadManager is an implementation of ThreadManager. This class + /// is responsible for polling for incoming RPCs and calling the RPC handlers. + /// This is only used in case of a Sync server (i.e a server exposing a sync + /// interface) + class SyncRequestThreadManager; + + class UnimplementedAsyncRequestContext; + class UnimplementedAsyncRequest; + class UnimplementedAsyncResponse; + + /// Register a generic service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. + void RegisterAsyncGenericService(AsyncGenericService* service) override; + void PerformOpsOnCall(internal::CallOpSetInterface* ops, internal::Call* call) override; @@ -184,8 +188,6 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { return max_receive_message_size_; }; - grpc_server* server() override { return server_; }; - ServerInitializer* initializer(); const int max_receive_message_size_; @@ -200,7 +202,7 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen { /// the \a sync_server_cqs) std::vector> sync_req_mgrs_; - // Sever status + // Server status std::mutex mu_; bool started_; bool shutdown_; diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index c35a6cf98a9..4c8dcf49167 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -52,7 +52,7 @@ class ServerBuilderPluginTest; class ServerBuilder { public: ServerBuilder(); - ~ServerBuilder(); + virtual ~ServerBuilder(); ////////////////////////////////////////////////////////////////////////////// // Primary API's @@ -65,7 +65,7 @@ class ServerBuilder { /// traffic (via AddListeningPort) /// 3. [for async api only] completion queues have been added via /// AddCompletionQueue - std::unique_ptr BuildAndStart(); + virtual std::unique_ptr BuildAndStart(); /// Register a service. This call does not take ownership of the service. /// The service must exist for the lifetime of the \a Server instance returned @@ -210,15 +210,48 @@ class ServerBuilder { /// doc/workarounds.md. ServerBuilder& EnableWorkaround(grpc_workaround_list id); - private: - friend class ::grpc::testing::ServerBuilderPluginTest; - + protected: + /// Experimental, to be deprecated struct Port { grpc::string addr; std::shared_ptr creds; int* selected_port; }; + /// Experimental, to be deprecated + typedef std::unique_ptr HostString; + struct NamedService { + explicit NamedService(Service* s) : service(s) {} + NamedService(const grpc::string& h, Service* s) + : host(new grpc::string(h)), service(s) {} + HostString host; + Service* service; + }; + + /// Experimental, to be deprecated + std::vector ports() { return ports_; } + + /// Experimental, to be deprecated + std::vector services() { + std::vector service_refs; + for (auto& ptr : services_) { + service_refs.push_back(ptr.get()); + } + return service_refs; + } + + /// Experimental, to be deprecated + std::vector options() { + std::vector option_refs; + for (auto& ptr : options_) { + option_refs.push_back(ptr.get()); + } + return option_refs; + } + + private: + friend class ::grpc::testing::ServerBuilderPluginTest; + struct SyncServerSettings { SyncServerSettings() : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {} @@ -238,15 +271,6 @@ class ServerBuilder { int cq_timeout_msec; }; - typedef std::unique_ptr HostString; - struct NamedService { - explicit NamedService(Service* s) : service(s) {} - NamedService(const grpc::string& h, Service* s) - : host(new grpc::string(h)), service(s) {} - HostString host; - Service* service; - }; - int max_receive_message_size_; int max_send_message_size_; std::vector> options_; diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 5638636e67d..760aaa4b4d2 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -382,11 +382,12 @@ Server::Server( global_callbacks_ = g_callbacks; global_callbacks_->UpdateArguments(args); - for (auto it = sync_server_cqs_->begin(); it != sync_server_cqs_->end(); - it++) { - sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( - this, (*it).get(), global_callbacks_, min_pollers, max_pollers, - sync_cq_timeout_msec)); + if (sync_server_cqs_ != nullptr) { + for (const auto& it : *sync_server_cqs_) { + sync_req_mgrs_.emplace_back(new SyncRequestThreadManager( + this, it.get(), global_callbacks_, min_pollers, max_pollers, + sync_cq_timeout_msec)); + } } grpc_channel_args channel_args; @@ -525,7 +526,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { // explicit one. if (health_check_service_ == nullptr && !health_check_service_disabled_ && DefaultHealthCheckServiceEnabled()) { - if (sync_server_cqs_->empty()) { + if (sync_server_cqs_ == nullptr || sync_server_cqs_->empty()) { gpr_log(GPR_INFO, "Default health check service disabled at async-only server."); } else {