diff --git a/CMakeLists.txt b/CMakeLists.txt index abcbaddbe6cea492b54007b468fdb07958c22b1d..39d15c9c54cf933e04bd2827d8175ff91adee090 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,7 +299,7 @@ if(_LINTING) else() message(STATUS "clang-tidy: ${clang_tidy}") set(_CMAKE_CXX_CLANG_TIDY_CHECKS - "--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type") + "--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone") set(_CMAKE_C_CLANG_TIDY_CHECKS "${_CMAKE_CXX_CLANG_TIDY_CHECKS}") set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}" "--header-filter=caosdb/.*[^\(\.pb\.h\)]$" diff --git a/include/caosdb/status_code.h b/include/caosdb/status_code.h index 6e5f7587ea0e114e4eab61c4bd3960f80cdb514d..a6fcda905284ae9dfa9b7e46c6be8da36bb32272 100644 --- a/include/caosdb/status_code.h +++ b/include/caosdb/status_code.h @@ -24,6 +24,8 @@ #include <string> +namespace caosdb { + /** * StatusCodes represent the status of this client, it's connections, * configuration and so on. @@ -33,9 +35,6 @@ * GENERIC_TRANSACTION_ERROR indicates that *there are* errors in a * transaction). */ - -namespace caosdb { - enum StatusCode { READY = -4, GO_ON = -3, diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h index 98148d6171306b2d35414934368568faf5bc2962..f9b6a591bb250c37e069c7ce164248aaa14e40e7 100644 --- a/include/caosdb/transaction.h +++ b/include/caosdb/transaction.h @@ -18,12 +18,8 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. * */ - #ifndef CAOSDB_TRANSACTION_H #define CAOSDB_TRANSACTION_H -/** - * @brief Creation and execution of transactions. - */ #include "boost/log/core/record.hpp" // for record #include "boost/log/sources/record_ostream.hpp" // for basic_record_o... #include "boost/preprocessor/seq/limits/enum_256.hpp" // for BOOST_PP_SEQ_E... @@ -37,11 +33,19 @@ #include "google/protobuf/util/json_util.h" // for MessageToJsonString, Jso... #include <stdexcept> #include <iterator> +// IWYU pragma: no_include <ext/alloc_traits.h> #include <memory> // for shared_ptr, unique_ptr #include <string> // for string #include <vector> // for vector -/* +/** + * @brief Creation and execution of transactions. + * @author Timm Fitschen + * @date 2021-08-05 + */ +namespace caosdb::transaction { + +/** * Do all necessary checks and assure that another retrieval (by id or by * query) can be added as a sub-request to a transaction. */ @@ -62,7 +66,7 @@ "wrong TransactionType.") \ } -/* +/** * Do all necessary checks and assure that another deletion can be added as a * sub-request to a transaction. */ @@ -84,7 +88,7 @@ "wrong TransactionType.") \ } -/* +/** * Do all necessary checks and assure that another insertion can be added as a * sub-request to a transaction. */ @@ -146,8 +150,13 @@ using caosdb::transaction::TransactionStatus; using WrappedResponseCase = caosdb::entity::v1alpha1::TransactionResponse::WrappedResponseCase; +class Transaction; + static const std::string logger_name = "caosdb::transaction"; +/** + * Abstract base class for the results of a Transaction. + */ class ResultSet { public: virtual ~ResultSet() = default; @@ -155,34 +164,16 @@ public: [[nodiscard]] virtual auto At(const int index) const -> const Entity & = 0; }; +/** + * Container with results of a transaction. + * + * In contrast to UniqueResult, this one can also hold multiple entities or zero + * entities. + */ class MultiResultSet : public ResultSet { public: ~MultiResultSet() = default; - explicit inline MultiResultSet(MultiTransactionResponse *response) { - auto responses = response->mutable_responses(); - Entity *entity = nullptr; - for (auto sub_response : *responses) { - switch (sub_response.wrapped_response_case()) { - case WrappedResponseCase::kRetrieveResponse: - entity = new Entity( - sub_response.mutable_retrieve_response()->release_entity()); - break; - case WrappedResponseCase::kInsertResponse: - - entity = new Entity(sub_response.release_insert_response()); - break; - case WrappedResponseCase::kDeleteResponse: - entity = new Entity(sub_response.release_delete_response()); - break; - default: - // TODO(tf) Updates - break; - } - if (entity) { - this->entities.push_back(std::unique_ptr<Entity>(entity)); - } - } - } + explicit MultiResultSet(MultiTransactionResponse *response); [[nodiscard]] inline auto Size() const noexcept -> int override { return this->entities.size(); } @@ -193,6 +184,12 @@ public: std::vector<std::unique_ptr<Entity>> entities; }; +/** + * Container with the single result of a transaction. + * + * In contrast to MultiResultSet, this one guarantees to hold exactly one + * entity. + */ class UniqueResult : public ResultSet { public: ~UniqueResult() = default; @@ -219,14 +216,21 @@ private: */ class Transaction { public: + /** + * The transaction type restricts the kind of sub-transaction which may be + * added to a transaction (insertion, update, deletion, retrieval). + * + * @note MIXED_READ_AND_WRITE and MIXED_WRITE transaction are not supported + * yet. + */ enum TransactionType { - NONE, - READ_ONLY, - INSERT, - UPDATE, - DELETE, - MIXED_WRITE, - MIXED_READ_AND_WRITE + NONE, /// Unspecified or not specified yet. + READ_ONLY, /// Only retrievals (by id, by query) + INSERT, /// Only insertions + UPDATE, /// Only updates + DELETE, /// Only deletions + MIXED_WRITE, /// Only insertions, deletions, updates + MIXED_READ_AND_WRITE /// all kind of transaction. }; Transaction(std::shared_ptr<EntityTransactionService::Stub> service_stub); diff --git a/include/caosdb/transaction_status.h b/include/caosdb/transaction_status.h index 8e54c8ba79c944f6b157a577cc9db64be01e1473..56c6b005112fd15c76f3c2741803a58837baed9e 100644 --- a/include/caosdb/transaction_status.h +++ b/include/caosdb/transaction_status.h @@ -22,15 +22,6 @@ #ifndef CAOSDB_TRANSACTION_STATUS_H #define CAOSDB_TRANSACTION_STATUS_H -/** - * TransactionStatus indicates the current status of a transaction and, when it - * has already terminated, whether the transaction has been successful or not. - * - * A status code of 0 denotes a generic success state, positive values indicate - * errors, and negative values indicate other states, such as different stages - * of a transaction in process. - */ - #include "caosdb/status_code.h" #include "caosdb/exceptions.h" #include <memory> // for shared_ptr, unique_ptr @@ -44,7 +35,12 @@ using caosdb::exceptions::Exception; using caosdb::exceptions::TransactionError; /** - * Status of a Request or Transaction. + * TransactionStatus indicates the current status of a transaction and, when it + * has already terminated, whether the transaction has been successful or not. + * + * A status code of 0 denotes a generic success state, positive values indicate + * errors, and negative values indicate other states, such as different stages + * of a transaction in process. */ class TransactionStatus { public: diff --git a/src/caosdb/configuration.cpp b/src/caosdb/configuration.cpp index ffa860471821b8733efeadf77801b8155ae6711e..76c437234a48fb339f1e04d71afe3ae84ce94ceb 100644 --- a/src/caosdb/configuration.cpp +++ b/src/caosdb/configuration.cpp @@ -39,11 +39,12 @@ #include <cstdlib> // for getenv #include <cstring> // for strcmp #include <exception> // IWYU pragma: keep -#include <grpcpp/security/credentials.h> // for SslCredentials -#include <iterator> // for next -#include <map> // for map -#include <stdexcept> // for out_of_range -#include <string> // for string, operator+ +// IWYU pragma: no_include <bits/exception.h> +#include <grpcpp/security/credentials.h> // for SslCredentials +#include <iterator> // for next +#include <map> // for map +#include <stdexcept> // for out_of_range +#include <string> // for string, operator+ namespace caosdb::configuration { using boost::filesystem::exists; diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index ae9ddd2b45c36b272ffcb62c6239a1ccb891bb5c..3e7b4ba7de97a7fa1d5f568451a1414e9189def5 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -100,6 +100,29 @@ using grpc::ClientAsyncResponseReader; using ProtoEntity = caosdb::entity::v1alpha1::Entity; using grpc::CompletionQueue; +MultiResultSet::MultiResultSet(MultiTransactionResponse *response) { + auto *responses = response->mutable_responses(); + for (auto sub_response : *responses) { + switch (sub_response.wrapped_response_case()) { + case WrappedResponseCase::kRetrieveResponse: + this->entities.push_back(std::make_unique<Entity>( + sub_response.mutable_retrieve_response()->release_entity())); + break; + case WrappedResponseCase::kInsertResponse: + this->entities.push_back( + std::make_unique<Entity>(sub_response.release_insert_response())); + break; + case WrappedResponseCase::kDeleteResponse: + this->entities.push_back( + std::make_unique<Entity>(sub_response.release_insert_response())); + break; + default: + // TODO(tf) Updates + break; + } + } +} + [[nodiscard]] auto UniqueResult::GetEntity() const -> const Entity & { const Entity *result = this->entity.get(); return *result; @@ -268,7 +291,7 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { this->result_set = std::make_unique<UniqueResult>(deletedIdResponse); } break; default: - // TODO(tf) + // TODO(tf) Error and Update break; } } else {