diff --git a/include/caosdb/configuration.h b/include/caosdb/configuration.h index 6426ab4b9e5b6dbfebb3cce4d67983df58a57a6a..80bc927018cb625d045e4f7379555b5a90d7b9b5 100644 --- a/include/caosdb/configuration.h +++ b/include/caosdb/configuration.h @@ -26,9 +26,10 @@ #include "boost/json/object.hpp" // for object #include "boost/json/value.hpp" // for value #include "boost/json/value_ref.hpp" // IWYU pragma: keep -#include "caosdb/authentication.h" // for Authenticator, PlainPassw... -#include "caosdb/certificate_provider.h" // for CertificateProvider, path -#include "caosdb/exceptions.h" // for ConfigurationError +// IWYU pragma: no_include "boost/json/fwd.hpp" +#include "caosdb/authentication.h" // for Authenticator, PlainPassw... +#include "caosdb/certificate_provider.h" // for CertificateProvider, path +#include "caosdb/exceptions.h" // for ConfigurationError #include "caosdb/logging.h" #include "caosdb/utility.h" // for load_json_file #include "grpcpp/security/credentials.h" // for ChannelCredentials diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h index 10333d75ba16da611e39433de803c4b004ee96ac..5f261dfb0c9e28946574387fca9fd17b6e577ecf 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -39,6 +39,7 @@ using caosdb::entity::v1alpha1::IdResponse; using ProtoParent = caosdb::entity::v1alpha1::Parent; using ProtoProperty = caosdb::entity::v1alpha1::Property; using ProtoEntity = caosdb::entity::v1alpha1::Entity; +using caosdb::entity::v1alpha1::FileTransmissionId; /** * Messages convey information about the state and result of transactions. @@ -456,12 +457,23 @@ public: */ auto CopyTo(ProtoEntity *target) -> void; + auto SetFileTransmissionId(const std::string ®istration_id, + const std::string &file_id) -> void; + auto SetFilePath(const std::string &path) -> void; + inline auto GetFileTransmissionId() const -> const FileTransmissionId & { + return *(this->file_transmission_id); + } + inline auto HasFile() const -> bool { + return this->file_transmission_id != nullptr; + } + protected: static auto CreateProtoEntity() -> ProtoEntity *; auto SetId(const std::string &id) -> void; auto SetVersionId(const std::string &id) -> void; private: + FileTransmissionId *file_transmission_id = nullptr; ProtoEntity *wrapped; Properties properties; Parents parents; diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h index ce7eb42fc72603b6d08d04321e1e619c293d0e9a..a1295904cc68488568a0f6753bdfded5d9ae5db5 100644 --- a/include/caosdb/transaction.h +++ b/include/caosdb/transaction.h @@ -37,6 +37,7 @@ #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 @@ -139,10 +140,15 @@ namespace caosdb::transaction { using caosdb::entity::Entity; using ProtoEntity = caosdb::entity::v1alpha1::Entity; using caosdb::entity::v1alpha1::EntityTransactionService; +using caosdb::entity::v1alpha1::FileDownloadResponse; using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1alpha1::FileUploadRequest; +using caosdb::entity::v1alpha1::FileUploadResponse; using caosdb::entity::v1alpha1::IdResponse; using caosdb::entity::v1alpha1::MultiTransactionRequest; using caosdb::entity::v1alpha1::MultiTransactionResponse; +using caosdb::entity::v1alpha1::RegisterFileDownloadRequest; +using caosdb::entity::v1alpha1::RegisterFileDownloadResponse; using caosdb::entity::v1alpha1::RegisterFileUploadResponse; using caosdb::transaction::TransactionStatus; using WrappedResponseCase = @@ -221,7 +227,14 @@ private: */ class Transaction { public: + auto UploadFile(FileUploadResponse *response, + const std::string ®istration_id) -> void; auto RegisterUploadFile(RegisterFileUploadResponse *response) -> void; + auto DownloadFile(FileDownloadResponse *response, + const RegisterFileDownloadResponse ®istration_response) + -> void; + auto RegisterDownloadFile(const RegisterFileDownloadRequest &request, + RegisterFileDownloadResponse *response) -> void; enum TransactionType { NONE, READ_ONLY, 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/entity.cpp b/src/caosdb/entity.cpp index 999ba3753b068909dc7dd54518ca5ff8bd8033bf..11e0ca0878856884be52466c86e6625ad96401f4 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -208,4 +208,17 @@ auto Entity::SetDatatype(const std::string &datatype) -> void { this->wrapped->set_datatype(datatype); } +auto Entity::SetFilePath(const std::string &path) -> void { + this->wrapped->mutable_file_descriptor()->set_path(path); +} + +auto Entity::SetFileTransmissionId(const std::string ®istration_id, + const std::string &file_id) -> void { + this->file_transmission_id = + google::protobuf::Arena::CreateMessage<FileTransmissionId>(get_arena()); + + this->file_transmission_id->set_registration_id(registration_id); + this->file_transmission_id->set_file_id(file_id); +} + } // namespace caosdb::entity diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 3a23b4994bf36a0475a5f292b84edbd7a28814df..1c889fef4d51486e244f20bd65996eedb465a951 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -91,9 +91,15 @@ auto get_status_description(int code) -> const std::string & { namespace caosdb::transaction { using caosdb::entity::v1alpha1::EntityTransactionService; +using caosdb::entity::v1alpha1::FileDownloadRequest; +using caosdb::entity::v1alpha1::FileDownloadResponse; using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1alpha1::FileUploadRequest; +using caosdb::entity::v1alpha1::FileUploadResponse; using caosdb::entity::v1alpha1::MultiTransactionRequest; using caosdb::entity::v1alpha1::MultiTransactionResponse; +using caosdb::entity::v1alpha1::RegisterFileDownloadRequest; +using caosdb::entity::v1alpha1::RegisterFileDownloadResponse; using caosdb::entity::v1alpha1::RegisterFileUploadRequest; using caosdb::entity::v1alpha1::RegisterFileUploadResponse; using WrappedResponseCase = @@ -154,6 +160,10 @@ auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode { // copy the original entity for the transaction entity->CopyTo(proto_entity); + if (entity->HasFile()) { + sub_request->mutable_insert_request()->mutable_upload_id()->CopyFrom( + entity->GetFileTransmissionId()); + } return StatusCode::INITIAL; } @@ -302,7 +312,87 @@ auto Transaction::RegisterUploadFile(RegisterFileUploadResponse *response) void *recv_tag = nullptr; bool ok = false; - // TODO(tf) make this actually asynchronous by moving this to WaitForIt() + cq.Next(&recv_tag, &ok); + assert(recv_tag == send_tag); + assert(ok); +} + +auto Transaction::UploadFile(FileUploadResponse *response, + const std::string ®istration_id) -> void { + grpc::Status grpc_status; + CompletionQueue cq; + grpc::ClientContext context; + + FileUploadRequest request; + auto *chunk = request.mutable_chunk(); + auto *file_transmission_id = chunk->mutable_file_transmission_id(); + file_transmission_id->set_registration_id(registration_id); + file_transmission_id->set_file_id("test.txt"); + chunk->set_data("this is some data"); + + std::unique_ptr<ClientAsyncResponseReader<FileUploadResponse>> rpc( + this->file_service->PrepareAsyncFileUpload(&context, request, &cq)); + + rpc->StartCall(); + + int tag = 1; + void *send_tag = static_cast<void *>(&tag); + rpc->Finish(response, &grpc_status, send_tag); + void *recv_tag = nullptr; + bool ok = false; + + cq.Next(&recv_tag, &ok); + assert(recv_tag == send_tag); + assert(ok); +} + +auto Transaction::DownloadFile( + FileDownloadResponse *response, + const RegisterFileDownloadResponse ®istration_response) -> void { + + FileDownloadRequest request; + auto *file_transmission_id = request.mutable_file_transmission_id(); + file_transmission_id->CopyFrom( + registration_response.files(0).file_transmission_id()); + grpc::Status grpc_status; + CompletionQueue cq; + + grpc::ClientContext context; + std::unique_ptr<ClientAsyncResponseReader<FileDownloadResponse>> rpc( + this->file_service->PrepareAsyncFileDownload(&context, request, &cq)); + + rpc->StartCall(); + + int tag = 1; + void *send_tag = static_cast<void *>(&tag); + rpc->Finish(response, &grpc_status, send_tag); + void *recv_tag = nullptr; + bool ok = false; + + cq.Next(&recv_tag, &ok); + assert(recv_tag == send_tag); + assert(ok); +} + +auto Transaction::RegisterDownloadFile( + const RegisterFileDownloadRequest &request, + RegisterFileDownloadResponse *response) -> void { + grpc::Status grpc_status; + CompletionQueue cq; + + grpc::ClientContext context; + std::unique_ptr<ClientAsyncResponseReader<RegisterFileDownloadResponse>> rpc( + this->file_service->PrepareAsyncRegisterFileDownload(&context, request, + &cq)); + + rpc->StartCall(); + + int tag = 1; + void *send_tag = static_cast<void *>(&tag); + rpc->Finish(response, &grpc_status, send_tag); + void *recv_tag = nullptr; + bool ok = false; + cq.Next(&recv_tag, &ok); assert(recv_tag == send_tag); assert(ok);