Skip to content
Snippets Groups Projects
Verified Commit 6e477c6d authored by Daniel Lyubomirov's avatar Daniel Lyubomirov
Browse files

[OPTIMIZATION] Use pimpl in the gRPC server

parent 3597f9e1
No related branches found
No related tags found
1 merge request!94gRPC and vereign services code generation
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,modernize-*,readability-*,-readability-container-size-empty'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: none
CheckOptions:
- key: cert-dcl16-c.NewSuffixes
value: 'L;LL;LU;LLU'
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
value: '0'
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
value: '1'
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
value: '1'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '1'
- key: google-readability-function-size.StatementThreshold
value: '800'
- key: google-readability-namespace-comments.ShortNamespaceLines
value: '10'
- key: google-readability-namespace-comments.SpacesBeforeComments
value: '2'
- key: modernize-loop-convert.MaxCopySize
value: '16'
- key: modernize-loop-convert.MinConfidence
value: reasonable
- key: modernize-loop-convert.NamingStyle
value: CamelCase
- key: modernize-pass-by-value.IncludeStyle
value: llvm
- key: modernize-replace-auto-ptr.IncludeStyle
value: llvm
- key: modernize-use-nullptr.NullMacros
value: 'NULL'
......@@ -6,6 +6,11 @@ endif()
project (vereign)
# Options
option(VEREIGN_USE_LLD "Use the lld linker" OFF)
option(VEREIGN_USE_PRECOMPILED_HEADERS "Use precompiled headers" OFF)
option(VEREIGN_USE_TIME_TRACE OFF)
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0.24215.1")
message(FATAL_ERROR "Microsoft Visual C++ version MSVC 19.0.24215.1 required")
......@@ -46,6 +51,9 @@ endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -Wall -Wextra -pedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -pedantic")
if (VEREIGN_USE_LLD)
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")
endif()
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
......@@ -141,13 +149,14 @@ message(STATUS "summary of build options:
Install prefix: ${CMAKE_INSTALL_PREFIX}
Target system: ${CMAKE_SYSTEM_NAME}
Compiler:
Build type: ${CMAKE_BUILD_TYPE}
C compiler: ${CMAKE_C_COMPILER}
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
C++ compiler: ${CMAKE_CXX_COMPILER}
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
WARNCFLAGS: ${WARNCFLAGS}
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
Build type: ${CMAKE_BUILD_TYPE}
C compiler: ${CMAKE_C_COMPILER}
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
C++ compiler: ${CMAKE_CXX_COMPILER}
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS_${_build_type}} ${CMAKE_EXE_LINKER_FLAGS}
WARNCFLAGS: ${WARNCFLAGS}
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
Libs:
fmt: ${fmt_FOUND} [${fmt_VERSION}] (DIR='${fmt_DIR}')
OpenSSL: ${OpenSSL_FOUND} [${OPENSSL_VERSION}] (LIBS='${OPENSSL_LIBRARIES}')
......@@ -155,4 +164,8 @@ message(STATUS "summary of build options:
Boost ${Boost_FOUND} [${Boost_VERSION_STRING}] (DIR='${Boost_DIR}')
Boost libs ${Boost_LIBRARIES}
gRPC ${gRPC_FOUND} [${gRPC_VERSION}] (LIBS='${_grpc_libs}')
Options:
VEREIGN_USE_LLD ${VEREIGN_USE_LLD}
VEREIGN_USE_PRECOMPILED_HEADERS ${VEREIGN_USE_PRECOMPILED_HEADERS}
VEREIGN_USE_TIME_TRACE ${VEREIGN_USE_TIME_TRACE}
")
......@@ -35,6 +35,8 @@ target_link_libraries(
OpenSSL::Crypto
$<$<CXX_COMPILER_ID:MSVC>:CRYPT32.LIB>
)
file(GLOB PROTO_HEADERS ${CMAKE_SOURCE_DIR}/proto/cpp/vereign/client_library/*pb.h)
target_precompile_headers(vereignproto PUBLIC ${PROTO_HEADERS})
set(VEREIGNLIB_SRC
vereign/restapi/detail/http_reader.cc
......@@ -66,12 +68,18 @@ set(csandbox_sources
add_executable(csandbox ${csandbox_sources})
target_link_libraries(csandbox
fmt::fmt
Boost::regex
Threads::Threads
OpenSSL::SSL
$<$<CXX_COMPILER_ID:MSVC>:CRYPT32.LIB>
vereignlib
# fmt::fmt
# Boost::regex
# Threads::Threads
# OpenSSL::SSL
# $<$<CXX_COMPILER_ID:MSVC>:CRYPT32.LIB>
)
if (VEREIGN_USE_TIME_TRACE AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(csandbox
PRIVATE "-ftime-trace"
)
endif()
# Generates the gRPC and Vereign services source code.
add_custom_target(
......
#include <functional>
#include <memory>
#include <thread>
#include <future>
#include <iostream>
#include <type_traits>
#include <vector>
#include <boost/bind.hpp>
#include <boost/optional.hpp>
namespace experiment {
/**
* Array with c++11 move semantics for research purposes.
*
* @note Do not use this in real code.
*/
class Array {
public:
Array() : arr_{nullptr}, size_{0} {
std::cout << "default construct " << to_s() << "\n";
}
Array(std::initializer_list<int> l)
: arr_(new int[l.size()]{})
, size_(l.size()) {
std::copy(l.begin(), l.end(), arr_);
std::cout << "create list " << to_s() << "\n";
}
Array(const std::vector<int>& src) {
arr_ = new int[src.size()]{};
size_ = src.size();
std::copy(src.begin(), src.end(), arr_);
std::cout << "create " << to_s() << "\n";
}
Array(const Array& other) : arr_(new int[other.size_]{}), size_{other.size_} {
std::copy(other.arr_, other.arr_ + other.size_, arr_);
std::cout << "copy construct " << to_s() << "\n";
}
Array& operator=(const Array& other) {
Array tmp{other};
swap(*this, tmp);
std::cout << "copy assign " << to_s() << "\n";
return *this;
}
Array(Array&& other) noexcept : arr_{other.arr_}, size_(other.size_) {
other.arr_ = nullptr;
other.size_ = 0;
std::cout << "move construct " << to_s() << "\n";
}
Array& operator=(Array&& other) noexcept {
swap(*this, other);
std::cout << "move assign " << to_s() << "\n";
return *this;
}
~Array() {
std::cout << "destroy " << to_s() << "\n";
if (arr_) {
delete [] arr_;
}
}
void reset() {
if (arr_) {
delete [] arr_;
arr_ = nullptr;
}
size_ = 0;
}
std::string to_s() const {
std::string ret = std::to_string(intptr_t(this)) + " ";
if (!arr_) {
return ret;
}
for (int i = 0; i < size_; i++) {
ret += std::to_string(arr_[i]) + " ";
}
return ret;
}
friend void swap(Array& lhs, Array& rhs) noexcept;
private:
int* arr_;
int size_;
};
void swap(Array& lhs, Array& rhs) noexcept {
using std::swap;
swap(lhs.arr_, rhs.arr_);
swap(lhs.size_, rhs.size_);
}
}
using namespace experiment;
int main(int , char* []) {
auto main(int argc, char* argv[]) -> int {
}
#ifndef __VEREIGN_CORE_SCOPE_GUARD_HH
#define __VEREIGN_CORE_SCOPE_GUARD_HH
#include <type_traits>
#include <utility>
namespace vereign {
namespace core {
......@@ -23,11 +26,11 @@ private:
};
template<typename Func>
ScopeGuard<Func> MakeScopeGuard(Func&& func) {
auto MakeScopeGuard(Func&& func) -> ScopeGuard<Func> {
return ScopeGuard<Func>{std::move(func)};
}
}
}
#endif
\ No newline at end of file
#endif
#include "vereign/grpc/gen/conversation_api.hh"
#include "vereign/service/gen/conversation_service.hh"
#include <vereign/grpc/server.hh>
#include <vereign/grpc/gen/passport_api.hh>
#include <vereign/service/gen/passport_service.hh>
#include <vereign/restapi/client.hh>
#include <vereign/restapi/client_session.hh>
#include <vereign/service/gen/gen.hh>
#include <vereign/service/passport_service.hh>
#include <vereign/grpc/gen/gen.hh>
#include <vereign/grpc/service_registry.hh>
#include <vereign/service/passport_service.hh>
#include <vereign/grpc/passport_api.hh>
#include <grpcpp/server.h>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include <grpcpp/security/server_credentials.h>
......@@ -22,14 +22,17 @@
namespace vereign {
namespace grpc {
Server::Server(
const std::string& listenAddress,
const std::string& vereignHost,
const std::string& vereignPort,
// FIXME: the public key must come from a storage
const std::string& publicKey
)
: work_guard_{asio::make_work_guard(ioc_)},
namespace asio = boost::asio;
class Server::Impl {
public:
Impl(
const std::string& listenAddress,
const std::string& vereignHost,
const std::string& vereignPort,
// FIXME: the public key must come from a storage
const std::string& publicKey
) : work_guard_{asio::make_work_guard(ioc_)},
ssl_context_{asio::ssl::context::tlsv12_client},
client_{std::make_unique<restapi::Client>(
ioc_, ssl_context_, vereignHost, vereignPort
......@@ -37,37 +40,79 @@ Server::Server(
client_session_{std::make_unique<restapi::ClientSession>(
*client_, publicKey
)}
{
// FIXME: Verify the remote server's certificate
// ssl_context.set_verify_mode(ssl::verify_peer);
{
// FIXME: Verify the remote server's certificate
// ssl_context.set_verify_mode(ssl::verify_peer);
::grpc::ServerBuilder builder;
builder.AddListeningPort(
listenAddress,
::grpc::InsecureServerCredentials(),
&selected_port_
);
// register manually written services
services_registry_.RegisterIfNotExist<PassportAPI<service::PassportService>>(*client_session_);
// register all generated services
grpc::gen::RegisterAll(*client_session_, services_registry_);
::grpc::ServerBuilder builder;
builder.AddListeningPort(
listenAddress,
::grpc::InsecureServerCredentials(),
&selected_port_
);
services_registry_.RegisterIntoBuilder(builder);
// register manually written services
services_registry_.RegisterIfNotExist<PassportAPI<service::PassportService>>(*client_session_);
server_ = builder.BuildAndStart();
if (server_ == nullptr) {
throw std::runtime_error("server start failed");
}
// register all generated services
grpc::gen::RegisterAll(*client_session_, services_registry_);
server_thread_ = std::thread([this]() {
server_->Wait();
});
services_registry_.RegisterIntoBuilder(builder);
service_thread_ = std::thread([this]() {
ioc_.run();
});
}
void Shutdown() {
client_session_->Close();
server_->Shutdown();
if (server_thread_.joinable()) {
server_thread_.join();
}
work_guard_.reset();
if (service_thread_.joinable()) {
service_thread_.join();
}
}
server_ = builder.BuildAndStart();
if (server_ == nullptr) {
throw std::runtime_error("server start failed");
auto SelectedPort() const -> int {
return selected_port_;
}
server_thread_ = std::thread([this]() {
server_->Wait();
});
private:
int selected_port_;
asio::io_context ioc_;
asio::executor_work_guard<asio::io_context::executor_type> work_guard_;
asio::ssl::context ssl_context_;
std::unique_ptr<vereign::restapi::Client> client_;
std::unique_ptr<vereign::restapi::ClientSession> client_session_;
ServiceRegistry services_registry_;
std::unique_ptr<::grpc::Server> server_;
std::thread server_thread_;
std::thread service_thread_;
};
service_thread_ = std::thread([this]() {
ioc_.run();
});
Server::Server(
const std::string& listenAddress,
const std::string& vereignHost,
const std::string& vereignPort,
// FIXME: the public key must come from a storage
const std::string& publicKey
)
: impl_{std::make_unique<Impl>(listenAddress, vereignHost, vereignPort, publicKey)}
{
}
Server::~Server() {
......@@ -75,21 +120,11 @@ Server::~Server() {
}
void Server::Shutdown() {
client_session_->Close();
server_->Shutdown();
if (server_thread_.joinable()) {
server_thread_.join();
}
work_guard_.reset();
if (service_thread_.joinable()) {
service_thread_.join();
}
impl_->Shutdown();
}
int Server::SelectedPort() const {
return selected_port_;
auto Server::SelectedPort() const -> int {
return impl_->SelectedPort();
}
} // namespace grpc
......
#ifndef __VEREIGN_GRPC_SERVER_API_HH
#define __VEREIGN_GRPC_SERVER_API_HH
#include <thread>
#include <grpcpp/server.h>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <vereign/grpc/service_registry.hh>
#include <string>
#include <memory>
namespace vereign {
namespace restapi {
class Client;
class ClientSession;
}
namespace grpc {
namespace asio = boost::asio;
/**
* Server is a grpc server that provides the Vereign services.
*
......@@ -51,7 +39,7 @@ public:
// Disable copying
Server(const Server&) = delete;
Server& operator=(const Server&) = delete;
auto operator=(const Server&) -> Server& = delete;
/**
* Shutdown the server.
......@@ -68,19 +56,11 @@ public:
* Then this method will return the port that the OS assigned to the gRPC
* socket.
*/
int SelectedPort() const;
auto SelectedPort() const -> int;
private:
int selected_port_;
asio::io_context ioc_;
asio::executor_work_guard<asio::io_context::executor_type> work_guard_;
asio::ssl::context ssl_context_;
std::unique_ptr<vereign::restapi::Client> client_;
std::unique_ptr<vereign::restapi::ClientSession> client_session_;
ServiceRegistry services_registry_;
std::unique_ptr<::grpc::Server> server_;
std::thread server_thread_;
std::thread service_thread_;
class Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace grpc
......
......@@ -23,6 +23,12 @@ target_link_libraries(tests
Threads::Threads
)
if (VEREIGN_USE_TIME_TRACE AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(tests
PRIVATE "-ftime-trace"
)
endif()
#add_custom_command(
# TARGET protobuf_tests
# COMMENT "Run protobuf tests"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment