diff --git a/services/backup/docker-server/contents/server/CMakeLists.txt b/services/backup/docker-server/contents/server/CMakeLists.txt index 6002419cf..65f9008f0 100644 --- a/services/backup/docker-server/contents/server/CMakeLists.txt +++ b/services/backup/docker-server/contents/server/CMakeLists.txt @@ -1,124 +1,125 @@ PROJECT(backup C CXX) cmake_minimum_required(VERSION 3.16) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) set(CMAKE_CXX_STANDARD 17) set(BUILD_TESTING OFF CACHE BOOL "Turn off tests" FORCE) set(WITH_GTEST "Use Google Test" OFF) # FIND LIBS include(./cmake-components/grpc.cmake) include(./cmake-components/folly.cmake) add_subdirectory(./lib/glog) find_package(AWSSDK REQUIRED COMPONENTS core dynamodb) find_package(Boost 1.40 COMPONENTS program_options REQUIRED) # FIND FILES file(GLOB DOUBLE_CONVERSION_SOURCES "./lib/double-conversion/double-conversion/*.cc") if ($ENV{COMM_TEST_SERVICES} MATCHES 1) add_compile_definitions(COMM_TEST_SERVICES) endif() file(GLOB GENERATED_CODE "./_generated/*.cc") set(DEV_SOURCE_CODE "") set(DEV_HEADERS_PATH "") if ($ENV{COMM_SERVICES_DEV_MODE} MATCHES 1) add_compile_definitions(COMM_SERVICES_DEV_MODE) file(GLOB DEV_SOURCE_CODE "./dev/*.cpp" "./src/*.dev.cpp") set(DEV_HEADERS_PATH "./dev") endif() file(GLOB SOURCE_CODE "./src/*.cpp" "./src/**/*.cpp") list(FILTER SOURCE_CODE EXCLUDE REGEX ".*.dev.cpp$") foreach (ITEM ${DEV_SOURCE_CODE}) string(REPLACE "/" ";" SPLIT_ITEM ${ITEM}) list(GET SPLIT_ITEM -1 FILE_FULL_NAME) string(REPLACE ".dev.cpp" ".cpp" FILE_NAME ${FILE_FULL_NAME}) list(FILTER SOURCE_CODE EXCLUDE REGEX ".*${FILE_NAME}$") list(APPEND SOURCE_CODE "${ITEM}") endforeach() include_directories( ./src ./src/DatabaseEntities + ./src/Reactors ./_generated ${FOLLY_INCLUDES} ./lib/double-conversion ${Boost_INCLUDE_DIR} ${DEV_HEADERS_PATH} ) # SERVER add_executable( backup ${GENERATED_CODE} ${DOUBLE_CONVERSION_SOURCES} ${FOLLY_SOURCES} ${SOURCE_CODE} ) set( LIBS ${GRPC_LIBS} ${AWSSDK_LINK_LIBRARIES} ${Boost_LIBRARIES} glog::glog ) target_link_libraries( backup ${LIBS} ) install( TARGETS backup RUNTIME DESTINATION bin/ ) # TEST if ($ENV{COMM_TEST_SERVICES} MATCHES 1) file(GLOB TEST_CODE "./test/*.cpp") list(FILTER SOURCE_CODE EXCLUDE REGEX "./src/server.cpp") enable_testing() find_package(GTest REQUIRED) include_directories( ${GTEST_INCLUDE_DIR} ./test ) add_executable( runTests ${GENERATED_CODE} ${DOUBLE_CONVERSION_SOURCES} ${FOLLY_SOURCES} ${SOURCE_CODE} ${TEST_CODE} ) target_link_libraries( runTests ${LIBS} gtest gtest_main ) add_test( NAME runTests COMMAND runTests ) endif() diff --git a/services/backup/docker-server/contents/server/src/Reactors/BidiReactorBase.h b/services/backup/docker-server/contents/server/src/Reactors/BidiReactorBase.h new file mode 100644 index 000000000..082d2d749 --- /dev/null +++ b/services/backup/docker-server/contents/server/src/Reactors/BidiReactorBase.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + +namespace comm { +namespace network { + +template +class BidiReactorBase : public grpc::ServerBidiReactor { + Request request; + Response response; + +public: + BidiReactorBase(); + + void OnDone() override; + void OnReadDone(bool ok) override; + void OnWriteDone(bool ok) override; + + virtual std::unique_ptr + handleRequest(Request request, Response *response) = 0; +}; + +template +BidiReactorBase::BidiReactorBase() { + this->StartRead(&this->request); +} + +template +void BidiReactorBase::OnDone() { + delete this; +} + +template +void BidiReactorBase::OnReadDone(bool ok) { + if (!ok) { + this->Finish( + grpc::Status(grpc::StatusCode::INTERNAL, "OnReadDone: reading error")); + return; + } + this->response = Response(); + try { + std::unique_ptr status = + this->handleRequest(this->request, &this->response); + if (status != nullptr) { + this->Finish(*status); + return; + } + this->StartWrite(&this->response); + } catch (std::runtime_error &e) { + this->Finish(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); + } +} + +template +void BidiReactorBase::OnWriteDone(bool ok) { + if (!ok) { + std::cout << "Server write failed" << std::endl; + return; + } + this->StartRead(&this->request); +} + +} // namespace network +} // namespace comm diff --git a/services/backup/docker-server/contents/server/src/Reactors/ReadReactorBase.h b/services/backup/docker-server/contents/server/src/Reactors/ReadReactorBase.h new file mode 100644 index 000000000..4b8776d01 --- /dev/null +++ b/services/backup/docker-server/contents/server/src/Reactors/ReadReactorBase.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include +#include + +namespace comm { +namespace network { + +template +class ReadReactorBase : public grpc::ServerReadReactor { + Request request; + +protected: + Response *response; + +public: + ReadReactorBase(Response *response); + + void OnDone() override; + void OnReadDone(bool ok) override; + + virtual std::unique_ptr readRequest(Request request) = 0; +}; + +template +ReadReactorBase::ReadReactorBase(Response *response) + : response(response) { + this->StartRead(&this->request); +} + +template +void ReadReactorBase::OnDone() { + delete this; +} + +template +void ReadReactorBase::OnReadDone(bool ok) { + if (!ok) { + this->Finish( + grpc::Status(grpc::StatusCode::INTERNAL, "OnReadDone: reading error")); + return; + } + try { + std::unique_ptr status = this->readRequest(this->request); + if (status != nullptr) { + this->Finish(*status); + return; + } + } catch (std::runtime_error &e) { + this->Finish(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); + return; + } + this->StartRead(&this->request); +} + +} // namespace network +} // namespace comm diff --git a/services/backup/docker-server/contents/server/src/Reactors/WriteReactorBase.h b/services/backup/docker-server/contents/server/src/Reactors/WriteReactorBase.h new file mode 100644 index 000000000..d18fd5629 --- /dev/null +++ b/services/backup/docker-server/contents/server/src/Reactors/WriteReactorBase.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include + +namespace comm { +namespace network { + +template +class WriteReactorBase : public grpc::ServerWriteReactor { + Response response; + +protected: + // this is a const ref since it's not meant to be modified + const Request &request; + +public: + WriteReactorBase(const Request *request); + + virtual void NextWrite(); + void OnDone() override; + void OnWriteDone(bool ok) override; + + virtual std::unique_ptr writeResponse(Response *response) = 0; +}; + +template +WriteReactorBase::WriteReactorBase(const Request *request) + : request(*request) { + // we cannot call this->NextWrite() here because it's going to call it on + // the base class, not derived leading to the runtime error of calling + // a pure virtual function + // NextWrite has to be exposed as a public function and called explicitly + // to initialize writing +} + +template +void WriteReactorBase::NextWrite() { + this->response = Response(); + std::unique_ptr status = this->writeResponse(&this->response); + if (status != nullptr) { + this->Finish(*status); + return; + } + this->StartWrite(&this->response); +} + +template +void WriteReactorBase::OnDone() { + delete this; +} + +template +void WriteReactorBase::OnWriteDone(bool ok) { + if (!ok) { + this->Finish(grpc::Status(grpc::StatusCode::INTERNAL, "writing error")); + return; + } + try { + this->NextWrite(); + } catch (std::runtime_error &e) { + this->Finish(grpc::Status(grpc::StatusCode::INTERNAL, e.what())); + } +} + +} // namespace network +} // namespace comm