diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index f6689deb461e3a8e4e0617d2514d69985be5d4dd..d480ec17b4ad33498ca1a845ebc0fb1a622cb04a 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -42,13 +42,11 @@ set(libcaosdb_INCL ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utility.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/value.h ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_upload_handler.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/Client.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/UploadRequestHandler.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/DownloadRequestHandler.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileWriter.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileReader.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileLock.h - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileError.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/upload_request_handler.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/download_request_handler.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/file_writer.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/file_reader.h + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/file_error.h ) # pass variable to parent scope diff --git a/include/caosdb/file_transmission/Client.h b/include/caosdb/file_transmission/Client.h deleted file mode 100644 index 3a2b4a8fc487112a4d89d845d0340620261c2fc4..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/Client.h +++ /dev/null @@ -1,41 +0,0 @@ -#include "caosdb/entity.h" // for FileDescriptor -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/handler_interface.h" // for HandlerInterface -#include "caosdb/status_code.h" // for StatusCode -#include "caosdb/transaction_status.h" // for StatusCode -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <memory> // for shared_ptr, uniqu... - -namespace caosdb::transaction { -using caosdb::StatusCode; -using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::FileTransmissionService; - -class FileExchangeClient final { -public: - FileExchangeClient( - const std::shared_ptr<FileTransmissionService::Stub> &service) - : stub_(service) {} - - ~FileExchangeClient(); - - FileExchangeClient(const FileExchangeClient &) = delete; - FileExchangeClient &operator=(const FileExchangeClient &) = delete; - FileExchangeClient(FileExchangeClient &&) = delete; - FileExchangeClient &operator=(FileExchangeClient &&) = delete; - - StatusCode upload(const FileDescriptor &file_descriptor); - StatusCode download(const FileDescriptor &file_descriptor); - - void Cancel(); - -private: - int processMessages(); - - grpc::CompletionQueue cq_; - - std::shared_ptr<FileTransmissionService::Stub> stub_; - std::unique_ptr<HandlerInterface> handler_; -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/DownloadRequestHandler.h b/include/caosdb/file_transmission/DownloadRequestHandler.h deleted file mode 100644 index a59f9067605ac15aa01f569b8cc10ccadd6e7fef..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/DownloadRequestHandler.h +++ /dev/null @@ -1,73 +0,0 @@ -#include "caosdb/entity.h" // for FileDescriptor -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse -#include "caosdb/file_transmission/FileWriter.h" // for FileWriter -#include "caosdb/handler_interface.h" // for HandlerTag, Handl... -#include "caosdb/transaction_status.h" // for TransactionStatus -#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncReader -#include <grpcpp/impl/codegen/client_context.h> // for ClientContext -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <grpcpp/impl/codegen/status.h> // for Status -#include <memory> // for unique_ptr - -namespace caosdb::transaction { -using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::FileDownloadRequest; -using caosdb::entity::v1alpha1::FileDownloadResponse; -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::transaction::HandlerInterface; -using caosdb::transaction::HandlerTag; - -class DownloadRequestHandler final : public HandlerInterface { -public: - DownloadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub, - grpc::CompletionQueue *cq, - FileDescriptor file_descriptor); - - ~DownloadRequestHandler() override = default; - - DownloadRequestHandler(const DownloadRequestHandler &) = delete; - DownloadRequestHandler &operator=(const DownloadRequestHandler &) = delete; - DownloadRequestHandler(DownloadRequestHandler &&) = delete; - DownloadRequestHandler &operator=(DownloadRequestHandler &&) = delete; - - TransactionStatus GetStatus() override { - return TransactionStatus::EXECUTING(); - } - - void Start() override { OnNext(true); } - - bool OnNext(bool ok) override; - - void Cancel() override; - -protected: - enum class CallState { NewCall, SendingRequest, ReceivingFile, CallComplete }; - - void handleNewCallState(); - void handleSendingRequestState(); - void handleReceivingFileState(); - void handleCallCompleteState(); - - HandlerTag tag_; - - FileTransmissionService::Stub *stub_; - grpc::CompletionQueue *cq_; - grpc::ClientContext ctx_; - - std::unique_ptr<grpc::ClientAsyncReader<FileDownloadResponse>> rpc_; - - FileDownloadRequest *request_; - FileDownloadResponse *response_; - grpc::Status status_; - - CallState state_; - - std::unique_ptr<FileWriter> fileWriter_; - - FileDescriptor file_descriptor_; - - unsigned long long bytesReceived_; -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/FileError.h b/include/caosdb/file_transmission/FileError.h deleted file mode 100644 index f9bae6083fc7f1db4791f82fee474302b77cd420..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/FileError.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include <stdexcept> -#include <string> - -namespace caosdb::transaction { - -class FileLockError : public std::runtime_error { -public: - FileLockError(const std::string &message) : std::runtime_error(message) {} -}; - -class FileIOError : public std::runtime_error { -public: - FileIOError(const std::string &message) : std::runtime_error(message) {} -}; - -class FileNotManagedError : public std::runtime_error { -public: - FileNotManagedError(const std::string &message) - : std::runtime_error(message) {} -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/FileLock.h b/include/caosdb/file_transmission/FileLock.h deleted file mode 100644 index 40092ea49e842f8848da40c38ee4b26135c846aa..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/FileLock.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include <mutex> -#include <shared_mutex> - -namespace caosdb::transaction { - -using FileMutex = std::shared_timed_mutex; -using FileReadLock = std::shared_lock<FileMutex>; -using FileWriteLock = std::unique_lock<FileMutex>; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/FileReader.h b/include/caosdb/file_transmission/FileReader.h deleted file mode 100644 index 4ddca922cf5304239086840cb268b1205b505bb2..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/FileReader.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "caosdb/file_transmission/FileLock.h" // for FileMutex, FileReadLock -#include <boost/filesystem/fstream.hpp> // for ifstream -#include <boost/filesystem/operations.hpp> // for exists -#include <boost/filesystem/path.hpp> // for path -#include <fstream> // for ifstream, size_t -#include <memory> // for shared_ptr -#include <string> // for string - -namespace caosdb::transaction { -using boost::filesystem::exists; -using boost::filesystem::ifstream; -using boost::filesystem::path; - -class FileReader final { -public: - FileReader(boost::filesystem::path filename); - FileReader(boost::filesystem::path filename, - std::shared_ptr<FileMutex> mutexPtr); - - ~FileReader() = default; - - FileReader(const FileReader &) = delete; - FileReader &operator=(const FileReader &) = delete; - - FileReader(FileReader &&) = default; - FileReader &operator=(FileReader &&) = default; - - unsigned long long fileSize() const { return size_; } - - std::size_t read(std::string &buffer); - -private: - void openFile(); - - std::ifstream stream_; - boost::filesystem::path filename_; - unsigned long long size_; - - std::shared_ptr<FileMutex> mutexPtr_; - FileReadLock lock_; -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/FileWriter.h b/include/caosdb/file_transmission/FileWriter.h deleted file mode 100644 index 0142d723910d361bee905c76c28d2157c7aebdb6..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/FileWriter.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include "caosdb/file_transmission/FileLock.h" // for FileMutex, FileWriteLock -#include <boost/filesystem/path.hpp> // for path -#include <fstream> // for ofstream -#include <memory> // for shared_ptr -#include <string> // for string - -namespace caosdb::transaction { - -class FileWriter final { -public: - FileWriter(boost::filesystem::path filename); - FileWriter(boost::filesystem::path filename, - std::shared_ptr<FileMutex> mutexPtr); - - ~FileWriter() = default; - - FileWriter(const FileWriter &) = delete; - FileWriter &operator=(const FileWriter &) = delete; - - FileWriter(FileWriter &&) = default; - FileWriter &operator=(FileWriter &&) = default; - - void write(const std::string &buffer); - -private: - void openFile(); - - std::ofstream stream_; - boost::filesystem::path filename_; - - std::shared_ptr<FileMutex> mutexPtr_; - FileWriteLock lock_; -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/UploadRequestHandler.h b/include/caosdb/file_transmission/UploadRequestHandler.h deleted file mode 100644 index 8ee96c8a2875162bbbb615fdb2d30a2e47f82370..0000000000000000000000000000000000000000 --- a/include/caosdb/file_transmission/UploadRequestHandler.h +++ /dev/null @@ -1,81 +0,0 @@ -#include "caosdb/entity.h" // for FileDescriptor -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileUploadRequest -#include "caosdb/file_transmission/FileReader.h" // for FileReader -#include "caosdb/handler_interface.h" // for HandlerTag, Handl... -#include "caosdb/transaction_status.h" // for TransactionStatus -#include <cstdint> // for uint64_t -#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncWriter -#include <grpcpp/impl/codegen/client_context.h> // for ClientContext -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue -#include <grpcpp/impl/codegen/status.h> // for Status -#include <memory> // for unique_ptr - -namespace caosdb::transaction { -using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::entity::v1alpha1::FileUploadRequest; -using caosdb::entity::v1alpha1::FileUploadResponse; -using caosdb::transaction::HandlerInterface; -using caosdb::transaction::HandlerTag; - -class UploadRequestHandler final : public HandlerInterface { -public: - UploadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub, - grpc::CompletionQueue *cq, - FileDescriptor file_descriptor); - - ~UploadRequestHandler() override = default; - - UploadRequestHandler(const UploadRequestHandler &) = delete; - UploadRequestHandler &operator=(const UploadRequestHandler &) = delete; - UploadRequestHandler(UploadRequestHandler &&) = delete; - UploadRequestHandler &operator=(UploadRequestHandler &&) = delete; - - TransactionStatus GetStatus() override { - return TransactionStatus::EXECUTING(); - } - - void Start() override { OnNext(true); } - - bool OnNext(bool ok) override; - - void Cancel() override; - -protected: - enum class CallState { - NewCall, - SendingHeader, - SendingFile, - ExpectingResponse, - CallComplete - }; - - void handleNewCallState(); - void handleSendingHeaderState(); - void handleSendingFileState(); - void handleExpectingResponseState(); - void handleCallCompleteState(); - - HandlerTag tag_; - - FileTransmissionService::Stub *stub_; - grpc::CompletionQueue *cq_; - grpc::ClientContext ctx_; - - std::unique_ptr<grpc::ClientAsyncWriter<FileUploadRequest>> rpc_; - - FileUploadRequest *request_; - FileUploadResponse *response_; - grpc::Status status_; - - CallState state_; - - std::unique_ptr<FileReader> fileReader_; - - FileDescriptor file_descriptor_; - - uint64_t bytesToSend_; -}; - -} // namespace caosdb::transaction diff --git a/include/caosdb/file_transmission/download_request_handler.h b/include/caosdb/file_transmission/download_request_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..c6ee1c36b67c637c8faad901f590a4eee318b7b5 --- /dev/null +++ b/include/caosdb/file_transmission/download_request_handler.h @@ -0,0 +1,121 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_DOWNLOAD_REQUEST_HANDLER_H +#define CAOSDB_FILE_TRANSMISSION_DOWNLOAD_REQUEST_HANDLER_H + +#include "caosdb/entity.h" // for FileDescriptor +#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse +#include "caosdb/file_transmission/file_writer.h" // for FileWriter +#include "caosdb/handler_interface.h" // for HandlerTag, Handl... +#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncReader +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue +#include <grpcpp/impl/codegen/status.h> // for Status +#include <memory> // for unique_ptr + +namespace caosdb::transaction { +using caosdb::entity::FileDescriptor; +using caosdb::entity::v1alpha1::FileDownloadRequest; +using caosdb::entity::v1alpha1::FileDownloadResponse; +using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::transaction::HandlerInterface; +using caosdb::transaction::HandlerTag; + +class DownloadRequestHandler final : public HandlerInterface { +public: + DownloadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub, + grpc::CompletionQueue *cq, + FileDescriptor file_descriptor); + + ~DownloadRequestHandler() override = default; + + DownloadRequestHandler(const DownloadRequestHandler &) = delete; + DownloadRequestHandler &operator=(const DownloadRequestHandler &) = delete; + DownloadRequestHandler(DownloadRequestHandler &&) = delete; + DownloadRequestHandler &operator=(DownloadRequestHandler &&) = delete; + + void Start() override { OnNext(true); } + + bool OnNext(bool ok) override; + + void Cancel() override; + +protected: + enum class CallState { NewCall, SendingRequest, ReceivingFile, CallComplete }; + + void handleNewCallState(); + void handleSendingRequestState(); + void handleReceivingFileState(); + void handleCallCompleteState(); + + HandlerTag tag_; + + FileTransmissionService::Stub *stub_; + grpc::CompletionQueue *cq_; + grpc::ClientContext ctx_; + + std::unique_ptr<grpc::ClientAsyncReader<FileDownloadResponse>> rpc_; + + FileDownloadRequest *request_; + FileDownloadResponse *response_; + grpc::Status status_; + + CallState state_; + + std::unique_ptr<FileWriter> fileWriter_; + + FileDescriptor file_descriptor_; + + unsigned long long bytesReceived_; +}; + +} // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/file_transmission/file_error.h b/include/caosdb/file_transmission/file_error.h new file mode 100644 index 0000000000000000000000000000000000000000..ae057be3ba47f894f8fdbc22adb6e6d56accdafd --- /dev/null +++ b/include/caosdb/file_transmission/file_error.h @@ -0,0 +1,64 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_FILE_ERROR_H +#define CAOSDB_FILE_TRANSMISSION_FILE_ERROR_H + +#include <stdexcept> +#include <string> + +namespace caosdb::transaction { + +class FileIOError : public std::runtime_error { +public: + FileIOError(const std::string &message) : std::runtime_error(message) {} +}; + +} // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/file_transmission/file_reader.h b/include/caosdb/file_transmission/file_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..67c1247fa97cc43e28064b4e0da81812f41b231a --- /dev/null +++ b/include/caosdb/file_transmission/file_reader.h @@ -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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_FILE_READER_H +#define CAOSDB_FILE_TRANSMISSION_FILE_READER_H + +#include <boost/filesystem/fstream.hpp> // for ifstream +#include <boost/filesystem/operations.hpp> // for exists +#include <boost/filesystem/path.hpp> // for path +#include <fstream> // for ifstream, size_t +#include <string> // for string + +namespace caosdb::transaction { +using boost::filesystem::exists; +using boost::filesystem::ifstream; +using boost::filesystem::path; + +class FileReader final { +public: + FileReader(boost::filesystem::path filename); + + ~FileReader() = default; + + FileReader(const FileReader &) = delete; + FileReader &operator=(const FileReader &) = delete; + + FileReader(FileReader &&) = default; + FileReader &operator=(FileReader &&) = default; + + unsigned long long fileSize() const { return size_; } + + std::size_t read(std::string &buffer); + +private: + void openFile(); + + std::ifstream stream_; + boost::filesystem::path filename_; + unsigned long long size_; +}; + +} // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/file_transmission/file_writer.h b/include/caosdb/file_transmission/file_writer.h new file mode 100644 index 0000000000000000000000000000000000000000..801d74b9547951d2a3b86ed4b333bfb4b7035aa9 --- /dev/null +++ b/include/caosdb/file_transmission/file_writer.h @@ -0,0 +1,81 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_FILE_WRITER_H +#define CAOSDB_FILE_TRANSMISSION_FILE_WRITER_H + +#include <boost/filesystem/path.hpp> // for path +#include <fstream> // for ofstream +#include <string> // for string + +namespace caosdb::transaction { + +class FileWriter final { +public: + FileWriter(boost::filesystem::path filename); + + ~FileWriter() = default; + + FileWriter(const FileWriter &) = delete; + FileWriter &operator=(const FileWriter &) = delete; + + FileWriter(FileWriter &&) = default; + FileWriter &operator=(FileWriter &&) = default; + + void write(const std::string &buffer); + +private: + void openFile(); + + std::ofstream stream_; + boost::filesystem::path filename_; +}; + +} // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/file_transmission/register_file_upload_handler.h b/include/caosdb/file_transmission/register_file_upload_handler.h index 0d41b947eebf92b50ac6b33b97f0dc67bf6bad9c..17a42c0a2a2cf1d591048abb6e4c8b329bfd008c 100644 --- a/include/caosdb/file_transmission/register_file_upload_handler.h +++ b/include/caosdb/file_transmission/register_file_upload_handler.h @@ -1,4 +1,54 @@ -#pragma once +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_REGISTER_FILE_UPLOAD_H +#define CAOSDB_FILE_TRANSMISSION_REGISTER_FILE_UPLOAD_H + #include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... #include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse #include "caosdb/handler_interface.h" // for HandlerTag, Handl... @@ -30,7 +80,6 @@ public: protected: void handleNewCallState() override; - void handleReceivingFileState() override; HandlerTag tag_; @@ -44,3 +93,5 @@ protected: }; } // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/file_transmission/upload_request_handler.h b/include/caosdb/file_transmission/upload_request_handler.h new file mode 100644 index 0000000000000000000000000000000000000000..54621d12ba7d67d374037ecdb1f1259662071319 --- /dev/null +++ b/include/caosdb/file_transmission/upload_request_handler.h @@ -0,0 +1,129 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_FILE_TRANSMISSION_UPLOAD_REQUEST_HANDLER_H +#define CAOSDB_FILE_TRANSMISSION_UPLOAD_REQUEST_HANDLER_H + +#include "caosdb/entity.h" // for FileDescriptor +#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1alpha1/main.pb.h" // for FileUploadRequest +#include "caosdb/file_transmission/file_reader.h" // for FileReader +#include "caosdb/handler_interface.h" // for HandlerTag, Handl... +#include <cstdint> // for uint64_t +#include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncWriter +#include <grpcpp/impl/codegen/client_context.h> // for ClientContext +#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue +#include <grpcpp/impl/codegen/status.h> // for Status +#include <memory> // for unique_ptr + +namespace caosdb::transaction { +using caosdb::entity::FileDescriptor; +using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1alpha1::FileUploadRequest; +using caosdb::entity::v1alpha1::FileUploadResponse; +using caosdb::transaction::HandlerInterface; +using caosdb::transaction::HandlerTag; + +class UploadRequestHandler final : public HandlerInterface { +public: + UploadRequestHandler(HandlerTag tag, FileTransmissionService::Stub *stub, + grpc::CompletionQueue *cq, + FileDescriptor file_descriptor); + + ~UploadRequestHandler() override = default; + + UploadRequestHandler(const UploadRequestHandler &) = delete; + UploadRequestHandler &operator=(const UploadRequestHandler &) = delete; + UploadRequestHandler(UploadRequestHandler &&) = delete; + UploadRequestHandler &operator=(UploadRequestHandler &&) = delete; + + void Start() override { OnNext(true); } + + bool OnNext(bool ok) override; + + void Cancel() override; + +protected: + enum class CallState { + NewCall, + SendingHeader, + SendingFile, + ExpectingResponse, + CallComplete + }; + + void handleNewCallState(); + void handleSendingHeaderState(); + void handleSendingFileState(); + void handleExpectingResponseState(); + void handleCallCompleteState(); + + HandlerTag tag_; + + FileTransmissionService::Stub *stub_; + grpc::CompletionQueue *cq_; + grpc::ClientContext ctx_; + + std::unique_ptr<grpc::ClientAsyncWriter<FileUploadRequest>> rpc_; + + FileUploadRequest *request_; + FileUploadResponse *response_; + grpc::Status status_; + + CallState state_; + + std::unique_ptr<FileReader> fileReader_; + + FileDescriptor file_descriptor_; + + uint64_t bytesToSend_; +}; + +} // namespace caosdb::transaction + +#endif diff --git a/include/caosdb/handler_interface.h b/include/caosdb/handler_interface.h index ff1a42b047cc7f216cacc63c945e97adb709c66c..4ba563a300175478c8140e9b88c991e2f5321245 100644 --- a/include/caosdb/handler_interface.h +++ b/include/caosdb/handler_interface.h @@ -59,6 +59,8 @@ const static std::string logger_name = "caosdb::transaction"; class HandlerInterface { public: + HandlerInterface() : transaction_status(TransactionStatus::READY()) {} + virtual ~HandlerInterface() = default; virtual void Start() = 0; @@ -67,7 +69,10 @@ public: virtual void Cancel() = 0; - virtual TransactionStatus GetStatus() = 0; + inline TransactionStatus GetStatus() { return this->transaction_status; } + +protected: + TransactionStatus transaction_status; }; using HandlerPtr = std::unique_ptr<HandlerInterface>; diff --git a/include/caosdb/transaction_handler.h b/include/caosdb/transaction_handler.h index 69df4f0b370c5cdcc9515a916e36c1c899fd3397..0a7154d03dfbde19284807d1e1f40998c89e1de0 100644 --- a/include/caosdb/transaction_handler.h +++ b/include/caosdb/transaction_handler.h @@ -30,7 +30,6 @@ public: protected: virtual void handleNewCallState() override; - virtual void handleReceivingFileState() override; HandlerTag tag_; diff --git a/include/caosdb/unary_rpc_handler.h b/include/caosdb/unary_rpc_handler.h index 816bd65683eeee0d5aebf34abb386c76cbb544fb..6955504a2baea38cb0bd8075bdca2d20c9f8a52a 100644 --- a/include/caosdb/unary_rpc_handler.h +++ b/include/caosdb/unary_rpc_handler.h @@ -1,4 +1,54 @@ -#pragma once +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#ifndef CAOSDB_UNARY_RPC_HANDLER_H +#define CAOSDB_UNARY_RPC_HANDLER_H + #include "caosdb/handler_interface.h" // for HandlerTag, Handl... #include "caosdb/transaction_status.h" // for TransactionStatus #include <grpcpp/impl/codegen/client_context.h> // for ClientContext @@ -10,8 +60,8 @@ namespace caosdb::transaction { class UnaryRpcHandler : public HandlerInterface { public: inline UnaryRpcHandler(grpc::CompletionQueue *completion_queue) - : state_(CallState::NewCall), completion_queue(completion_queue), - transaction_status(TransactionStatus::EXECUTING()) {} + : HandlerInterface(), state_(CallState::NewCall), + completion_queue(completion_queue) {} void Start() override { transaction_status = TransactionStatus::EXECUTING(); @@ -22,20 +72,18 @@ public: void Cancel() override; - TransactionStatus GetStatus() override { return transaction_status; } - protected: virtual void handleNewCallState() = 0; - virtual void handleReceivingFileState() = 0; void handleCallCompleteState(); - enum class CallState { NewCall, ReceivingFile, CallComplete }; + enum class CallState { NewCall, CallComplete }; CallState state_; grpc::CompletionQueue *completion_queue; grpc::ClientContext call_context; grpc::Status status_; - TransactionStatus transaction_status; }; } // namespace caosdb::transaction + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 366875d669b57c4df3942aec5fa4658873754a86..89180ee81fc6b07d4f081c90fd1200530a2d60b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,11 +31,10 @@ set(libcaosdb_SRC ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction_handler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/unary_rpc_handler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_upload_handler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/Client.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/UploadRequestHandler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/DownloadRequestHandler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileWriter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/FileReader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/upload_request_handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/download_request_handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/file_writer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/file_reader.cpp ) # pass variable to parent scope diff --git a/src/caosdb/file_transmission/Client.cpp b/src/caosdb/file_transmission/Client.cpp deleted file mode 100644 index 9adabd60806537c35ac882fa601723a2cad37464..0000000000000000000000000000000000000000 --- a/src/caosdb/file_transmission/Client.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "caosdb/file_transmission/Client.h" -#include "caosdb/file_transmission/DownloadRequestHandler.h" // for DownloadReq... -#include "caosdb/file_transmission/UploadRequestHandler.h" // for UploadReque... -#include "caosdb/logging.h" // for CAOSDB_LOG_... -#include "caosdb/status_code.h" // for StatusCode -#include <boost/log/core/record.hpp> // for record -#include <boost/log/sources/record_ostream.hpp> // for basic_recor... -#include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SE... -#include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SE... -#include <exception> // IWYU pragma: keep -// IWYU pragma: no_include <bits/exception.h> -#include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQ... - -namespace caosdb::transaction { -using caosdb::StatusCode; - -FileExchangeClient::~FileExchangeClient() { - this->Cancel(); - - cq_.Shutdown(); - - // drain the queue - void *ignoredTag = nullptr; - bool ok = false; - while (cq_.Next(&ignoredTag, &ok)) { - ; - } -} - -StatusCode FileExchangeClient::upload(const FileDescriptor &file_descriptor) { - handler_ = std::make_unique<UploadRequestHandler>(&handler_, stub_.get(), - &cq_, file_descriptor); - - int status = this->processMessages(); - if (status > 0) { - return StatusCode::FILE_UPLOAD_ERROR; - } - return StatusCode::SUCCESS; -} - -StatusCode FileExchangeClient::download(const FileDescriptor &file_descriptor) { - handler_ = std::make_unique<DownloadRequestHandler>(&handler_, stub_.get(), - &cq_, file_descriptor); - - int status = this->processMessages(); - if (status > 0) { - return StatusCode::FILE_DOWNLOAD_ERROR; - } - return StatusCode::SUCCESS; -} - -void FileExchangeClient::Cancel() { - if (handler_) { - handler_->Cancel(); - } -} - -int FileExchangeClient::processMessages() { - try { - handler_->Start(); - void *tag = nullptr; - bool ok = false; - while (true) { - if (cq_.Next(&tag, &ok)) { - if (tag != nullptr) { - // TODO(tf): assert - auto res = handler_->OnNext(ok); - if (!res) { - // TODO(tf): comment - handler_.reset(); - break; - } - } else { - CAOSDB_LOG_ERROR(logger_name) - << "Invalid tag delivered by notification queue."; - } - } else { - CAOSDB_LOG_ERROR(logger_name) - << "Notification queue has been shut down unexpectedly."; - return 1; - } - } - } catch (std::exception &e) { - CAOSDB_LOG_ERROR(logger_name) << "Caught exception: " << e.what(); - return 1; - } catch (...) { - CAOSDB_LOG_ERROR(logger_name) << "Caught unknown exception."; - return 1; - } - return 0; -} - -} // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/FileReader.cpp b/src/caosdb/file_transmission/FileReader.cpp deleted file mode 100644 index 5124846c5f993fa3311c72f3445f53ea5482bba7..0000000000000000000000000000000000000000 --- a/src/caosdb/file_transmission/FileReader.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "caosdb/file_transmission/FileReader.h" -#include "caosdb/file_transmission/FileError.h" // for FileIOError, FileLockError -#include <boost/filesystem/path.hpp> // for path -#include <mutex> // for try_to_lock -#include <utility> // for move - -namespace caosdb::transaction { - -FileReader::FileReader(boost::filesystem::path filename) - : filename_(std::move(filename)), size_(0) { - this->openFile(); -} - -FileReader::FileReader(boost::filesystem::path filename, - std::shared_ptr<FileMutex> mutexPtr) - : filename_(std::move(filename)), size_(0), mutexPtr_(std::move(mutexPtr)) { - this->openFile(); -} - -void FileReader::openFile() { - if (mutexPtr_) { - lock_ = FileReadLock(*mutexPtr_, std::try_to_lock); - if (!lock_) { - throw FileLockError("Can't lock file for reading: " + filename_.string()); - } - } - - stream_.open(filename_, std::ios::binary | std::ios::ate); - if (!stream_) { - throw FileIOError("Can't open file for reading: " + filename_.string()); - } - - auto size = stream_.tellg(); - stream_.seekg(0); - if (size > 0) { - size_ = static_cast<decltype(size_)>(size); - } -} - -std::size_t FileReader::read(std::string &buffer) { - std::size_t bytesRead = 0; - - if (!stream_.eof()) { - auto bufferSize = buffer.size(); - if (bufferSize > 0) { - if (!stream_.read(&buffer[0], bufferSize)) { - throw FileIOError("Can't read file: " + filename_.string()); - } - - bytesRead = static_cast<std::size_t>(stream_.gcount()); - } - } - - return bytesRead; -} - -} // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/FileWriter.cpp b/src/caosdb/file_transmission/FileWriter.cpp deleted file mode 100644 index 3d89c1c6f2343ca5a39a167ad2dc88ff5a4e3aa2..0000000000000000000000000000000000000000 --- a/src/caosdb/file_transmission/FileWriter.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "caosdb/file_transmission/FileWriter.h" -#include "caosdb/file_transmission/FileError.h" // for FileIOError, FileLockError -#include <boost/filesystem/path.hpp> // for path -#include <mutex> // for try_to_lock -#include <utility> // for move - -namespace caosdb::transaction { - -FileWriter::FileWriter(boost::filesystem::path filename) - : filename_(std::move(filename)) { - this->openFile(); -} - -FileWriter::FileWriter(boost::filesystem::path filename, - std::shared_ptr<FileMutex> mutexPtr) - : filename_(std::move(filename)), mutexPtr_(std::move(mutexPtr)) { - this->openFile(); -} - -void FileWriter::openFile() { - if (mutexPtr_) { - lock_ = FileWriteLock(*mutexPtr_, std::try_to_lock); - if (!lock_) { - throw FileLockError("Can't lock file for writing: " + filename_.string()); - } - } - - stream_.open(filename_, std::ios::binary | std::ios::trunc); - if (!stream_) { - throw FileIOError("Can't open file for writing: " + filename_.string()); - } -} - -void FileWriter::write(const std::string &buffer) { - auto bufferSize = buffer.size(); - if (bufferSize > 0) { - if (!stream_.write(buffer.data(), bufferSize)) { - throw FileIOError("Can't write file: " + filename_.string()); - } - } -} - -} // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/DownloadRequestHandler.cpp b/src/caosdb/file_transmission/download_request_handler.cpp similarity index 57% rename from src/caosdb/file_transmission/DownloadRequestHandler.cpp rename to src/caosdb/file_transmission/download_request_handler.cpp index 87730febcf8589f30639123a18a65d60df05de90..fb36ca5b46cbf2c4f08c2c06bc9faf6b00e038be 100644 --- a/src/caosdb/file_transmission/DownloadRequestHandler.cpp +++ b/src/caosdb/file_transmission/download_request_handler.cpp @@ -1,8 +1,56 @@ -#include "caosdb/file_transmission/DownloadRequestHandler.h" -#include "caosdb/exceptions.h" // for Exception +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#include "caosdb/file_transmission/download_request_handler.h" #include "caosdb/logging.h" // for CAOSDB_LOG_TRACE #include "caosdb/protobuf_helper.h" // for get_arena #include "caosdb/status_code.h" // for GENERIC_RPC_E... +#include "caosdb/transaction_status.h" // for TransactionStatus #include <boost/filesystem/path.hpp> // for operator<<, path #include <boost/log/core/record.hpp> // for record #include <boost/log/detail/attachable_sstream_buf.hpp> // for basic_ostring... @@ -24,9 +72,6 @@ namespace caosdb::transaction { using caosdb::StatusCode; -using caosdb::exceptions::AuthenticationError; -using caosdb::exceptions::ConnectionError; -using caosdb::exceptions::Exception; using caosdb::utility::get_arena; using google::protobuf::Arena; @@ -50,7 +95,7 @@ bool DownloadRequestHandler::OnNext(bool ok) { this->handleReceivingFileState(); } else if (state_ == CallState::CallComplete) { this->handleCallCompleteState(); - return false; // TODO(tf): comment + return false; } } else { state_ = CallState::CallComplete; @@ -58,19 +103,20 @@ bool DownloadRequestHandler::OnNext(bool ok) { } return true; - } catch (Exception &e) { - throw; } catch (std::exception &e) { - CAOSDB_LOG_ERROR(logger_name) << "Download processing error: " << e.what(); - throw; + CAOSDB_LOG_ERROR(logger_name) + << "DownloadRequestHandler caught an exception: " << e.what(); + transaction_status = TransactionStatus::GENERIC_ERROR(e.what()); + state_ = CallState::CallComplete; } catch (...) { CAOSDB_LOG_ERROR(logger_name) - << "Download processing error: unknown exception caught"; - throw; + << "Transaction error: unknown exception caught"; + transaction_status = TransactionStatus::GENERIC_ERROR( + "DownloadRequestHandler caught an unknown exception"); + state_ = CallState::CallComplete; } if (state_ == CallState::NewCall) { - // TODO(tf): comment return false; } @@ -93,6 +139,7 @@ void DownloadRequestHandler::handleNewCallState() { rpc_ = stub_->PrepareAsyncFileDownload(&ctx_, *request_, cq_); + transaction_status = TransactionStatus::EXECUTING(); state_ = CallState::SendingRequest; rpc_->StartCall(tag_); CAOSDB_LOG_TRACE(logger_name) @@ -133,22 +180,26 @@ void DownloadRequestHandler::handleReceivingFileState() { void DownloadRequestHandler::handleCallCompleteState() { CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleCallCompleteState"; + switch (status_.error_code()) { - case grpc::OK: - CAOSDB_LOG_INFO(logger_name) << "[" << file_descriptor_.local_path - << "]: download complete: " << bytesReceived_ - << " bytes received" << std::endl; - break; - - case grpc::UNAUTHENTICATED: - throw AuthenticationError(status_.error_message()); - case grpc::UNAVAILABLE: - throw ConnectionError(status_.error_message()); - default: - throw Exception(StatusCode::GENERIC_RPC_ERROR, - "GRPC error code " + std::to_string(status_.error_code()) + - " - " + status_.error_message()); + case grpc::OK: { + CAOSDB_LOG_INFO(logger_name) + << "DownloadRequestHandler finished successfully (" + << file_descriptor_.local_path << "): Download complete, " + << bytesReceived_ << " bytes received."; + } break; + default: { + auto code(static_cast<StatusCode>(status_.error_code())); + std::string description(get_status_description(code) + + " Original message: " + status_.error_message()); + transaction_status = TransactionStatus(code, description); + CAOSDB_LOG_ERROR(logger_name) + << "DownloadRequestHandler finished with an error (" + << file_descriptor_.local_path << "): Download aborted with code " << code + << " - " << description; + } break; } + CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleCallCompleteState"; } diff --git a/src/caosdb/file_transmission/file_reader.cpp b/src/caosdb/file_transmission/file_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2df58c9accbde99c9bc908ed7f80ceef7685b573 --- /dev/null +++ b/src/caosdb/file_transmission/file_reader.cpp @@ -0,0 +1,91 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#include "caosdb/file_transmission/file_reader.h" +#include "caosdb/file_transmission/file_error.h" // for FileIOError +#include <boost/filesystem/path.hpp> // for path +#include <utility> // for move + +namespace caosdb::transaction { + +FileReader::FileReader(boost::filesystem::path filename) + : filename_(std::move(filename)), size_(0) { + this->openFile(); +} + +void FileReader::openFile() { + stream_.open(filename_, std::ios::binary | std::ios::ate); + if (!stream_) { + throw FileIOError("Can't open file for reading: " + filename_.string()); + } + + auto size = stream_.tellg(); + stream_.seekg(0); + if (size > 0) { + size_ = static_cast<decltype(size_)>(size); + } +} + +std::size_t FileReader::read(std::string &buffer) { + std::size_t bytesRead = 0; + + if (!stream_.eof()) { + auto bufferSize = buffer.size(); + if (bufferSize > 0) { + if (!stream_.read(&buffer[0], bufferSize)) { + throw FileIOError("Can't read file: " + filename_.string()); + } + + bytesRead = static_cast<std::size_t>(stream_.gcount()); + } + } + + return bytesRead; +} + +} // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/file_writer.cpp b/src/caosdb/file_transmission/file_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73b604d4255b213d015e010ea987fdb6a9918f6c --- /dev/null +++ b/src/caosdb/file_transmission/file_writer.cpp @@ -0,0 +1,77 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#include "caosdb/file_transmission/file_writer.h" +#include "caosdb/file_transmission/file_error.h" // for FileIOError +#include <boost/filesystem/path.hpp> // for path +#include <utility> // for move + +namespace caosdb::transaction { + +FileWriter::FileWriter(boost::filesystem::path filename) + : filename_(std::move(filename)) { + this->openFile(); +} + +void FileWriter::openFile() { + stream_.open(filename_, std::ios::binary | std::ios::trunc); + if (!stream_) { + throw FileIOError("Can't open file for writing: " + filename_.string()); + } +} + +void FileWriter::write(const std::string &buffer) { + auto bufferSize = buffer.size(); + if (bufferSize > 0) { + if (!stream_.write(buffer.data(), bufferSize)) { + throw FileIOError("Can't write file: " + filename_.string()); + } + } +} + +} // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/register_file_upload_handler.cpp b/src/caosdb/file_transmission/register_file_upload_handler.cpp index 2661756cdc565516a7ec6dfa74fde36bf2f1cc7e..b2020223f1c79f69e77b1e0950bac1c8f1220986 100644 --- a/src/caosdb/file_transmission/register_file_upload_handler.cpp +++ b/src/caosdb/file_transmission/register_file_upload_handler.cpp @@ -1,3 +1,51 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ #include "caosdb/file_transmission/register_file_upload_handler.h" #include "caosdb/logging.h" // for CAOSDB_LOG_TRACE #include <boost/log/core/record.hpp> // for record @@ -33,6 +81,4 @@ void RegisterFileUploadHandler::handleNewCallState() { << "Leave RegisterFileUploadHandler::handleNewCallState"; } -void RegisterFileUploadHandler::handleReceivingFileState() {} - } // namespace caosdb::transaction diff --git a/src/caosdb/file_transmission/UploadRequestHandler.cpp b/src/caosdb/file_transmission/upload_request_handler.cpp similarity index 56% rename from src/caosdb/file_transmission/UploadRequestHandler.cpp rename to src/caosdb/file_transmission/upload_request_handler.cpp index c93ca3ab29d36bc752fb0bf5dae733b07e0bbeff..cffe7577be41229110b1f6467615bf62cc629fa7 100644 --- a/src/caosdb/file_transmission/UploadRequestHandler.cpp +++ b/src/caosdb/file_transmission/upload_request_handler.cpp @@ -1,8 +1,56 @@ -#include "caosdb/file_transmission/UploadRequestHandler.h" -#include "caosdb/exceptions.h" // for Exception +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ +#include "caosdb/file_transmission/upload_request_handler.h" #include "caosdb/logging.h" // for CAOSDB_LOG_ERROR #include "caosdb/protobuf_helper.h" // for get_arena #include "caosdb/status_code.h" // for GENERIC_RPC_E... +#include "caosdb/transaction_status.h" // for TransactionStatus #include <algorithm> // for min #include <boost/filesystem/path.hpp> // for operator<<, path #include <boost/log/core/record.hpp> // for record @@ -27,9 +75,6 @@ namespace caosdb::transaction { using caosdb::StatusCode; -using caosdb::exceptions::AuthenticationError; -using caosdb::exceptions::ConnectionError; -using caosdb::exceptions::Exception; using caosdb::utility::get_arena; using google::protobuf::Arena; @@ -47,7 +92,7 @@ bool UploadRequestHandler::OnNext(bool ok) { try { if (state_ == CallState::CallComplete) { this->handleCallCompleteState(); - return false; // TODO(tf): comment + return false; } else if (ok) { if (state_ == CallState::NewCall) { this->handleNewCallState(); @@ -64,17 +109,20 @@ bool UploadRequestHandler::OnNext(bool ok) { } return true; - } catch (Exception &e) { - throw; } catch (std::exception &e) { - CAOSDB_LOG_ERROR(logger_name) << "Upload processing error: " << e.what(); + CAOSDB_LOG_ERROR(logger_name) + << "UploadRequestHandler caught an exception: " << e.what(); + transaction_status = TransactionStatus::GENERIC_ERROR(e.what()); + state_ = CallState::CallComplete; } catch (...) { CAOSDB_LOG_ERROR(logger_name) - << "Upload processing error: unknown exception caught"; + << "Transaction error: unknown exception caught"; + transaction_status = TransactionStatus::GENERIC_ERROR( + "UploadRequestHandler caught an unknown exception"); + state_ = CallState::CallComplete; } if (state_ == CallState::NewCall) { - // TODO(tf): comment return false; } @@ -91,6 +139,7 @@ void UploadRequestHandler::handleNewCallState() { rpc_ = stub_->PrepareAsyncFileUpload(&ctx_, response_, cq_); + transaction_status = TransactionStatus::EXECUTING(); state_ = CallState::SendingHeader; rpc_->StartCall(tag_); } @@ -139,21 +188,31 @@ void UploadRequestHandler::handleExpectingResponseState() { } void UploadRequestHandler::handleCallCompleteState() { + CAOSDB_LOG_TRACE(logger_name) + << "Enter UploadRequestHandler::handleCallCompleteState"; + switch (status_.error_code()) { case grpc::OK: { - auto bytesSent = fileReader_ ? fileReader_->fileSize() : 0; + auto bytesSent = fileReader_ != nullptr ? fileReader_->fileSize() : 0; CAOSDB_LOG_INFO(logger_name) - << "[" << file_descriptor_.local_path - << "]: upload complete: " << bytesSent << " bytes sent" << std::endl; + << "UploadRequestHandler finished successfully (" + << file_descriptor_.local_path << "): upload complete, " << bytesSent + << " bytes sent"; + } break; + default: { + auto code(static_cast<StatusCode>(status_.error_code())); + std::string description(get_status_description(code) + + " Original message: " + status_.error_message()); + transaction_status = TransactionStatus(code, description); + CAOSDB_LOG_ERROR(logger_name) + << "UploadRequestHandler finished with an error (" + << file_descriptor_.local_path << "): Upload aborted with code " << code + << " - " << description; } break; - - case grpc::UNAUTHENTICATED: - throw AuthenticationError(status_.error_message()); - case grpc::UNAVAILABLE: - throw ConnectionError(status_.error_message()); - default: - throw Exception(StatusCode::GENERIC_RPC_ERROR, status_.error_message()); } + + CAOSDB_LOG_TRACE(logger_name) + << "Leave UploadRequestHandler::handleCallCompleteState"; } } // namespace caosdb::transaction diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 214e0a76ff20fc11c7beb32c4461a6603ca811ba..2bb5b34f8ad0ec8a79b62c730c3d68ab50bdf188 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -20,11 +20,12 @@ #include "caosdb/transaction.h" #include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransac... #include "caosdb/entity/v1alpha1/main.pb.h" // for TransactionRe... -#include "caosdb/file_transmission/Client.h" // for FileExchangeC... +#include "caosdb/file_transmission/download_request_handler.h" // Download... +#include "caosdb/file_transmission/file_reader.h" // for path #include "caosdb/file_transmission/register_file_upload_handler.h" -#include "caosdb/logging.h" // for CAOSDB_LOG_FATAL -#include "caosdb/protobuf_helper.h" // for get_arena -#include "caosdb/status_code.h" // for StatusCode +#include "caosdb/file_transmission/upload_request_handler.h" // Upload... +#include "caosdb/logging.h" // for CAOSDB_LOG_FATAL +#include "caosdb/status_code.h" // for StatusCode #include "caosdb/transaction_handler.h" #include <algorithm> // for max #include <boost/filesystem/path.hpp> // for operator<<, path @@ -285,7 +286,6 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { CAOSDB_LOG_INFO(logger_name) << "Number of files to be uploaded: " << upload_files.size(); - // TODO(tf): Use Arena auto *registration_request = Arena::CreateMessage<RegisterFileUploadRequest>(GetArena()); auto *registration_response = @@ -302,15 +302,15 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { return StatusCode::EXECUTING; } - FileExchangeClient upload_client(file_service); - for (auto file_descriptor : upload_files) { + for (auto &file_descriptor : upload_files) { file_descriptor.file_transmission_id->set_registration_id( registration_response->registration_id()); CAOSDB_LOG_INFO(logger_name) << "Uploading " << file_descriptor.local_path; - auto file_upload_status = upload_client.upload(file_descriptor); - if (file_upload_status != StatusCode::SUCCESS) { - this->status = TransactionStatus::FILE_UPLOAD_ERROR(); + handler_ = std::make_unique<UploadRequestHandler>( + &handler_, file_service.get(), &completion_queue, file_descriptor); + this->status = ProcessCalls(); + if (this->status.GetCode() != StatusCode::EXECUTING) { return StatusCode::EXECUTING; } } @@ -319,12 +319,13 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { CAOSDB_LOG_DEBUG(logger_name) << "RPC Request: " << RequestToString(); handler_ = std::make_unique<EntityTransactionHandler>( &handler_, entity_service.get(), &completion_queue, request, response); - this->status = ProcessCalls(); - CAOSDB_LOG_DEBUG(logger_name) << "RPC Response: " << ResponseToString(); + if (this->status.GetCode() != StatusCode::EXECUTING) { + return StatusCode::EXECUTING; + } // file download afterwards - if (status.GetCode() == StatusCode::SUCCESS && !download_files.empty()) { + if (status.GetCode() == StatusCode::EXECUTING && !download_files.empty()) { // run over all retrieved entities and get the download_id for (auto sub_response : *(response->mutable_responses())) { if (sub_response.transaction_response_case() == @@ -342,15 +343,15 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { } } - FileExchangeClient download_client(file_service); for (const auto &item : download_files) { auto file_descriptor(item.second); - CAOSDB_DEBUG_MESSAGE_STRING(*file_descriptor.file_transmission_id, out) CAOSDB_LOG_INFO(logger_name) - << "Downloading " << file_descriptor.local_path << ", " << out; - auto file_download_status = download_client.download(file_descriptor); - if (file_download_status != StatusCode::SUCCESS) { - this->status = TransactionStatus::FILE_DOWNLOAD_ERROR(); + << "Downloading " << file_descriptor.local_path; + + handler_ = std::make_unique<DownloadRequestHandler>( + &handler_, file_service.get(), &completion_queue, file_descriptor); + this->status = ProcessCalls(); + if (this->status.GetCode() != StatusCode::EXECUTING) { return StatusCode::EXECUTING; } } @@ -359,6 +360,10 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { } auto Transaction::WaitForIt() const noexcept -> TransactionStatus { + if (this->status.GetCode() != StatusCode::EXECUTING) { + return this->status; + } + this->status = TransactionStatus::SUCCESS(); bool set_error = false; auto *responses = this->response->mutable_responses(); std::vector<std::unique_ptr<Entity>> entities; diff --git a/src/caosdb/transaction_handler.cpp b/src/caosdb/transaction_handler.cpp index 8e3f1388c47121da0b0dd6de49c00eb174251d89..cf020af35bf56b2e68da11a92b0961995397f2fd 100644 --- a/src/caosdb/transaction_handler.cpp +++ b/src/caosdb/transaction_handler.cpp @@ -37,8 +37,4 @@ void EntityTransactionHandler::handleNewCallState() { << "Leave EntityTransactionHandler::handleNewCallState"; } -void EntityTransactionHandler::handleReceivingFileState() { - // TODO(tf) remove -} - } // namespace caosdb::transaction diff --git a/src/caosdb/unary_rpc_handler.cpp b/src/caosdb/unary_rpc_handler.cpp index b41c13af66cff101fc91fa0ee1d283ffc0289483..4d1e1cf618ef119278b02fdc3657d17482a87601 100644 --- a/src/caosdb/unary_rpc_handler.cpp +++ b/src/caosdb/unary_rpc_handler.cpp @@ -1,3 +1,51 @@ +/* + * 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/>. + * + ********************************************************************************* + * + * This is derived work which is heavily based on + * https://github.com/NeiRo21/grpcpp-bidi-streaming, Commit + * cd9cb78e5d6d72806c2ec4c703e5e856b223dc96, Aug 10, 2020 + * + * The orginal work is licensed as + * + * > MIT License + * > + * > Copyright (c) 2019 NeiRo21 + * > + * > Permission is hereby granted, free of charge, to any person obtaining a + * > copy of this software and associated documentation files (the "Software"), + * > to deal in the Software without restriction, including without limitation + * > the rights to use, copy, modify, merge, publish, distribute, sublicense, + * > and/or sell copies of the Software, and to permit persons to whom the + * > Software is furnished to do so, subject to the following conditions: + * > + * > The above copyright notice and this permission notice shall be included in + * > all copies or substantial portions of the Software. + * > + * > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * > DEALINGS IN THE SOFTWARE. + */ #include "caosdb/unary_rpc_handler.h" #include "caosdb/logging.h" // for CAOSDB_LOG_TRACE #include "caosdb/status_code.h" // for GENERIC_RPC_E... @@ -21,8 +69,6 @@ bool UnaryRpcHandler::OnNext(bool ok) { if (ok) { if (state_ == CallState::NewCall) { this->handleNewCallState(); - } else if (state_ == CallState::ReceivingFile) { - this->handleReceivingFileState(); } else if (state_ == CallState::CallComplete) { this->handleCallCompleteState(); return false; @@ -69,7 +115,6 @@ void UnaryRpcHandler::handleCallCompleteState() { switch (status_.error_code()) { case grpc::OK: - transaction_status = TransactionStatus::SUCCESS(); CAOSDB_LOG_INFO(logger_name) << "UnaryRpcHandler finished successfully."; break; default: diff --git a/test/test_file_transmission.cpp b/test/test_file_transmission.cpp index c5afd8741d9803a9899a229c12d53f71a266317e..801b89db3a07f5b96e530cfbdfc8335c892a1331 100644 --- a/test/test_file_transmission.cpp +++ b/test/test_file_transmission.cpp @@ -1,5 +1,24 @@ -#include "caosdb/file_transmission/FileWriter.h" -#include "caosdb/file_transmission/FileReader.h" +/* + * 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/file_transmission/file_writer.h" +#include "caosdb/file_transmission/file_reader.h" #include <boost/filesystem/operations.hpp> // for exists, file_size, remove #include <boost/filesystem/path.hpp> // for path #include <boost/filesystem/path_traits.hpp> // for filesystem