From 60379439139cda6cfa287f3e103f19e9b3977ecd Mon Sep 17 00:00:00 2001 From: Timm Fitschen <t.fitschen@indiscale.com> Date: Wed, 7 Jul 2021 00:44:23 +0200 Subject: [PATCH] WIP: entity retrieve --- CMakeLists.txt | 256 ++++++++++++++++------------------- conanfile.py | 4 +- include/CMakeLists.txt | 10 +- include/caosdb/connection.h | 22 +-- include/caosdb/entity.h | 58 ++++++++ include/caosdb/transaction.h | 75 ++++++++++ proto | 2 +- src/CMakeLists.txt | 2 + src/caosdb/connection.cpp | 35 +++-- src/caosdb/entity.cpp | 38 ++++++ src/caosdb/transaction.cpp | 89 ++++++++++++ src/caosdbcli.cpp | 4 +- test/CMakeLists.txt | 7 +- test/test_transaction.cpp | 43 ++++++ 14 files changed, 475 insertions(+), 170 deletions(-) create mode 100644 include/caosdb/entity.h create mode 100644 include/caosdb/transaction.h create mode 100644 src/caosdb/entity.cpp create mode 100644 src/caosdb/transaction.cpp create mode 100644 test/test_transaction.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 090c823..33cda78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.14) -set(libcaosdb_VERSION 0.0.3) +set(libcaosdb_VERSION 0.0.4) project(libcaosdb VERSION ${libcaosdb_VERSION} @@ -57,9 +57,87 @@ add_subdirectory(src) add_subdirectory(include) add_subdirectory(doc) -add_library(caosdb STATIC ${libcaosdb_INCL} ${libcaosdb_SRC}) +#################################################################### +### CODE GENERATION (WITH GRPC) +#################################################################### + +# Protobuf/Grpc source files +set(PROTO_FILES + ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1alpha1/main.proto + ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1alpha1/main.proto +) + +set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto) + +# compiler binaries +set(_PROTOBUF_PROTOC "${CMAKE_BINARY_DIR}/build_tools/protoc") +set(_GRPC_CPP_PLUGIN_EXECUTABLE "${CMAKE_BINARY_DIR}/build_tools/grpc_cpp_plugin") + +# Generated sources +list(LENGTH PROTO_FILES len_proto_files) +math(EXPR len_proto_files "${len_proto_files} - 1") +foreach(i RANGE "${len_proto_files}") + list(GET PROTO_FILES ${i} next_proto_file) + + # strip away the prefix path and the ".proto" suffix + string(REPLACE + "${PROJECT_SOURCE_DIR}/proto/proto/caosdb/" + "" + next_proto_module + "${next_proto_file}") + string(REPLACE + ".proto" + "" + next_proto_module + "${next_proto_module}") + set(next_proto_src + "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.pb.cc") + set(next_proto_hdr + "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.pb.h") + set(next_grpc_src + "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.grpc.pb.cc") + set(next_grpc_hdr + "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.grpc.pb.h") + list(APPEND GRPC_GENERATED_HEADERS "${next_proto_hdr}" "${next_grpc_hdr}") + list(APPEND GRPC_GENERATED_SOURCES "${next_proto_src}" "${next_grpc_src}") + +endforeach() + +set(GRPC_GENERATED + ${GRPC_GENERATED_SOURCES} + ${GRPC_GENERATED_HEADERS}) +add_custom_command( + OUTPUT ${GRPC_GENERATED} + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}/include" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}/include" + -I "${PROTO_PATH}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + ${PROTO_FILES} + DEPENDS ${PROTO_FILES}) + + +if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") + add_library(caosdb_grpc STATIC ${GRPC_GENERATED}) + add_library(caosdb STATIC ${libcaosdb_INCL} ${libcaosdb_SRC}) + target_link_libraries(caosdb caosdb_grpc) + set(LIBCAOSDB caosdb caosdb_grpc) +else() + add_library(caosdb + STATIC ${libcaosdb_INCL} ${libcaosdb_SRC} ${GRPC_GENERATED}) + set(LIBCAOSDB caosdb) +endif() add_executable(caosdbcli src/caosdbcli.cpp) +target_link_libraries(caosdb + ${CONAN_LIBS} +) + +target_link_libraries(caosdbcli + ${LIBCAOSDB} + ${CONAN_LIBS} +) + ####################################################### ### LINTING with CLANG-TIDY and INCLUDE-WHAT-YOU-USE ####################################################### @@ -82,6 +160,13 @@ if(_LINTING) else() message(STATUS "include-what-you-use: ${iwyu}") set(_CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${iwyu} "-Xiwyu" "--cxx17ns") + + set_target_properties(caosdb PROPERTIES + CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}" + ) + set_target_properties(caosdbcli PROPERTIES + CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}" + ) endif() find_program(clang_tidy NAMES clang-tidy clang-tidy-11) @@ -96,17 +181,17 @@ if(_LINTING) "--warnings-as-errors=*") option(AUTO_FIX_LINTING "Append --fix option to clang-tidy" OFF) if(AUTO_FIX_LINTING) - set(APPEND AUTO_FIX_LINTING "--fix") + set(_CMAKE_CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};--fix") endif() + message(STATUS "Using clang-tidy with + '${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}'") + set_target_properties(caosdb PROPERTIES + CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}" + ) + set_target_properties(caosdbcli PROPERTIES + CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}" + ) endif() - set_target_properties(caosdb PROPERTIES - CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}" - CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}" - ) - set_target_properties(caosdbcli PROPERTIES - CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}" - CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}" - ) endif() @@ -119,73 +204,6 @@ if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") add_subdirectory(test) endif() -#################################################################### -### CODE GENERATION (WITH GRPC) -#################################################################### - -# Protobuf/Grpc source files -set(PROTO_FILES - ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1alpha1/main.proto -) - -set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto) - -# compiler binaries -set(_PROTOBUF_PROTOC "${CMAKE_BINARY_DIR}/build_tools/protoc") -set(_GRPC_CPP_PLUGIN_EXECUTABLE "${CMAKE_BINARY_DIR}/build_tools/grpc_cpp_plugin") - -# Generated sources -set(hw_hdrs_path "info/v1alpha1") -set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${hw_hdrs_path}/main.pb.cc") -set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${hw_hdrs_path}/main.pb.h") -set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${hw_hdrs_path}/main.grpc.pb.cc") -set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${hw_hdrs_path}/main.grpc.pb.h") - -# compile *proto files to cpp -set(GRPC_GENERATED_HEADERS - "${hw_proto_hdrs}" - "${hw_grpc_hdrs}") -set(GRPC_GENERATED_SOURCES - "${hw_proto_srcs}" - "${hw_grpc_srcs}") -set(GRPC_GENERATED - ${GRPC_GENERATED_SOURCES} - ${GRPC_GENERATED_HEADERS}) -add_custom_command( - OUTPUT ${GRPC_GENERATED} - COMMAND ${_PROTOBUF_PROTOC} - ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}/include" - --cpp_out "${CMAKE_CURRENT_BINARY_DIR}/include" - -I "${PROTO_PATH}" - --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" - "${PROTO_FILES}" - DEPENDS "${PROTO_FILES}") - - -# hw_grpc_proto -add_library(caosdb_info_v1alpha1 - ${GRPC_GENERATED}) -target_link_libraries(caosdb_info_v1alpha1 - ${CONAN_LIBS}) -target_include_directories(caosdb_info_v1alpha1 PUBLIC - # headers to include when building from source - ${CONAN_INCLUDE_DIRS} - $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include> - $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include> - $<INSTALL_INTERFACE:include> - ) - -target_link_libraries(caosdb - caosdb_info_v1alpha1 - ${CONAN_LIBS} -) -target_link_libraries(caosdbcli - caosdb - caosdb_info_v1alpha1 - ${CONAN_LIBS} -) - - ############################################### ############ INSTALLATION ##################### ############################################### @@ -193,59 +211,36 @@ target_link_libraries(caosdbcli set(libcaosdb_INCLUDE_DEST "include/caosdb") set(libcaosdb_LIB_DEST "lib") - -# generator expressions are needed for the include directories, since -# installing headers changes the include path specify that libcaosdb requires -# the files located in the include/ directory at compile time. This would -# normally look like -# target_include_directories(caosdb PUBLIC include/) -# PUBLIC means that other libraries including caosdb should also include -# the directory include/. -# However, there is a catch. If we are installing the project in -# CMAKE_INSTALL_PREFIX, we can't specify include/ in the build directory: we -# have copied the contents of include to CMAKE_INSTALL_PREFIX/include and we -# would like other projects to include this directory instead of include/. -# The following CMake command handles this. $<BUILD_INTERFACE:...> and -# $<INSTALL_INTERFACE:...> are macros whose values change depending on if we -# are simply building the code or if we are installing it. target_include_directories(caosdb PUBLIC - # headers to include when building from source - $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include> - $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include> + # headers to include when building from source + $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include> + $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include> - # headers to include when installing (implicitly prefixes with ${CMAKE_INSTALL_PREFIX}). - $<INSTALL_INTERFACE:include> - ) + # headers to include when installing (implicitly prefixes with ${CMAKE_INSTALL_PREFIX}). + $<INSTALL_INTERFACE:include> +) + +if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") + target_include_directories(caosdb_grpc PUBLIC + # headers to include when building from source + $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include> + $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include> + + # headers to include when installing (implicitly prefixes with ${CMAKE_INSTALL_PREFIX}). + $<INSTALL_INTERFACE:include> + ) +endif() target_include_directories(caosdbcli PUBLIC ${libcaosdb_SOURCE_DIR}/include> ${libcaosdb_BINARY_DIR}/include> ${CONAN_INCLUDE_DIRS} - ) +) set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local/") -# Install libcaosdb in CMAKE_INSTALL_PREFIX (defaults to /usr/local on linux). -# To change the install location, run -# cmake -DCMAKE_INSTALL_PREFIX=<desired-install-path> .. - -# install(...) specifies installation rules for the project. It can specify -# location of installed files on the system, user permissions, build -# configurations, etc. Here, we are only copying files. -# install(TARGETS ...) specifies rules for installing targets. -# Here, we are taking a target or list of targets (libcosdb) and telling -# CMake the following: -# - put shared libraries associated with libcaosdb in ${libcaosdb_LIB_DEST} -# - put static libraries associated with libcaosdb in ${libcaosdb_LIB_DEST} -# - put include files associated with libcaosdb in ${libcaosdb_INCLUDE_DEST} -# We also need to specify the export that is associated with libcaosdb; an -# export is just a list of targets to be installed. So we are associating -# libcaosdb with libcaosdbTargets. install( # targets to install - TARGETS - caosdb - caosdb_info_v1alpha1 - ${_GRPC_DEPS} + TARGETS ${LIBCAOSDB} # name of the CMake "export group" containing the targets we want to install EXPORT caosdbTargets # Dynamic, static library and include destination locations after running @@ -253,19 +248,9 @@ install( LIBRARY DESTINATION ${libcaosdb_LIB_DEST} ARCHIVE DESTINATION ${libcaosdb_LIB_DEST} INCLUDES DESTINATION ${libcaosdb_INCLUDE_DEST} - ) - - -# We now need to install the export libcaosdbTargets that we defined above. -# This is needed in order for another project to import libcaosdb using -# find_package(caosdb) -# find_package(caosdb) will look for caosdb-config.cmake to provide -# information about the targets contained in the project libcaosdb. -# Fortunately, this is specified in the export libcaosdbTargets, so we will -# install this too. -# install(EXPORT ...) will install the information about an export. Here, we -# save it to a file {$libcaosdb_LIB_DEST}/libcaosdbTargets.cmake and prepend -# everything inside libcaosdbTargets with the namespace libcaosdb::. +) + + set(libcaosdb_CMAKE_DEST "${libcaosdb_LIB_DEST}/cmake/caosdb") install( # The export we want to save (matches name defined above containing the @@ -278,10 +263,8 @@ install( NAMESPACE caosdb:: # where to place the resulting file (here, we're putting it with the library) DESTINATION ${libcaosdb_CMAKE_DEST} - ) +) -## install(FILES ...) simply puts files in a certain place with certain -## properties. We're just copying them to the desired place here. install(FILES ${libcaosdb_INCL} DESTINATION ${libcaosdb_INCLUDE_DEST}) install(FILES ${GRPC_GENERATED_HEADERS} DESTINATION ${libcaosdb_INCLUDE_DEST}/${hw_hdrs_path}) @@ -310,4 +293,3 @@ if(AUTOFORMATTING) ${format_test_sources} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) endif() - diff --git a/conanfile.py b/conanfile.py index 947b59f..b32c783 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools class CaosdbConan(ConanFile): name = "caosdb" - version = "0.0.3" + version = "0.0.4" license = "AGPL-3.0-or-later" author = "Timm C. Fitschen <t.fitschen@indiscale.com>" url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git" @@ -47,4 +47,4 @@ class CaosdbConan(ConanFile): self.copy("*.a", dst="lib", keep_path=False) def package_info(self): - self.cpp_info.libs = ["caosdb", "caosdb_info_v1alpha1"] + self.cpp_info.libs = ["caosdb"] diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index a71690f..89657f1 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -20,12 +20,14 @@ # add all header files to this list set(libcaosdb_INCL - ${CMAKE_CURRENT_BINARY_DIR}/caosdb/constants.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utils.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/info.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.h + ${CMAKE_CURRENT_BINARY_DIR}/caosdb/constants.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/entity.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/exceptions.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/info.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utils.h ) # pass variable to parent scope diff --git a/include/caosdb/connection.h b/include/caosdb/connection.h index 7c971c0..a58f043 100644 --- a/include/caosdb/connection.h +++ b/include/caosdb/connection.h @@ -27,10 +27,13 @@ * @date 2021-05-18 * @brief Configuration and setup of the connection. */ -#include <iosfwd> // for ostream -#include <memory> // for shared_ptr, unique_ptr -#include <string> // for string -#include "caosdb/info/v1alpha1/main.grpc.pb.h" // for GeneralInfoService +#include <iosfwd> // for ostream +#include <memory> // for shared_ptr, unique_ptr +#include <string> // for string +#include "caosdb/transaction.h" +#include "caosdb/info/v1alpha1/main.grpc.pb.h" // for GeneralInfoService +#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransactionService + namespace caosdb { namespace authentication { class Authenticator; @@ -40,13 +43,16 @@ class VersionInfo; } // namespace info } // namespace caosdb namespace grpc { +class Channel; class ChannelCredentials; } // namespace grpc namespace caosdb::connection { using caosdb::authentication::Authenticator; +using caosdb::entity::v1alpha1::EntityTransactionService; using caosdb::info::VersionInfo; using caosdb::info::v1alpha1::GeneralInfoService; +using caosdb::transaction::Transaction; using grpc::ChannelCredentials; class CACertificateProvider { @@ -131,16 +137,16 @@ public: class CaosDBConnection { std::shared_ptr<grpc::Channel> channel; std::shared_ptr<CaosDBConnectionConfig> config; - std::unique_ptr<GeneralInfoService::Stub> stub_; + std::unique_ptr<GeneralInfoService::Stub> general_info_service; + std::shared_ptr<EntityTransactionService::Stub> entity_transaction_service; public: explicit CaosDBConnection( const std::shared_ptr<CaosDBConnectionConfig> &config); friend auto operator<<(std::ostream &out, const CaosDBConnection &connection) -> std::ostream &; - [[nodiscard]] auto getGeneralInfoService() const - -> GeneralInfoService::Stub &; - [[nodiscard]] auto getVersionInfo() const -> std::unique_ptr<VersionInfo>; + [[nodiscard]] auto GetVersionInfo() const -> std::unique_ptr<VersionInfo>; + [[nodiscard]] auto CreateTransaction() const -> std::unique_ptr<Transaction>; }; } // namespace caosdb::connection #endif diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h new file mode 100644 index 0000000..d9bdf06 --- /dev/null +++ b/include/caosdb/entity.h @@ -0,0 +1,58 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +/** + * @brief Anything entity-related. + */ +#ifndef CAOSDB_ENTITY_H +#define CAOSDB_ENTITY_H + +#include <string> + +namespace caosdb::entity { + +/** + * Entity ID. + */ +class EntityID { +private: + std::string id; + +public: + EntityID(std::string id); + [[nodiscard]] auto ToString() const -> std::string; +}; + +/** + * @brief Wrapper for the Protobuf entity. + */ +class Entity { +private: + EntityID id; + +public: + [[nodiscard]] auto GetId() const -> EntityID; + auto SetId(EntityID id) -> void; + [[nodiscard]] auto GetName() const -> std::string; +}; + +} // namespace caosdb::entity +#endif diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h new file mode 100644 index 0000000..552f1f0 --- /dev/null +++ b/include/caosdb/transaction.h @@ -0,0 +1,75 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +/** + * @brief Creation and execution of transactions. + */ + +#ifndef CAOSDB_TRANSACTION_H +#define CAOSDB_TRANSACTION_H + +#include <memory> +#include "caosdb/entity.h" +#include "caosdb/entity/v1alpha1/main.pb.h" +#include "caosdb/entity/v1alpha1/main.grpc.pb.h" + +namespace caosdb::transaction { +using caosdb::entity::Entity; +using caosdb::entity::EntityID; +using ProtoEntity = caosdb::entity::v1alpha1::Entity; +using caosdb::entity::v1alpha1::EntityTransactionService; +using caosdb::entity::v1alpha1::RetrieveRequest; + +class ResultSet { +public: + [[nodiscard]] auto GetById(EntityID id) const -> Entity; +}; + +class UniqueResult : public ResultSet { +private: + Entity entity; + +public: + UniqueResult(ProtoEntity entity); +}; + +enum TransactionState { INIT = 10, EXECUTING = 20, SUCCESS = 30, ERROR = 40 }; + +/** + * @brief Create a transaction via `CaosDBConnection.createTransaction()` + */ +class Transaction { +private: + std::shared_ptr<ResultSet> result_set; + TransactionState state = TransactionState::INIT; + std::shared_ptr<EntityTransactionService::Stub> service_stub; + RetrieveRequest request; // TODO(tf) + +public: + Transaction(std::shared_ptr<EntityTransactionService::Stub> service_stub); + auto Retrieve(const EntityID &id) -> void; + auto Execute() -> void; + [[nodiscard]] auto GetResultSet() const -> std::shared_ptr<ResultSet>; + auto WaitForIt() const -> void; +}; + +} // namespace caosdb::transaction +#endif diff --git a/proto b/proto index b0cade5..dd9abe3 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit b0cade5e02daff99eaa46e1201f2786ac873114b +Subproject commit dd9abe3499367c4eded4774ade1acbc90ef048b3 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5f7f41c..2ea6daa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,7 +23,9 @@ set(libcaosdb_SRC ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/entity.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/info.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction.cpp ) # pass variable to parent scope diff --git a/src/caosdb/connection.cpp b/src/caosdb/connection.cpp index 81339c2..24bf8e7 100644 --- a/src/caosdb/connection.cpp +++ b/src/caosdb/connection.cpp @@ -20,32 +20,33 @@ * */ #include "caosdb/connection.h" -#include <grpcpp/create_channel.h> // for CreateChannel -#include <grpcpp/impl/codegen/client_context.h> // for ClientContext -#include <grpcpp/impl/codegen/status.h> // for Status -#include <grpcpp/security/credentials.h> // for SslCredentials -#include <iostream> // for operator<<, basic_... -#include <stdexcept> // for runtime_error -#include <string> // for operator+, char_tr... +#include <grpcpp/create_channel.h> // for CreateChannel +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/status.h> // for Status +#include <grpcpp/security/credentials.h> // for SslCredentials +#include <iostream> // for operator<<, basic_... +#include <stdexcept> // for runtime_error +#include <string> // for operator+, char_tr... +#include <memory> #include "caosdb/authentication.h" // for Authenticator #include "caosdb/exceptions.h" // for AuthenticationError #include "caosdb/info/v1alpha1/main.grpc.pb.h" // for GeneralInfoService #include "caosdb/info/v1alpha1/main.pb.h" // for GetVersionInfoResp... +#include "caosdb/transaction.h" // for Transaction #include "caosdb/utils.h" // for load_string_file #include "caosdb/info.h" // for VersionInfo #include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH... -namespace grpc { -class Channel; -} // namespace grpc namespace caosdb::connection { using caosdb::authentication::Authenticator; +using caosdb::entity::v1alpha1::EntityTransactionService; using caosdb::exceptions::AuthenticationError; using caosdb::exceptions::ConnectionError; using caosdb::info::VersionInfo; using caosdb::info::v1alpha1::GeneralInfoService; using caosdb::info::v1alpha1::GetVersionInfoRequest; using caosdb::info::v1alpha1::GetVersionInfoResponse; +using caosdb::transaction::Transaction; using caosdb::utils::load_string_file; using grpc::InsecureChannelCredentials; using grpc::SslCredentials; @@ -149,7 +150,9 @@ CaosDBConnection::CaosDBConnection( this->config->getHost() + ":" + std::to_string(this->config->getPort()); this->channel = grpc::CreateChannel(target, this->config->getChannelCredentials()); - this->stub_ = GeneralInfoService::NewStub(this->channel); + this->general_info_service = GeneralInfoService::NewStub(this->channel); + this->entity_transaction_service = + std::make_shared<EntityTransactionService::Stub>(this->channel); } auto operator<<(std::ostream &out, const CaosDBConnection &connection) @@ -158,13 +161,13 @@ auto operator<<(std::ostream &out, const CaosDBConnection &connection) return out; } -[[nodiscard]] auto CaosDBConnection::getVersionInfo() const +[[nodiscard]] auto CaosDBConnection::GetVersionInfo() const -> std::unique_ptr<VersionInfo> { const GetVersionInfoRequest request; GetVersionInfoResponse response; grpc::ClientContext context; const grpc::Status status = - this->stub_->GetVersionInfo(&context, request, &response); + this->general_info_service->GetVersionInfo(&context, request, &response); if (!status.ok()) { switch (status.error_code()) { @@ -180,4 +183,10 @@ auto operator<<(std::ostream &out, const CaosDBConnection &connection) return std::make_unique<VersionInfo>(response.release_version_info()); } +[[nodiscard]] auto CaosDBConnection::CreateTransaction() const + -> std::unique_ptr<Transaction> { + auto service_stub = this->entity_transaction_service; + return std::make_unique<Transaction>(service_stub); +}; + } // namespace caosdb::connection diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp new file mode 100644 index 0000000..dc3cbf3 --- /dev/null +++ b/src/caosdb/entity.cpp @@ -0,0 +1,38 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "caosdb/entity.h" + +#include <utility> + +namespace caosdb::entity { + +EntityID::EntityID(std::string id) { this->id = std::move(id); } + +[[nodiscard]] auto EntityID::ToString() const -> std::string { + return this->id; +} + +[[nodiscard]] auto Entity::GetId() const -> EntityID { return this->id; } + +auto Entity::SetId(EntityID id) -> void { this->id = std::move(id); } + +} // namespace caosdb::entity diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp new file mode 100644 index 0000000..1b0faad --- /dev/null +++ b/src/caosdb/transaction.cpp @@ -0,0 +1,89 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "caosdb/entity.h" +#include "caosdb/exceptions.h" // for AuthenticationError +#include "caosdb/transaction.h" +#include <memory> +#include <utility> +#include <iostream> // for basic_ostream::ope... +#include <stdexcept> // for runtime_error +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/status.h> // for Status +#include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH... +#include "caosdb/entity/v1alpha1/main.pb.h" +#include "caosdb/entity/v1alpha1/main.grpc.pb.h" + +namespace caosdb::transaction { +using caosdb::entity::v1alpha1::EntityTransactionService; +using caosdb::entity::v1alpha1::RetrieveRequest; +using caosdb::entity::v1alpha1::RetrieveResponse; +using caosdb::exceptions::AuthenticationError; +using caosdb::exceptions::ConnectionError; + +Transaction::Transaction( + std::shared_ptr<EntityTransactionService::Stub> service_stub) { + this->service_stub = std::move(service_stub); +} + +auto Transaction::Retrieve(const EntityID &id) -> void { + + RetrieveRequest request; + request.mutable_entity()->set_eid(id.ToString()); + + this->request = request; +} + +auto Transaction::Execute() -> void { + // TODO(tf) throw error if not int INIT state + this->state = TransactionState::EXECUTING; + + RetrieveResponse response; + grpc::ClientContext context; + const grpc::Status status = + this->service_stub->Retrieve(&context, this->request, &response); + + if (!status.ok()) { + switch (status.error_code()) { + case grpc::StatusCode::UNAUTHENTICATED: + throw AuthenticationError(status.error_message()); + case grpc::StatusCode::UNAVAILABLE: + throw ConnectionError(status.error_message()); + default: + std::cout << status.error_code() << "\n"; + throw std::runtime_error(status.error_message()); + } + } + // TODO(tf) + this->result_set = std::make_shared<ResultSet>(); +} + +auto Transaction::WaitForIt() const -> void { + // TODO(tf) throw error if still in INIT state + // TODO(tf) +} + +[[nodiscard]] auto Transaction::GetResultSet() const + -> std::shared_ptr<ResultSet> { + return this->result_set; +} + +} // namespace caosdb::transaction diff --git a/src/caosdbcli.cpp b/src/caosdbcli.cpp index 7dc2d71..3151919 100644 --- a/src/caosdbcli.cpp +++ b/src/caosdbcli.cpp @@ -57,10 +57,10 @@ auto main() -> int { auto cacert = std::make_shared<caosdb::connection::PemFileCACertProvider>(pem_file); auto config = std::make_shared<caosdb::connection::SslCaosDBConnectionConfig>( - host, port, cacert); + host, port, cacert, auth); caosdb::connection::CaosDBConnection connection(config); std::cout << std::endl << connection << std::endl; - const auto &v_info = connection.getVersionInfo(); + const auto &v_info = connection.GetVersionInfo(); std::cout << "VersionInfo(" << v_info->GetMajor() << "." << v_info->GetMinor() << "." << v_info->GetPatch() << "-" << v_info->GetPreRelease() << "-" << v_info->GetBuild() << ")" << std::endl; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d1e1c4d..78e25be 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -21,8 +21,9 @@ # append all the test cases here (file name without the ".cpp" suffix) set(test_cases test_connection - test_utils test_info + test_transaction + test_utils ) @@ -46,8 +47,8 @@ foreach (i RANGE "${len_test_cases}") add_executable(${test_case_name} ${test_case_name}.cpp) set(libcaosdb_TEST_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${test_case_name}.cpp ${libcaosdb_TEST_SRC}") - target_link_libraries(${test_case_name} PRIVATE caosdb - caosdb_info_v1alpha1 ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST}) + target_link_libraries(${test_case_name} + PRIVATE ${LIBCAOSDB} ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST}) if(_LINTING) set_target_properties(${test_case_name} PROPERTIES diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp new file mode 100644 index 0000000..cb13a3f --- /dev/null +++ b/test/test_transaction.cpp @@ -0,0 +1,43 @@ +/* + * + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include <memory> // for allocator, make_shared, unique_ptr +#include "caosdb/connection.h" // for InsecureCaosDBConnectionConfig +#include "caosdb/entity.h" // for EntityID +#include "caosdb/transaction.h" // for Transaction, EntityID +#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, TEST, Tes... + +namespace caosdb::transaction { +using caosdb::connection::CaosDBConnection; +using caosdb::connection::InsecureCaosDBConnectionConfig; + +TEST(test_transaction, create_transaction) { + const auto *pHost = "localhost"; + auto config = std::make_shared<InsecureCaosDBConnectionConfig>(pHost, 8000); + CaosDBConnection connection(config); + auto transaction = connection.CreateTransaction(); + + transaction->Retrieve(EntityID("someid")); + transaction->Execute(); +} + +} // namespace caosdb::transaction -- GitLab