diff --git a/cartographer_grpc/framework/completion_queue_thread.cc b/cartographer_grpc/framework/completion_queue_thread.cc new file mode 100644 index 0000000..85ba092 --- /dev/null +++ b/cartographer_grpc/framework/completion_queue_thread.cc @@ -0,0 +1,36 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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. + */ + +#include "cartographer_grpc/framework/completion_queue_thread.h" + +#include "cartographer/common/make_unique.h" +#include "glog/logging.h" + +namespace cartographer_grpc { +namespace framework { + +CompletionQueueThread::CompletionQueueThread( + std::unique_ptr<::grpc::ServerCompletionQueue> completion_queue) + : completion_queue_(std::move(completion_queue)) {} + +void CompletionQueueThread::Start(CompletionQueueRunner runner) { + CHECK(!worker_thread_); + worker_thread_ = cartographer::common::make_unique( + [this, runner]() { runner(this->completion_queue_.get()); }); +} + +} // namespace framework +} // namespace cartographer_grpc diff --git a/cartographer_grpc/framework/completion_queue_thread.h b/cartographer_grpc/framework/completion_queue_thread.h new file mode 100644 index 0000000..a014a70 --- /dev/null +++ b/cartographer_grpc/framework/completion_queue_thread.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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 CARTOGRAPHER_COMPLETION_QUEUE_THREAD_H +#define CARTOGRAPHER_COMPLETION_QUEUE_THREAD_H + +#include +#include +#include + +namespace cartographer_grpc { +namespace framework { + +class CompletionQueueThread { + public: + using CompletionQueueRunner = + std::function; + + explicit CompletionQueueThread( + std::unique_ptr<::grpc::ServerCompletionQueue> completion_queue); + + void Start(CompletionQueueRunner runner); + + private: + std::unique_ptr<::grpc::ServerCompletionQueue> completion_queue_; + std::unique_ptr worker_thread_; +}; + +} // namespace framework +} // namespace cartographer_grpc + +#endif // CARTOGRAPHER_COMPLETION_QUEUE_THREAD_H diff --git a/cartographer_grpc/framework/rpc_handler.h b/cartographer_grpc/framework/rpc_handler.h new file mode 100644 index 0000000..9965dbe --- /dev/null +++ b/cartographer_grpc/framework/rpc_handler.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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 CARTOGRAPHER_GRPC_FRAMEWORK_RPC_HANDLER_H +#define CARTOGRAPHER_GRPC_FRAMEWORK_RPC_HANDLER_H + +#include "google/protobuf/message.h" + +namespace cartographer_grpc { +namespace framework { + +class Rpc; +class RpcHandlerInterface { + public: + void SetRpc(Rpc* rpc); +}; + +using RpcHandlerFactory = + std::function(Rpc*)>; + +struct RpcHandlerInfo { + const google::protobuf::Descriptor* request_descriptor; + const google::protobuf::Descriptor* response_descriptor; + const RpcHandlerFactory rpc_handler_factory; +}; + +} // namespace framework +} // namespace cartographer_grpc + +#endif // CARTOGRAPHER_GRPC_FRAMEWORK_RPC_HANDLER_H diff --git a/cartographer_grpc/framework/server.cc b/cartographer_grpc/framework/server.cc new file mode 100644 index 0000000..83924d2 --- /dev/null +++ b/cartographer_grpc/framework/server.cc @@ -0,0 +1,65 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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. + */ + +#include "cartographer_grpc/framework/server.h" + +#include "cartographer/common/make_unique.h" +#include "glog/logging.h" + +namespace cartographer_grpc { +namespace framework { + +void Server::Builder::SetNumberOfThreads(const size_t number_of_threads) { + options_.number_of_threads = number_of_threads; +} + +void Server::Builder::SetServerAddress(const std::string& server_address) { + options_.server_address = server_address; +} + +std::unique_ptr Server::Builder::Build() { + std::unique_ptr server(new Server(options_)); + for (const auto& service_handlers : rpc_handlers_) { + server->AddService(service_handlers.first, service_handlers.second); + } + return server; +} + +Server::Server(const Options& options) : options_(options) { + server_builder_.AddListeningPort(options_.server_address, + grpc::InsecureServerCredentials()); + + // Set up completion queues threads. + for (size_t i = 0; i < options_.number_of_threads; ++i) { + completion_queue_threads_.emplace_back( + server_builder_.AddCompletionQueue()); + } +} + +void Server::AddService( + const std::string& service_name, + const std::map& rpc_handler_infos) { + // Instantiate and register service. + const auto result = + services_.emplace(std::piecewise_construct, std::make_tuple(service_name), + std::make_tuple(rpc_handler_infos)); + CHECK(result.second) << "A service named " << service_name + << " already exists."; + server_builder_.RegisterService(&result.first->second); +} + +} // namespace framework +} // namespace cartographer_grpc diff --git a/cartographer_grpc/framework/server.h b/cartographer_grpc/framework/server.h new file mode 100644 index 0000000..b81a862 --- /dev/null +++ b/cartographer_grpc/framework/server.h @@ -0,0 +1,104 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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 CARTOGRAPHER_GRPC_FRAMEWORK_SERVER_H +#define CARTOGRAPHER_GRPC_FRAMEWORK_SERVER_H + +#include +#include +#include +#include + +#include "cartographer/common/make_unique.h" +#include "cartographer_grpc/framework/completion_queue_thread.h" +#include "cartographer_grpc/framework/rpc_handler.h" +#include "cartographer_grpc/framework/service.h" +#include "grpc++/grpc++.h" + +namespace cartographer_grpc { +namespace framework { + +class Server { + private: + // All options that configure server behaviour such as number of threads, + // ports etc. + struct Options { + size_t number_of_threads = 4; + std::string server_address = "0.0.0.0:50051"; + }; + + public: + // This 'Builder' is the only way to construct a 'Server'. + class Builder { + public: + Builder() = default; + + std::unique_ptr Build(); + void SetNumberOfThreads(std::size_t number_of_threads); + void SetServerAddress(const std::string& server_address); + + template + void RegisterHandler(const std::string& method_name) { + rpc_handlers_[ServiceType::service_full_name()].emplace( + method_name, + RpcHandlerInfo{ + RpcHandlerType::RequestType::default_instance().GetDescriptor(), + RpcHandlerType::ResponseType::default_instance().GetDescriptor(), + [](Rpc* const rpc) { + std::unique_ptr rpc_handler = + cartographer::common::make_unique(); + rpc_handler->SetRpc(rpc); + return rpc_handler; + }}); + } + + private: + using ServiceInfo = std::map; + + Options options_; + std::map rpc_handlers_; + }; + friend class Builder; + + // Starts a server and waits for its termination. + void StartAndWait(); + + private: + Server(const Options& options); + Server(const Server&) = delete; + Server& operator=(const Server&) = delete; + + void AddService( + const std::string& service_name, + const std::map& rpc_handler_infos); + + Options options_; + + // gRPC objects needed to build a server. + ::grpc::ServerBuilder server_builder_; + std::unique_ptr<::grpc::Server> server_; + + // Threads processing the completion queues. + std::vector completion_queue_threads_; + + // Map of service names to services. + std::map services_; +}; + +} // namespace framework +} // namespace cartographer_grpc + +#endif // CARTOGRAPHER_GRPC_FRAMEWORK_SERVER_H diff --git a/cartographer_grpc/framework/service.cc b/cartographer_grpc/framework/service.cc new file mode 100644 index 0000000..973d555 --- /dev/null +++ b/cartographer_grpc/framework/service.cc @@ -0,0 +1,26 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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. + */ + +#include "cartographer_grpc/framework/server.h" + +namespace cartographer_grpc { +namespace framework { + +Service::Service(const std::map& rpc_handlers) + : rpc_handlers_(rpc_handlers) {} + +} // namespace framework +} // namespace cartographer_grpc diff --git a/cartographer_grpc/framework/service.h b/cartographer_grpc/framework/service.h new file mode 100644 index 0000000..fac13c1 --- /dev/null +++ b/cartographer_grpc/framework/service.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 The Cartographer Authors + * + * Licensed 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 CARTOGRAPHER_GRPC_FRAMEWORK_SERVICE_H +#define CARTOGRAPHER_GRPC_FRAMEWORK_SERVICE_H + +#include "cartographer_grpc/framework/rpc_handler.h" +#include "grpc++/impl/codegen/service_type.h" + +namespace cartographer_grpc { +namespace framework { + +// A 'Service' represents a generic service for gRPC asynchronous methods and is +// responsible for managing the lifetime of active RPCs issued against methods +// of the service and distributing incoming gRPC events to their respective +// 'Rpc' handler objects. +class Service : public ::grpc::Service { + public: + Service(const std::map& rpc_handlers); + + private: + std::map rpc_handlers_; +}; + +} // namespace framework +} // namespace cartographer_grpc + +#endif // CARTOGRAPHER_GRPC_FRAMEWORK_SERVICE_H