diff --git a/.cspell/words.txt b/.cspell/words.txt index 35f9955b..fefbc103 100644 --- a/.cspell/words.txt +++ b/.cspell/words.txt @@ -26,6 +26,7 @@ cppvsdbg create_notraverse crypto_aead_xchacha20poly1305_ietf_npubbytes cstdint +curlopt_aws_sigv4 cxxflags cxxstd d_largefile64_source @@ -127,6 +128,7 @@ libcurl libdsm libevent libexample +libexpat libfuse3 libgmock libgtest @@ -139,10 +141,12 @@ libuuid libuuid_include_dirs libvlc linkflags +localappdata lptr lpwstr markdownlint mbig +minio msvc msvcr120 msys2 @@ -154,6 +158,7 @@ nlohmann_json nmakeprg nominmax ntstatus +nullptr nuspell_version oleaut32 openal_version @@ -198,6 +203,7 @@ stduuid_project strequal ularge_integer uring +url userenv utimens_impl utimensat diff --git a/CHANGELOG.md b/CHANGELOG.md index 389269a0..d48fc15b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,37 @@ # Changelog +## v2.0.3-rc + +### Issues + +* \#28 \[bug\] Address slow directory responses in S3 mounts for deeply nested directories +* \#29 \[bug\] S3 error responses are not being logged +* \#30 \[bug\] Sia provider error responses are not logged +* \#31 \[bug\] S3 provider should limit max key size to 1024 + +### Changes from v2.0.2-rc + +* Always use direct for read-only providers +* Fixed externally removed files not being processed during cleanup +* Fixed http headers not being added for requests +* Fixed incorrect `stat` values for remote mounts +* Fixed invalid directory nullptr error on remote mounts +* Fixed memory leak in event system +* Refactored application shutdown +* Refactored event system +* Updated build system to Alpine 3.21.0 +* Updated build system to MinGW-w64 12.0.0 +* Updated copyright to 2018-2025 + ## v2.0.2-rc ### BREAKING CHANGES * Refactored `config.json` - will need to verify configuration settings prior to mounting + ### Issues -* \#12 \[Unit Test\] Complete all providers unit tests * \#14 \[Unit Test\] SQLite mini-ORM unit tests and cleanup * \#16 Add support for bucket name in Sia provider * \#17 Update to common c++ build system diff --git a/CMakeLists.txt b/CMakeLists.txt index dd48d67d..ec98d7be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,10 @@ cmake_minimum_required(VERSION 3.27) cmake_policy(SET CMP0135 NEW) cmake_policy(SET CMP0144 NEW) +if (NOT PROJECT_INTERFACE) + message(FATAL_ERROR "Project must be compiled via 'make_win32.cmd'/'make_win32.sh' or 'make_unix.sh' build scripts. Invoking 'cmake' directly is not supported.") +endif() + project(${PROJECT_NAME} DESCRIPTION ${PROJECT_DESC} HOMEPAGE_URL ${PROJECT_URL} @@ -158,6 +162,7 @@ endif() -DPROJECT_FUSE=${PROJECT_FUSE} -DPROJECT_FUSE_INCLUDE_DIRS=${PROJECT_FUSE_INCLUDE_DIRS} -DPROJECT_GIT_REV=${PROJECT_GIT_REV} + -DPROJECT_INTERFACE=1 -DPROJECT_IS_ALPINE=${PROJECT_IS_ALPINE} -DPROJECT_IS_ARM64=${PROJECT_IS_ARM64} -DPROJECT_IS_MINGW=${PROJECT_IS_MINGW} diff --git a/LICENSE.md b/LICENSE.md index 77a53a10..f15323a8 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,5 +1,5 @@ # Repertory MIT License -### Copyright <2018-2024> +### Copyright <2018-2025> 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: diff --git a/README.md b/README.md index 41b1e5e3..e4f83697 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,22 @@ # Repertory -Repertory allows you to mount AWS S3 and Sia via FUSE on Linux ~~/OS X~~ or via WinFSP +Repertory allows you to mount S3 and Sia via FUSE on Linux or via WinFSP on Windows. ## Details and Features * Optimized for [Plex Media Server](https://www.plex.tv/) -* Single application to mount AWS S3 and/or Sia -* Remote mounting of Repertory instances on Linux ~~, OS X~~ and Windows - * Securely share your mounts over TCP/IP (`XChaCha20-Poly1305` stream cipher) -* Cross-platform support (Linux 64-bit, Linux arm64/aarch64, ~~OS X,~~ Windows 64-bit) +* Single application to mount S3 and/or Sia +* Remote mounting of Repertory instances on Linux and Windows + * Securely share your mounts over TCP/IP via `XChaCha20-Poly1305` with other systems on your network or over the internet. +* Cross-platform support (Linux 64-bit, Linux arm64/aarch64, Windows 64-bit) +* Optionally encrypt file names and file data via `XChaCha20-Poly1305` in S3 mounts ## Minimum Requirements * [Sia renterd](https://github.com/SiaFoundation/renterd/releases) v0.4.0+ for Sia support * Only 64-bit operating systems are supported * By default, Linux requires `fusermount3`; otherwise, `repertory` must be manually compiled with `libfuse2` support - * ~~OS X requires the following dependency to be installed:~~ - * ~~[FUSE for macOS v4.5.0](https://github.com/osxfuse/osxfuse/releases/download/macfuse-4.5.0/macfuse-4.5.0.dmg)~~ * Windows requires the following dependencies to be installed: * [WinFSP 2023](https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi) @@ -25,47 +24,103 @@ on Windows. * Linux `arm64/aarch64` * Linux `amd64` -* ~~OS X Mojave and above~~ * Windows 64-bit 10, 11 ## Usage +### Sia + +* Initial Configuration + * Sia steps: + * Set the appropriate bucket name and `renterd` API password in `repertory` configuration: + * To use `default` as the bucket name and configuration name: + * `repertory -set HostConfig.ApiPassword ''` + * To use a different bucket name with `default` as the configuration name: + * `repertory -set HostConfig.ApiPassword ''` + * `repertory -set SiaConfig.Bucket ''` + * For all other configurations: + * `repertory --name '' -set HostConfig.ApiPassword ''` + * `repertory --name '' -set SiaConfig.Bucket ''` + * To verify/view all configuration options: + * `repertory -dc` + * `repertory --name '' -dc` + * Example: + * `repertory --name default -dc` +* Mounting on Linux: + * `repertory /mnt/location` + * `repertory --name '' /mnt/location` + * Example: + * `repertory --name default /mnt/location` +* Mounting on Windows: + * `repertory t:` + * `repertory --name '' t:` + * Example: + * `repertory --name default t:` + +### S3 + +* Initial Configuration + * S3 steps: + * Set the appropriate base URL: + * `repertory -s3 --name '' -set S3Config.URL ''` + * Example: + * `repertory -s3 --name minio -set S3Config.URL 'http://localhost:9000'` + * Set the appropriate bucket name: + * `repertory -s3 --name '' -set S3Config.Bucket ''` + * Set the appropriate access key: + * `repertory -s3 --name '' -set S3Config.AccessKey ''` + * Set the appropriate secret key: + * `repertory -s3 --name '' -set S3Config.SecretKey ''` + * For Sia and most local S3 gateway instances, enable path style URL's: + * `repertory -s3 --name '' -set S3Config.UsePathStyle true` + * Optional steps: + * Set an appropriate region. Default is set to `any`: + * `repertory -s3 --name '' -set S3Config.Region ''` + * Enable encrypted file names and file data. Set a strong, random encryption token and be sure to store it in a secure backup location: + * `repertory -s3 --name '' -set S3Config.EncryptionToken ''` + * To verify/view all configuration options: + * `repertory -s3 --name '' -dc` + * Example: + * `repertory -s3 --name minio -dc` +* Mounting on Linux: + * `repertory -s3 --name '' /mnt/location` + * Example: + * `repertory -s3 --name minio /mnt/location` +* Mounting on Windows: + * `repertory -s3 --name '' t:` + * Example: + * `repertory -s3 --name minio t:` + ### Notable Options -* `-dc` - * Display mount configuration. - * For Sia, `--name` is optional - * For S3, the `-s3` option is required along with `--name` * `--help` - * Display all mount utility options. + * Display all mount utility options * `--name, -na [name]` * The `--name` option can be set to any valid value allowed as a file name for your filesystem. * For Sia, the bucket name will be set to the same value if it is empty in the configuration file. * If the `--name` option is not specified, `default` will be used. * For S3, the `--name` option is required and does not affect the bucket name. -* `-set SiaConfig.Bucket` - * Set Sia bucket name for the mount. - * Can be used in combination with `--name` to target a unique configuration. -* `-set S3Config.Bucket` - * S3 bucket name for the mount. - * Must be used in combination with `--name` to target a unique configuration. - * Must be used in combination with `-s3`. +* `-dc` + * Display mount configuration + * For Sia, `--name` is optional + * For S3, the `-s3` option is required along with `--name` -### Sia +### Data Directories * Linux - * `repertory /mnt/location` - * `repertory --name default /mnt/location` + * `~/.local/repertory2` * Windows - * `repertory.exe t:` - * `repertory.exe --name default t:` + * `%LOCALAPPDATA%\repertory2` + * Example: + * `C:\Users\Tom\AppData\Local\repertory2` + * IMPORTANT: + * It is highly recommended to exclude this folder from any anti-virus/anti-malware applications as severe performance issues may arise. + * Excluding the mounted drive letter is also highly recommended. -### S3 +## Remote Mounting -* Linux - * `repertory --name storj -s3 /mnt/location` -* Windows - * `repertory.exe --name storj -s3 t:` +`Repertory` allows local mounts to be shared with other computers on your network. +This option is referred to as remote mounting. Instructions TBD. ## Compiling @@ -94,17 +149,26 @@ on Windows. ## Credits +* [binutils](https://www.gnu.org/software/binutils/) * [boost c++ libraries](https://www.boost.org/) * [cpp-httplib](https://github.com/yhirose/cpp-httplib) * [curl](https://curl.haxx.se/) -* ~~[FUSE for macOS](https://osxfuse.github.io/)~~ +* [docker](https://www.docker.com/) * [Google Test](https://github.com/google/googletest) +* [ICU](https://icu.unicode.org/) * [JSON for Modern C++](https://github.com/nlohmann/json) +* [libexpat](https://github.com/libexpat/libexpat) * [libfuse](https://github.com/libfuse/libfuse) * [libsodium](https://doc.libsodium.org/) +* [mingw-w64](https://www.mingw-w64.org/) +* [MSYS2](https://www.msys2.org) * [OpenSSL](https://www.openssl.org/) +* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) +* [pugixml](https://pugixml.org/) +* [RocksDB](https://rocksdb.org) * [ScPrime](https://scpri.me/) * [Sia Decentralized Cloud Storage](https://sia.tech/) +* [spdlog](https://github.com/gabime/spdlog) * [SQLite](https://www.sqlite.org) * [stduuid](https://github.com/mariusbancila/stduuid) * [Storj](https://storj.io/) diff --git a/cmake/hashes.cmake b/cmake/hashes.cmake index 096bfdd8..9fbd0b43 100644 --- a/cmake/hashes.cmake +++ b/cmake/hashes.cmake @@ -1,15 +1,15 @@ -set(BINUTILS_HASH ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450) -set(BOOST_HASH f55c340aa49763b1925ccf02b2e83f35fdcf634c9d5164a2acb87540173c741d) +set(BINUTILS_HASH b53606f443ac8f01d1d5fc9c39497f2af322d99e14cea5c0b4b124d630379365) set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca) +set(BOOST_HASH f55c340aa49763b1925ccf02b2e83f35fdcf634c9d5164a2acb87540173c741d) set(CPP_HTTPLIB_HASH 405abd8170f2a446fc8612ac635d0db5947c0d2e156e32603403a4496255ff00) set(CURL_HASH 5a231145114589491fc52da118f9c7ef8abee885d1cb1ced99c7290e9a352f07) set(EXPAT_HASH 372b18f6527d162fa9658f1c74d22a37429b82d822f5a1e1fc7e00f6045a06a2) set(GCC_HASH 7d376d445f93126dc545e2c0086d0f647c3094aae081cdb78f42ce2bc25e7293) set(GTEST_HASH 7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926) -set(ICU_HASH 925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e) +set(ICU_HASH a2c443404f00098e9e90acf29dc318e049d2dc78d9ae5f46efb261934a730ce2) set(JSON_HASH 0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406) set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1) -set(MINGW_HASH 3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10) +set(MINGW_HASH 30e5aad2c48dd318150f79cff47661232c4175876d6b4d6b270961cf2b49a48b) set(OPENSSL_HASH e15dda82fe2fe8139dc2ac21a36d4ca01d5313c75f99f46c4e8a27709b7294bf) set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591) set(PUGIXML_HASH 2f10e276870c64b1db6809050a75e11a897a8d7456c4be5c6b2e35a11168a015) diff --git a/cmake/libraries/curl.cmake b/cmake/libraries/curl.cmake index f18b5208..17be921e 100644 --- a/cmake/libraries/curl.cmake +++ b/cmake/libraries/curl.cmake @@ -20,11 +20,13 @@ if(PROJECT_ENABLE_CURL) LIST_SEPARATOR | CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} - -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} - -DBUILD_STATIC_LIBS=ON -DBUILD_CURL_EXE=OFF + -DBUILD_LIBCURL_DOCS=OFF + -DBUILD_MISC_DOCS=OFF + -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_STATIC_CURL=ON -DBUILD_STATIC_LIBS=ON + -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=OFF -DCURL_CA_BUNDLE=./cacert.pem -DCURL_CA_FALLBACK=ON @@ -33,6 +35,7 @@ if(PROJECT_ENABLE_CURL) -DCURL_USE_LIBSSH2=OFF -DCURL_USE_OPENSSL=${PROJECT_ENABLE_OPENSSL} -DCURL_ZLIB=ON + -DENABLE_CURL_MANUAL=OFF -DENABLE_THREADED_RESOLVER=ON -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -DOPENSSL_USE_STATIC_LIBS=${OPENSSL_USE_STATIC_LIBS} diff --git a/cmake/versions.cmake b/cmake/versions.cmake index 4584b91f..4eddf7f5 100644 --- a/cmake/versions.cmake +++ b/cmake/versions.cmake @@ -1,28 +1,28 @@ -set(BINUTILS_VERSION 2.41) -set(BOOST2_MAJOR_VERSION 1) -set(BOOST2_MINOR_VERSION 76) -set(BOOST2_PATCH_VERSION 0) +set(BINUTILS_VERSION 2.43) set(BOOST_MAJOR_VERSION 1) set(BOOST_MINOR_VERSION 87) set(BOOST_PATCH_VERSION 0) +set(BOOST2_MAJOR_VERSION 1) +set(BOOST2_MINOR_VERSION 76) +set(BOOST2_PATCH_VERSION 0) set(CPP_HTTPLIB_VERSION 0.18.1) -set(CURL2_VERSION 8_11_0) set(CURL_VERSION 8.11.0) -set(EXPAT2_VERSION 2_6_4) +set(CURL2_VERSION 8_11_0) set(EXPAT_VERSION 2.6.4) +set(EXPAT2_VERSION 2_6_4) set(GCC_VERSION 14.2.0) set(GTEST_VERSION 1.15.2) -set(ICU_VERSION 75-1) +set(ICU_VERSION 76-1) set(JSON_VERSION 3.11.3) set(LIBSODIUM_VERSION 1.0.20) set(MESA_VERSION 23.3.3) -set(MINGW_VERSION 11.0.1) +set(MINGW_VERSION 12.0.0) set(OPENSSL_VERSION 3.4.0) set(PKG_CONFIG_VERSION 0.29.2) set(PUGIXML_VERSION 1.14) set(ROCKSDB_VERSION 9.7.4) set(SPDLOG_VERSION 1.15.0) -set(SQLITE2_VERSION 3.46.1) set(SQLITE_VERSION 3460100) +set(SQLITE2_VERSION 3.46.1) set(STDUUID_VERSION 1.2.3) set(ZLIB_VERSION 1.3.1) diff --git a/config.sh b/config.sh index 00ce1e7f..cb708ffa 100755 --- a/config.sh +++ b/config.sh @@ -5,12 +5,12 @@ PROJECT_NAME="repertory" PROJECT_COMPANY_NAME="https://git.fifthgrid.com/blockstorage" PROJECT_URL="${PROJECT_COMPANY_NAME}/repertory" -PROJECT_COPYRIGHT="Copyright <2018-2024> <${PROJECT_URL}>" +PROJECT_COPYRIGHT="Copyright <2018-2025> <${PROJECT_URL}>" PROJECT_DESC="Mount utility for Sia and S3" PROJECT_MAJOR_VERSION=2 PROJECT_MINOR_VERSION=0 -PROJECT_REVISION_VERSION=2 +PROJECT_REVISION_VERSION=3 PROJECT_RELEASE_NUM=0 PROJECT_RELEASE_ITER=rc diff --git a/docker/aarch64/alpine b/docker/aarch64/alpine index 3cd2c4b7..eac8260c 100644 --- a/docker/aarch64/alpine +++ b/docker/aarch64/alpine @@ -1,4 +1,4 @@ -FROM arm64v8/alpine:3.20.3 +FROM arm64v8/alpine:3.21.0 MAINTAINER Scott E. Graves CMD bash @@ -30,7 +30,6 @@ RUN apk add \ gflags \ gflags-dev \ git \ - gtkmm3-dev \ icu-dev \ icu-libs \ icu-static \ @@ -69,7 +68,6 @@ RUN apk add \ tcl \ tcl-dev \ texinfo \ - vlc-dev \ wget \ xz \ xz-dev \ @@ -82,3 +80,6 @@ RUN apk add \ zstd-libs \ zstd-static \ xz-static + +RUN ln -sf /usr/bin/aclocal-1.17 /usr/bin/aclocal-1.16 +RUN ln -sf /usr/bin/automake-1.17 /usr/bin/automake-1.16 diff --git a/docker/x86_64/alpine b/docker/x86_64/alpine index ac79f66b..8b3687b7 100644 --- a/docker/x86_64/alpine +++ b/docker/x86_64/alpine @@ -1,4 +1,4 @@ -FROM alpine:3.20.3 +FROM alpine:3.21.0 MAINTAINER Scott E. Graves CMD bash @@ -80,3 +80,6 @@ RUN apk add \ zstd-libs \ zstd-static \ xz-static + +RUN ln -sf /usr/bin/aclocal-1.17 /usr/bin/aclocal-1.16 +RUN ln -sf /usr/bin/automake-1.17 /usr/bin/automake-1.16 diff --git a/docker/x86_64/mingw64 b/docker/x86_64/mingw64 index 50eddf8f..0077c720 100644 --- a/docker/x86_64/mingw64 +++ b/docker/x86_64/mingw64 @@ -1,5 +1,5 @@ #comment -FROM alpine:3.20.3 +FROM alpine:3.21.0 RUN apk update RUN apk upgrade @@ -671,6 +671,8 @@ RUN if [ -f "/3rd_party/curl-${MY_CURL_VERSION}.tar.gz" ]; then \ && cd build \ && cmake .. \ -DBUILD_CURL_EXE=ON \ + -DBUILD_LIBCURL_DOCS=OFF \ + -DBUILD_MISC_DOCS=OFF \ -DBUILD_SHARED_LIBS=OFF \ -DBUILD_STATIC_LIBS=ON \ -DBUILD_TESTING=OFF \ @@ -684,6 +686,7 @@ RUN if [ -f "/3rd_party/curl-${MY_CURL_VERSION}.tar.gz" ]; then \ -DCURL_USE_LIBSSH2=OFF \ -DCURL_USE_OPENSSL=ON \ -DCURL_ZLIB=ON \ + -DENABLE_CURL_MANUAL=OFF \ -DENABLE_THREADED_RESOLVER=ON \ -DOPENSSL_USE_STATIC_LIBS=ON \ -DUSE_LIBIDN2=OFF \ diff --git a/repertory/librepertory/include/app_config.hpp b/repertory/librepertory/include/app_config.hpp index 51ba7b12..e24bc44f 100644 --- a/repertory/librepertory/include/app_config.hpp +++ b/repertory/librepertory/include/app_config.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,12 +22,14 @@ #ifndef REPERTORY_INCLUDE_APP_CONFIG_HPP_ #define REPERTORY_INCLUDE_APP_CONFIG_HPP_ -#include "events/event.hpp" #include "types/remote.hpp" #include "types/repertory.hpp" namespace repertory { class app_config final { +private: + static stop_type stop_requested; + public: [[nodiscard]] static auto default_agent_name(const provider_type &prov) -> std::string; @@ -50,6 +52,11 @@ public: [[nodiscard]] static auto get_provider_name(const provider_type &prov) -> std::string; +public: + [[nodiscard]] static auto get_stop_requested() -> bool; + + static void set_stop_requested(); + public: app_config(const provider_type &prov, std::string_view data_directory = ""); diff --git a/repertory/librepertory/include/comm/curl/curl_comm.hpp b/repertory/librepertory/include/comm/curl/curl_comm.hpp index 46c409c8..f4e1eb41 100644 --- a/repertory/librepertory/include/comm/curl/curl_comm.hpp +++ b/repertory/librepertory/include/comm/curl/curl_comm.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,10 +22,11 @@ #ifndef REPERTORY_INCLUDE_COMM_CURL_CURL_COMM_HPP_ #define REPERTORY_INCLUDE_COMM_CURL_CURL_COMM_HPP_ +#include "app_config.hpp" #include "comm/curl/multi_request.hpp" #include "comm/i_http_comm.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/curl_error.hpp" #include "utils/encryption.hpp" namespace repertory { @@ -42,7 +43,7 @@ private: struct read_write_info final { data_buffer data{}; - stop_type &stop_requested; + stop_type_callback stop_requested_cb; }; static const write_callback write_data; @@ -61,13 +62,14 @@ public: [[nodiscard]] static auto reset_curl(CURL *curl_handle) -> CURL *; public: - [[nodiscard]] static auto - construct_url(CURL *curl, const std::string &relative_path, - const host_config &cfg) -> std::string; + [[nodiscard]] static auto construct_url(CURL *curl, + const std::string &relative_path, + const host_config &cfg) + -> std::string; - [[nodiscard]] static auto - create_host_config(const s3_config &cfg, - bool use_s3_path_style) -> host_config; + [[nodiscard]] static auto create_host_config(const s3_config &cfg, + bool use_s3_path_style) + -> host_config; [[nodiscard]] static auto url_encode(CURL *curl, const std::string &data, bool allow_slash) -> std::string; @@ -75,8 +77,8 @@ public: template [[nodiscard]] static auto make_encrypted_request(const host_config &cfg, const request_type &request, - long &response_code, - stop_type &stop_requested) -> bool { + long &response_code, stop_type &stop_requested) + -> bool { response_code = 0; if (not request.decryption_token.has_value() || @@ -114,7 +116,7 @@ public: return false; } - if (response_code != 200) { + if (response_code != http_error_codes::ok) { return false; } @@ -135,6 +137,8 @@ public: [[nodiscard]] static auto make_request(const host_config &cfg, const request_type &request, long &response_code, stop_type &stop_requested) -> bool { + REPERTORY_USES_FUNCTION_NAME(); + if (request.decryption_token.has_value() && not request.decryption_token.value().empty()) { return make_encrypted_request(cfg, request, response_code, @@ -169,7 +173,12 @@ public: curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_headers); } - read_write_info write_info{{}, stop_requested}; + read_write_info write_info{ + {}, + [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }, + }; if (request.response_handler.has_value()) { curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_info); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); @@ -193,6 +202,16 @@ public: request.aws_service.value().c_str()); } + curl_slist *header_list{nullptr}; + if (not request.headers.empty()) { + for (const auto &header : request.headers) { + header_list = curl_slist_append( + header_list, + fmt::format("{}: {}", header.first, header.second).c_str()); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list); + } + auto url = construct_url(curl, request.get_path(), cfg) + parameters; curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); @@ -200,8 +219,14 @@ public: CURLcode curl_code{}; curl_request.get_result(curl_code, response_code); + + if (header_list != nullptr) { + curl_slist_free_all(header_list); + } + if (curl_code != CURLE_OK) { - event_system::instance().raise(url, curl_code); + event_system::instance().raise(curl_code, function_name, + url); return false; } @@ -215,26 +240,30 @@ public: public: void enable_s3_path_style(bool enable) override; - [[nodiscard]] auto - make_request(const curl::requests::http_delete &del, long &response_code, - stop_type &stop_requested) const -> bool override; + [[nodiscard]] auto make_request(const curl::requests::http_delete &del, + long &response_code, + stop_type &stop_requested) const + -> bool override; - [[nodiscard]] auto - make_request(const curl::requests::http_get &get, long &response_code, - stop_type &stop_requested) const -> bool override; + [[nodiscard]] auto make_request(const curl::requests::http_get &get, + long &response_code, + stop_type &stop_requested) const + -> bool override; - [[nodiscard]] auto - make_request(const curl::requests::http_head &head, long &response_code, - stop_type &stop_requested) const -> bool override; + [[nodiscard]] auto make_request(const curl::requests::http_head &head, + long &response_code, + stop_type &stop_requested) const + -> bool override; - [[nodiscard]] auto - make_request(const curl::requests::http_post &post_file, long &response_code, - stop_type &stop_requested) const -> bool override; + [[nodiscard]] auto make_request(const curl::requests::http_post &post_file, + long &response_code, + stop_type &stop_requested) const + -> bool override; - [[nodiscard]] auto - make_request(const curl::requests::http_put_file &put_file, - long &response_code, - stop_type &stop_requested) const -> bool override; + [[nodiscard]] auto make_request(const curl::requests::http_put_file &put_file, + long &response_code, + stop_type &stop_requested) const + -> bool override; }; } // namespace repertory diff --git a/repertory/librepertory/include/comm/curl/multi_request.hpp b/repertory/librepertory/include/comm/curl/multi_request.hpp index 75c2d8bc..a294ce8b 100644 --- a/repertory/librepertory/include/comm/curl/multi_request.hpp +++ b/repertory/librepertory/include/comm/curl/multi_request.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -36,6 +36,9 @@ private: stop_type &stop_requested_; CURLM *multi_handle_; +private: + [[nodiscard]] auto get_stop_requested() const -> bool; + public: void get_result(CURLcode &curl_code, long &http_code); }; diff --git a/repertory/librepertory/include/comm/curl/requests/http_delete.hpp b/repertory/librepertory/include/comm/curl/requests/http_delete.hpp index 593bdc9c..41d6a94c 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_delete.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_delete.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/curl/requests/http_get.hpp b/repertory/librepertory/include/comm/curl/requests/http_get.hpp index 662070a2..e1f02326 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_get.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_get.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/curl/requests/http_head.hpp b/repertory/librepertory/include/comm/curl/requests/http_head.hpp index d7e225b8..341bed8f 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_head.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_head.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/curl/requests/http_post.hpp b/repertory/librepertory/include/comm/curl/requests/http_post.hpp index 9345bfda..c5425e12 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_post.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_post.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -32,15 +32,15 @@ struct http_post final : http_request_base { auto operator=(const http_post &) -> http_post & = default; auto operator=(http_post &&) -> http_post & = default; - ~http_post() override; + ~http_post() override = default; std::optional json; - [[nodiscard]] auto - set_method(CURL *curl, stop_type & /*stop_requested*/) const -> bool override; + [[nodiscard]] auto set_method(CURL *curl, + stop_type & /*stop_requested*/) const + -> bool override; private: - mutable curl_slist *headers{nullptr}; mutable std::optional json_str; }; } // namespace repertory::curl::requests diff --git a/repertory/librepertory/include/comm/curl/requests/http_put_file.hpp b/repertory/librepertory/include/comm/curl/requests/http_put_file.hpp index 90ae3772..8841adc4 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_put_file.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_put_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp b/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp index 8851372c..a99d88da 100644 --- a/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp +++ b/repertory/librepertory/include/comm/curl/requests/http_request_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,7 @@ struct http_request_base { bool allow_timeout{}; std::optional aws_service; std::optional decryption_token{}; - http_headers headers{}; + mutable http_headers headers{}; std::string path{}; http_query_parameters query{}; std::optional range{}; diff --git a/repertory/librepertory/include/comm/i_http_comm.hpp b/repertory/librepertory/include/comm/i_http_comm.hpp index f3b9b643..e4373b76 100644 --- a/repertory/librepertory/include/comm/i_http_comm.hpp +++ b/repertory/librepertory/include/comm/i_http_comm.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/packet/client_pool.hpp b/repertory/librepertory/include/comm/packet/client_pool.hpp index f64bd52b..d4c9795d 100644 --- a/repertory/librepertory/include/comm/packet/client_pool.hpp +++ b/repertory/librepertory/include/comm/packet/client_pool.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/packet/packet.hpp b/repertory/librepertory/include/comm/packet/packet.hpp index 924bfbae..61b5bcbe 100644 --- a/repertory/librepertory/include/comm/packet/packet.hpp +++ b/repertory/librepertory/include/comm/packet/packet.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/comm/packet/packet_client.hpp b/repertory/librepertory/include/comm/packet/packet_client.hpp index 9e67e387..ff47896d 100644 --- a/repertory/librepertory/include/comm/packet/packet_client.hpp +++ b/repertory/librepertory/include/comm/packet/packet_client.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -69,21 +69,21 @@ private: void put_client(std::shared_ptr &cli); - [[nodiscard]] auto read_packet(client &cli, packet &response) - -> packet::error_type; + [[nodiscard]] auto read_packet(client &cli, + packet &response) const -> packet::error_type; void resolve(); public: - [[nodiscard]] auto send(std::string_view method, std::uint32_t &service_flags) - -> packet::error_type; + [[nodiscard]] auto send(std::string_view method, + std::uint32_t &service_flags) -> packet::error_type; [[nodiscard]] auto send(std::string_view method, packet &request, std::uint32_t &service_flags) -> packet::error_type; [[nodiscard]] auto send(std::string_view method, packet &request, - packet &response, std::uint32_t &service_flags) - -> packet::error_type; + packet &response, + std::uint32_t &service_flags) -> packet::error_type; }; } // namespace repertory diff --git a/repertory/librepertory/include/comm/packet/packet_server.hpp b/repertory/librepertory/include/comm/packet/packet_server.hpp index b3c41708..e81fb1ae 100644 --- a/repertory/librepertory/include/comm/packet/packet_server.hpp +++ b/repertory/librepertory/include/comm/packet/packet_server.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/common.hpp b/repertory/librepertory/include/common.hpp index 9e798cba..c8948b8f 100644 --- a/repertory/librepertory/include/common.hpp +++ b/repertory/librepertory/include/common.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -221,25 +221,44 @@ using WCHAR = wchar_t; #define MAX_PATH 260 -#define STATUS_SUCCESS std::uint32_t{0U} -#define STATUS_ACCESS_DENIED std::uint32_t{0xC0000022L} -#define STATUS_DEVICE_BUSY std::uint32_t{0x80000011L} -#define STATUS_DEVICE_INSUFFICIENT_RESOURCES std::uint32_t{0xC0000468L} -#define STATUS_DIRECTORY_NOT_EMPTY std::uint32_t{0xC0000101L} -#define STATUS_FILE_IS_A_DIRECTORY std::uint32_t{0xC00000BAL} -#define STATUS_FILE_TOO_LARGE std::uint32_t{0xC0000904L} -#define STATUS_INSUFFICIENT_RESOURCES std::uint32_t{0xC000009AL} -#define STATUS_INTERNAL_ERROR std::uint32_t{0xC00000E5L} -#define STATUS_INVALID_ADDRESS std::uint32_t{0xC0000141L} -#define STATUS_INVALID_HANDLE std::uint32_t{0xC0000006L} -#define STATUS_INVALID_IMAGE_FORMAT std::uint32_t{0xC000007BL} -#define STATUS_INVALID_PARAMETER std::uint32_t{0xC000000DL} -#define STATUS_NO_MEMORY std::uint32_t{0xC0000017L} -#define STATUS_NOT_IMPLEMENTED std::uint32_t{0xC0000002L} -#define STATUS_OBJECT_NAME_EXISTS std::uint32_t{0x40000000L} -#define STATUS_OBJECT_NAME_NOT_FOUND std::uint32_t{0xC0000034L} -#define STATUS_OBJECT_PATH_INVALID std::uint32_t{0xC0000039L} -#define STATUS_UNEXPECTED_IO_ERROR std::uint32_t{0xC00000E9L} +#define STATUS_SUCCESS \ + std::uint32_t { 0U } +#define STATUS_ACCESS_DENIED \ + std::uint32_t { 0xC0000022L } +#define STATUS_DEVICE_BUSY \ + std::uint32_t { 0x80000011L } +#define STATUS_DEVICE_INSUFFICIENT_RESOURCES \ + std::uint32_t { 0xC0000468L } +#define STATUS_DIRECTORY_NOT_EMPTY \ + std::uint32_t { 0xC0000101L } +#define STATUS_FILE_IS_A_DIRECTORY \ + std::uint32_t { 0xC00000BAL } +#define STATUS_FILE_TOO_LARGE \ + std::uint32_t { 0xC0000904L } +#define STATUS_INSUFFICIENT_RESOURCES \ + std::uint32_t { 0xC000009AL } +#define STATUS_INTERNAL_ERROR \ + std::uint32_t { 0xC00000E5L } +#define STATUS_INVALID_ADDRESS \ + std::uint32_t { 0xC0000141L } +#define STATUS_INVALID_HANDLE \ + std::uint32_t { 0xC0000006L } +#define STATUS_INVALID_IMAGE_FORMAT \ + std::uint32_t { 0xC000007BL } +#define STATUS_INVALID_PARAMETER \ + std::uint32_t { 0xC000000DL } +#define STATUS_NO_MEMORY \ + std::uint32_t { 0xC0000017L } +#define STATUS_NOT_IMPLEMENTED \ + std::uint32_t { 0xC0000002L } +#define STATUS_OBJECT_NAME_EXISTS \ + std::uint32_t { 0x40000000L } +#define STATUS_OBJECT_NAME_NOT_FOUND \ + std::uint32_t { 0xC0000034L } +#define STATUS_OBJECT_PATH_INVALID \ + std::uint32_t { 0xC0000039L } +#define STATUS_UNEXPECTED_IO_ERROR \ + std::uint32_t { 0xC00000E9L } #define CONVERT_STATUS_NOT_IMPLEMENTED(e) \ ((std::uint32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e) diff --git a/repertory/librepertory/include/db/file_db.hpp b/repertory/librepertory/include/db/file_db.hpp index 0567f5f8..0ae82bd9 100644 --- a/repertory/librepertory/include/db/file_db.hpp +++ b/repertory/librepertory/include/db/file_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/db/file_mgr_db.hpp b/repertory/librepertory/include/db/file_mgr_db.hpp index 2ffca0d4..d1cd95cb 100644 --- a/repertory/librepertory/include/db/file_mgr_db.hpp +++ b/repertory/librepertory/include/db/file_mgr_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/db/i_file_db.hpp b/repertory/librepertory/include/db/i_file_db.hpp index 574a6979..ae05c3a3 100644 --- a/repertory/librepertory/include/db/i_file_db.hpp +++ b/repertory/librepertory/include/db/i_file_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,7 +31,7 @@ class i_file_db { public: struct file_info final { std::string api_path; - bool directory; + bool directory{}; std::string source_path; }; @@ -56,6 +56,10 @@ public: [[nodiscard]] virtual auto count() const -> std::uint64_t = 0; + virtual void enumerate_item_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const = 0; + [[nodiscard]] virtual auto get_api_path(const std::string &source_path, std::string &api_path) const -> api_error = 0; @@ -80,7 +84,8 @@ public: get_file_source_path(const std::string &api_path, std::string &source_path) const -> api_error = 0; - [[nodiscard]] virtual auto get_item_list() const + [[nodiscard]] virtual auto + get_item_list(stop_type_callback stop_requested_cb) const -> std::vector = 0; [[nodiscard]] virtual auto get_source_path(const std::string &api_path, diff --git a/repertory/librepertory/include/db/i_file_mgr_db.hpp b/repertory/librepertory/include/db/i_file_mgr_db.hpp index 0829261a..8d4627f1 100644 --- a/repertory/librepertory/include/db/i_file_mgr_db.hpp +++ b/repertory/librepertory/include/db/i_file_mgr_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -41,10 +41,7 @@ public: std::string source_path; }; - struct upload_entry final { - std::string api_path; - std::string source_path; - }; + using upload_entry = upload_active_entry; public: [[nodiscard]] virtual auto add_resume(const resume_entry &entry) -> bool = 0; diff --git a/repertory/librepertory/include/db/i_meta_db.hpp b/repertory/librepertory/include/db/i_meta_db.hpp index d8e82d35..a1a0d467 100644 --- a/repertory/librepertory/include/db/i_meta_db.hpp +++ b/repertory/librepertory/include/db/i_meta_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,10 @@ class i_meta_db { public: virtual void clear() = 0; + virtual void enumerate_api_path_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const = 0; + [[nodiscard]] virtual auto get_api_path(const std::string &source_path, std::string &api_path) const -> api_error = 0; diff --git a/repertory/librepertory/include/db/impl/rdb_file_db.hpp b/repertory/librepertory/include/db/impl/rdb_file_db.hpp index 64138441..902c777d 100644 --- a/repertory/librepertory/include/db/impl/rdb_file_db.hpp +++ b/repertory/librepertory/include/db/impl/rdb_file_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -67,50 +67,54 @@ private: rocksdb::Transaction *txn) -> rocksdb::Status; public: - [[nodiscard]] auto - add_directory(const std::string &api_path, - const std::string &source_path) -> api_error override; + [[nodiscard]] auto add_directory(const std::string &api_path, + const std::string &source_path) + -> api_error override; - [[nodiscard]] auto - add_or_update_file(const i_file_db::file_data &data) -> api_error override; + [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data) + -> api_error override; void clear() override; [[nodiscard]] auto count() const -> std::uint64_t override; - [[nodiscard]] auto - get_api_path(const std::string &source_path, - std::string &api_path) const -> api_error override; + void enumerate_item_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const override; - [[nodiscard]] auto - get_directory_api_path(const std::string &source_path, - std::string &api_path) const -> api_error override; + [[nodiscard]] auto get_api_path(const std::string &source_path, + std::string &api_path) const + -> api_error override; + + [[nodiscard]] auto get_directory_api_path(const std::string &source_path, + std::string &api_path) const + -> api_error override; [[nodiscard]] auto get_directory_source_path(const std::string &api_path, std::string &source_path) const -> api_error override; - [[nodiscard]] auto - get_file_api_path(const std::string &source_path, - std::string &api_path) const -> api_error override; + [[nodiscard]] auto get_file_api_path(const std::string &source_path, + std::string &api_path) const + -> api_error override; - [[nodiscard]] auto - get_file_data(const std::string &api_path, - i_file_db::file_data &data) const -> api_error override; + [[nodiscard]] auto get_file_data(const std::string &api_path, + i_file_db::file_data &data) const + -> api_error override; - [[nodiscard]] auto - get_file_source_path(const std::string &api_path, - std::string &source_path) const -> api_error override; + [[nodiscard]] auto get_file_source_path(const std::string &api_path, + std::string &source_path) const + -> api_error override; - [[nodiscard]] auto - get_item_list() const -> std::vector override; + [[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const + -> std::vector override; - [[nodiscard]] auto - get_source_path(const std::string &api_path, - std::string &source_path) const -> api_error override; + [[nodiscard]] auto get_source_path(const std::string &api_path, + std::string &source_path) const + -> api_error override; - [[nodiscard]] auto - remove_item(const std::string &api_path) -> api_error override; + [[nodiscard]] auto remove_item(const std::string &api_path) + -> api_error override; }; } // namespace repertory diff --git a/repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp b/repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp index 56647321..1e00f9c7 100644 --- a/repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp +++ b/repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/db/impl/rdb_meta_db.hpp b/repertory/librepertory/include/db/impl/rdb_meta_db.hpp index 87060a3a..b235f779 100644 --- a/repertory/librepertory/include/db/impl/rdb_meta_db.hpp +++ b/repertory/librepertory/include/db/impl/rdb_meta_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -80,6 +80,10 @@ private: public: void clear() override; + void enumerate_api_path_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const override; + [[nodiscard]] auto get_api_path(const std::string &source_path, std::string &api_path) const -> api_error override; diff --git a/repertory/librepertory/include/db/impl/sqlite_file_db.hpp b/repertory/librepertory/include/db/impl/sqlite_file_db.hpp index de5dbeca..4a9a7d82 100644 --- a/repertory/librepertory/include/db/impl/sqlite_file_db.hpp +++ b/repertory/librepertory/include/db/impl/sqlite_file_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -53,6 +53,10 @@ public: [[nodiscard]] auto count() const -> std::uint64_t override; + void enumerate_item_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const override; + [[nodiscard]] auto get_api_path(const std::string &source_path, std::string &api_path) const -> api_error override; @@ -77,7 +81,7 @@ public: std::string &source_path) const -> api_error override; - [[nodiscard]] auto get_item_list() const + [[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const -> std::vector override; [[nodiscard]] auto get_source_path(const std::string &api_path, diff --git a/repertory/librepertory/include/db/impl/sqlite_file_mgr_db.hpp b/repertory/librepertory/include/db/impl/sqlite_file_mgr_db.hpp index bf7a8ed2..acdb2a1d 100644 --- a/repertory/librepertory/include/db/impl/sqlite_file_mgr_db.hpp +++ b/repertory/librepertory/include/db/impl/sqlite_file_mgr_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/db/impl/sqlite_meta_db.hpp b/repertory/librepertory/include/db/impl/sqlite_meta_db.hpp index f96e9d6f..c1f7691d 100644 --- a/repertory/librepertory/include/db/impl/sqlite_meta_db.hpp +++ b/repertory/librepertory/include/db/impl/sqlite_meta_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -50,6 +50,10 @@ private: public: void clear() override; + void enumerate_api_path_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const override; + [[nodiscard]] auto get_api_path(const std::string &source_path, std::string &api_path) const -> api_error override; diff --git a/repertory/librepertory/include/db/meta_db.hpp b/repertory/librepertory/include/db/meta_db.hpp index 9ce6aa71..d2aa68d5 100644 --- a/repertory/librepertory/include/db/meta_db.hpp +++ b/repertory/librepertory/include/db/meta_db.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/directory_cache.hpp b/repertory/librepertory/include/drives/directory_cache.hpp index 706a64fc..1278d5e1 100644 --- a/repertory/librepertory/include/drives/directory_cache.hpp +++ b/repertory/librepertory/include/drives/directory_cache.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,12 +22,10 @@ #ifndef REPERTORY_INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_ #define REPERTORY_INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_ -#include "utils/single_thread_service_base.hpp" - namespace repertory { class directory_iterator; -class directory_cache final : public single_thread_service_base { +class directory_cache final { public: using execute_callback = std::function; @@ -35,13 +33,11 @@ private: struct open_directory final { std::shared_ptr iterator; std::vector handles; - std::chrono::system_clock::time_point last_update{ - std::chrono::system_clock::now()}; }; public: - directory_cache() : single_thread_service_base("directory_cache") {} - ~directory_cache() override = default; + directory_cache() = default; + ~directory_cache() = default; directory_cache(const directory_cache &) = delete; directory_cache(directory_cache &&) = delete; @@ -51,10 +47,6 @@ public: private: std::unordered_map directory_lookup_; std::recursive_mutex directory_mutex_; - std::unique_ptr refresh_thread_; - -protected: - void service_function() override; public: void execute_action(const std::string &api_path, @@ -63,7 +55,7 @@ public: [[nodiscard]] auto get_directory(std::uint64_t handle) -> std::shared_ptr; - [[nodiscard]] auto remove_directory(const std::string &api_path) + auto remove_directory(const std::string &api_path) -> std::shared_ptr; void remove_directory(std::uint64_t handle); diff --git a/repertory/librepertory/include/drives/directory_iterator.hpp b/repertory/librepertory/include/drives/directory_iterator.hpp index f03e8f76..d535a10e 100644 --- a/repertory/librepertory/include/drives/directory_iterator.hpp +++ b/repertory/librepertory/include/drives/directory_iterator.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/eviction.hpp b/repertory/librepertory/include/drives/eviction.hpp index cab21781..0fc48b59 100644 --- a/repertory/librepertory/include/drives/eviction.hpp +++ b/repertory/librepertory/include/drives/eviction.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/fuse/events.hpp b/repertory/librepertory/include/drives/fuse/events.hpp deleted file mode 100644 index 6faf6a1f..00000000 --- a/repertory/librepertory/include/drives/fuse/events.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_DRIVES_FUSE_EVENTS_HPP_ -#define REPERTORY_INCLUDE_DRIVES_FUSE_EVENTS_HPP_ - -#include "events/event_system.hpp" - -namespace repertory { -// clang-format off -E_SIMPLE3(fuse_event, debug, true, - std::string, function, func, E_FROM_STRING, - std::string, api_path, ap, E_FROM_STRING, - int, result, res, E_FROM_INT32 -); - -E_SIMPLE1(fuse_args_parsed, info, true, - std::string, arguments, args, E_FROM_STRING -); -// clang-format on -} // namespace repertory - -#endif // REPERTORY_INCLUDE_DRIVES_FUSE_EVENTS_HPP_ diff --git a/repertory/librepertory/include/drives/fuse/fuse_base.hpp b/repertory/librepertory/include/drives/fuse/fuse_base.hpp index 013db924..284e0b67 100644 --- a/repertory/librepertory/include/drives/fuse/fuse_base.hpp +++ b/repertory/librepertory/include/drives/fuse/fuse_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,7 @@ #if !defined(_WIN32) #include "events/event_system.hpp" -#include "utils/path.hpp" +#include "types/repertory.hpp" namespace repertory { class app_config; @@ -51,8 +51,8 @@ private: std::string mount_location_; protected: - bool atime_enabled_ = true; - bool console_enabled_ = false; + bool atime_enabled_{true}; + bool console_enabled_{false}; std::optional forced_gid_; std::optional forced_uid_; std::optional forced_umask_; diff --git a/repertory/librepertory/include/drives/fuse/fuse_drive.hpp b/repertory/librepertory/include/drives/fuse/fuse_drive.hpp index c3922a24..fa7b4b50 100644 --- a/repertory/librepertory/include/drives/fuse/fuse_drive.hpp +++ b/repertory/librepertory/include/drives/fuse/fuse_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -63,11 +63,14 @@ private: std::shared_ptr logging_consumer_; std::shared_ptr remote_server_; std::shared_ptr server_; - bool was_mounted_ = false; + std::mutex stop_all_mtx_; + bool was_mounted_{false}; private: void update_accessed_time(const std::string &api_path); + void stop_all(); + protected: #if defined(__APPLE__) [[nodiscard]] auto chflags_impl(std::string api_path, diff --git a/repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp b/repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp index 7c2641f9..9f51fbbc 100644 --- a/repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp +++ b/repertory/librepertory/include/drives/fuse/fuse_drive_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp b/repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp index aeaee22a..ef029052 100644 --- a/repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp +++ b/repertory/librepertory/include/drives/fuse/i_fuse_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/fuse/remotefuse/i_remote_instance.hpp b/repertory/librepertory/include/drives/fuse/remotefuse/i_remote_instance.hpp index c85787ce..4999da86 100644 --- a/repertory/librepertory/include/drives/fuse/remotefuse/i_remote_instance.hpp +++ b/repertory/librepertory/include/drives/fuse/remotefuse/i_remote_instance.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/fuse/remotefuse/remote_client.hpp b/repertory/librepertory/include/drives/fuse/remotefuse/remote_client.hpp index ca4d778a..494ee16c 100644 --- a/repertory/librepertory/include/drives/fuse/remotefuse/remote_client.hpp +++ b/repertory/librepertory/include/drives/fuse/remotefuse/remote_client.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/fuse/remotefuse/remote_fuse_drive.hpp b/repertory/librepertory/include/drives/fuse/remotefuse/remote_fuse_drive.hpp index 6c642555..aef87cc2 100644 --- a/repertory/librepertory/include/drives/fuse/remotefuse/remote_fuse_drive.hpp +++ b/repertory/librepertory/include/drives/fuse/remotefuse/remote_fuse_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -53,8 +53,8 @@ private: bool was_mounted_ = false; private: - void populate_stat(const remote::stat &r_stat, bool directory, - struct stat &unix_st); + static void populate_stat(const remote::stat &r_stat, bool directory, + struct stat &unix_st); protected: [[nodiscard]] auto access_impl(std::string api_path, diff --git a/repertory/librepertory/include/drives/fuse/remotefuse/remote_server.hpp b/repertory/librepertory/include/drives/fuse/remotefuse/remote_server.hpp index eaefed60..7290d4bd 100644 --- a/repertory/librepertory/include/drives/fuse/remotefuse/remote_server.hpp +++ b/repertory/librepertory/include/drives/fuse/remotefuse/remote_server.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/remote/i_remote_json.hpp b/repertory/librepertory/include/drives/remote/i_remote_json.hpp index f9118f23..74067975 100644 --- a/repertory/librepertory/include/drives/remote/i_remote_json.hpp +++ b/repertory/librepertory/include/drives/remote/i_remote_json.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp b/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp index 804ccc90..f21bf480 100644 --- a/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp +++ b/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/remote/remote_server_base.hpp b/repertory/librepertory/include/drives/remote/remote_server_base.hpp index 548c830a..32c09d78 100644 --- a/repertory/librepertory/include/drives/remote/remote_server_base.hpp +++ b/repertory/librepertory/include/drives/remote/remote_server_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,10 @@ #include "drives/remote/remote_open_file_table.hpp" #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "types/remote.hpp" #include "types/repertory.hpp" #include "utils/base64.hpp" @@ -55,7 +58,10 @@ public: drive_(drv), mount_location_(std::move(mount_location)), client_pool_(config.get_remote_mount().client_pool_size) { - event_system::instance().raise("remote_server_base"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "remote_server_base"); handler_lookup_.insert( {"::winfsp_can_delete", [this](std::uint32_t, const std::string &, std::uint64_t, @@ -1372,14 +1378,19 @@ public: method, request, response, message_complete); }); + event_system::instance().raise(function_name, + "remote_server_base"); } ~remote_server_base() override { - event_system::instance().raise( - "remote_server_base"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "remote_server_base"); client_pool_.shutdown(); packet_server_.reset(); - event_system::instance().raise("remote_server_base"); + event_system::instance().raise(function_name, + "remote_server_base"); } public: diff --git a/repertory/librepertory/include/drives/winfsp/i_winfsp_drive.hpp b/repertory/librepertory/include/drives/winfsp/i_winfsp_drive.hpp index c95a7c9b..e33e2e78 100644 --- a/repertory/librepertory/include/drives/winfsp/i_winfsp_drive.hpp +++ b/repertory/librepertory/include/drives/winfsp/i_winfsp_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/winfsp/remotewinfsp/i_remote_instance.hpp b/repertory/librepertory/include/drives/winfsp/remotewinfsp/i_remote_instance.hpp index b4f34333..03c78ab5 100644 --- a/repertory/librepertory/include/drives/winfsp/remotewinfsp/i_remote_instance.hpp +++ b/repertory/librepertory/include/drives/winfsp/remotewinfsp/i_remote_instance.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_client.hpp b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_client.hpp index 9c07a297..2c141606 100644 --- a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_client.hpp +++ b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_client.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_server.hpp b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_server.hpp index c82dfeef..8665277c 100644 --- a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_server.hpp +++ b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_server.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp index 9d430cea..4da2c416 100644 --- a/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp +++ b/repertory/librepertory/include/drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp b/repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp index 716fa36b..4609f40d 100644 --- a/repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp +++ b/repertory/librepertory/include/drives/winfsp/winfsp_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -73,6 +73,7 @@ private: std::unique_ptr fm_; std::unique_ptr eviction_; std::unique_ptr remote_server_; + std::mutex stop_all_mtx_; private: [[nodiscard]] auto handle_error(std::string_view function_name, @@ -94,6 +95,8 @@ private: static void set_file_info(remote::file_info &dest, const FSP_FSCTL_FILE_INFO &src); + void stop_all(); + public: auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name) -> NTSTATUS override; diff --git a/repertory/librepertory/include/events/consumers/console_consumer.hpp b/repertory/librepertory/include/events/consumers/console_consumer.hpp index c537d690..4b677be8 100644 --- a/repertory/librepertory/include/events/consumers/console_consumer.hpp +++ b/repertory/librepertory/include/events/consumers/console_consumer.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,7 @@ #define REPERTORY_INCLUDE_EVENTS_CONSUMERS_CONSOLE_CONSUMER_HPP_ #include "events/event_system.hpp" +#include "types/repertory.hpp" namespace repertory { class console_consumer final { @@ -36,7 +37,7 @@ public: ~console_consumer(); private: - void process_event(const event &e) const; + static void process_event(const i_event &evt); }; } // namespace repertory diff --git a/repertory/librepertory/include/events/consumers/logging_consumer.hpp b/repertory/librepertory/include/events/consumers/logging_consumer.hpp index 556bc72f..603f2ea1 100644 --- a/repertory/librepertory/include/events/consumers/logging_consumer.hpp +++ b/repertory/librepertory/include/events/consumers/logging_consumer.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,10 @@ #define REPERTORY_INCLUDE_EVENTS_CONSUMERS_LOGGING_CONSUMER_HPP_ #include "events/event_system.hpp" +#include "types/repertory.hpp" namespace repertory { -class logging_consumer { +class logging_consumer final { E_CONSUMER(); public: @@ -39,7 +40,7 @@ private: 5ULL}; private: - void process_event(const event &event) const; + static void process_event(const i_event &evt); }; } // namespace repertory diff --git a/repertory/librepertory/include/events/event.hpp b/repertory/librepertory/include/events/event.hpp deleted file mode 100644 index 8a9021fa..00000000 --- a/repertory/librepertory/include/events/event.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_EVENTS_EVENT_HPP_ -#define REPERTORY_INCLUDE_EVENTS_EVENT_HPP_ - -namespace repertory { -enum class event_level { - critical, - error, - warn, - info, - debug, - trace, -}; - -[[nodiscard]] auto -event_level_from_string(std::string level, - event_level default_level = event_level::info) - -> event_level; - -[[nodiscard]] auto event_level_to_string(event_level level) -> std::string; - -class event { -protected: - explicit event(bool allow_async) : allow_async_(allow_async) {} - - event(const std::stringstream &ss, json j, bool allow_async) - : allow_async_(allow_async), ss_(ss.str()), j_(std::move(j)) {} - -public: - event(const event &) = delete; - event(event &&) = delete; - auto operator=(const event &) -> event & = delete; - auto operator=(event &&) -> event & = delete; - virtual ~event() = default; - -private: - bool allow_async_; - -protected: - std::stringstream ss_; - json j_; - -public: - [[nodiscard]] virtual auto clone() const -> std::shared_ptr = 0; - - [[nodiscard]] auto get_allow_async() const -> bool { return allow_async_; } - - [[nodiscard]] virtual auto get_event_level() const -> event_level = 0; - - [[nodiscard]] auto get_json() const -> json { return j_; } - - [[nodiscard]] virtual auto get_name() const -> std::string = 0; - - [[nodiscard]] virtual auto get_single_line() const -> std::string = 0; -}; -} // namespace repertory - -NLOHMANN_JSON_NAMESPACE_BEGIN -template <> struct adl_serializer> { - static void to_json(json &data, - const std::atomic &value) { - data = repertory::event_level_to_string(value.load()); - } - - static void from_json(const json &data, - std::atomic &value) { - value.store(repertory::event_level_from_string(data.get())); - } -}; -NLOHMANN_JSON_NAMESPACE_END - -#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_ diff --git a/repertory/librepertory/include/events/event_system.hpp b/repertory/librepertory/include/events/event_system.hpp index b11bfb1d..cefdfe14 100644 --- a/repertory/librepertory/include/events/event_system.hpp +++ b/repertory/librepertory/include/events/event_system.hpp @@ -1,241 +1,141 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ -#define REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ - -#include "events/event.hpp" -#include "events/t_event_system.hpp" - -namespace repertory { -using event_system = t_event_system; -using event_consumer = event_system::event_consumer; - -#define E_FROM_API_FILE_ERROR(e) api_error_to_string(e) -#define E_FROM_BOOL(t) std::to_string(t) -#define E_FROM_CURL_CODE(t) std::string(curl_easy_strerror(t)) -#define E_FROM_DOUBLE(d) std::to_string(d) -#define E_FROM_DOUBLE_PRECISE(dbl_val) \ - ([](const double &d) -> std::string { \ - std::stringstream ss; \ - ss << std::fixed << std::setprecision(2) << d; \ - return ss.str(); \ - })(dbl_val) -#define E_FROM_INT32(t) std::to_string(t) -#define E_FROM_SIZE_T(t) std::to_string(t) -#define E_FROM_STRING(t) t -#define E_FROM_UINT16(t) std::to_string(t) -#define E_FROM_UINT64(t) std::to_string(t) -#define E_FROM_DOWNLOAD_TYPE(t) download_type_to_string(t) - -#define E_PROP(type, name, short_name, ts) \ -private: \ - void init_##short_name(const type &val) { \ - auto ts_val = ts(val); \ - ss_ << "|" << #short_name << "|" << ts_val; \ - j_[#name] = ts_val; \ - } \ - \ -public: \ - [[nodiscard]] auto get_##name() const->json { return j_[#name]; } - -#define E_BEGIN(name, el) \ - class name final : public virtual event { \ - private: \ - name(const std::stringstream &ss, const json &j, bool allow_async) \ - : event(ss, j, allow_async) {} \ - \ - public: \ - ~name() override = default; \ - \ - public: \ - static const event_level level = event_level::el; \ - \ - public: \ - [[nodiscard]] auto get_name() const -> std::string override { \ - return #name; \ - } \ - \ - [[nodiscard]] auto get_event_level() const -> event_level override { \ - return name::level; \ - } \ - \ - [[nodiscard]] auto get_single_line() const -> std::string override { \ - const auto s = ss_.str(); \ - return get_name() + (s.empty() ? "" : s); \ - } \ - \ - [[nodiscard]] auto clone() const -> std::shared_ptr override { \ - return std::shared_ptr(new name(ss_, j_, get_allow_async())); \ - } -#define E_END() } - -#define E_SIMPLE(event_name, el, allow_async) \ - E_BEGIN(event_name, el) \ -public: \ - event_name() : event(allow_async) {} \ - E_END() - -#define E_SIMPLE1(event_name, el, allow_async, type, name, short_name, tc) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv) : event(allow_async) { \ - init_##short_name(tv); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_END() - -#define E_SIMPLE2(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2) : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_END() - -#define E_SIMPLE3(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2, type3, name3, short_name3, \ - tc3) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3) \ - : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - init_##short_name3(tv3); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_PROP(type3, name3, short_name3, tc3) \ - E_END() - -#define E_SIMPLE4(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2, type3, name3, short_name3, \ - tc3, type4, name4, short_name4, tc4) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \ - const type4 &tv4) \ - : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - init_##short_name3(tv3); \ - init_##short_name4(tv4); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_PROP(type3, name3, short_name3, tc3) \ - E_PROP(type4, name4, short_name4, tc4) \ - E_END() - -#define E_SIMPLE5(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2, type3, name3, short_name3, \ - tc3, type4, name4, short_name4, tc4, type5, name5, \ - short_name5, tc5) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \ - const type4 &tv4, const type5 &tv5) \ - : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - init_##short_name3(tv3); \ - init_##short_name4(tv4); \ - init_##short_name5(tv5); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_PROP(type3, name3, short_name3, tc3) \ - E_PROP(type4, name4, short_name4, tc4) \ - E_PROP(type5, name5, short_name5, tc5) \ - E_END() - -#define E_SIMPLE6(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2, type3, name3, short_name3, \ - tc3, type4, name4, short_name4, tc4, type5, name5, \ - short_name5, tc5, type6, name6, short_name6, tc6) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \ - const type4 &tv4, const type5 &tv5, const type6 &tv6) \ - : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - init_##short_name3(tv3); \ - init_##short_name4(tv4); \ - init_##short_name5(tv5); \ - init_##short_name6(tv6); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_PROP(type3, name3, short_name3, tc3) \ - E_PROP(type4, name4, short_name4, tc4) \ - E_PROP(type5, name5, short_name5, tc5) \ - E_PROP(type6, name6, short_name6, tc6) \ - E_END() - -#define E_SIMPLE7(event_name, el, allow_async, type, name, short_name, tc, \ - type2, name2, short_name2, tc2, type3, name3, short_name3, \ - tc3, type4, name4, short_name4, tc4, type5, name5, \ - short_name5, tc5, type6, name6, short_name6, tc6, type7, \ - name7, short_name7, tc7) \ - E_BEGIN(event_name, el) \ - explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \ - const type4 &tv4, const type5 &tv5, const type6 &tv6, \ - const type7 &tv7) \ - : event(allow_async) { \ - init_##short_name(tv); \ - init_##short_name2(tv2); \ - init_##short_name3(tv3); \ - init_##short_name4(tv4); \ - init_##short_name5(tv5); \ - init_##short_name6(tv6); \ - init_##short_name7(tv7); \ - } \ - E_PROP(type, name, short_name, tc) \ - E_PROP(type2, name2, short_name2, tc2) \ - E_PROP(type3, name3, short_name3, tc3) \ - E_PROP(type4, name4, short_name4, tc4) \ - E_PROP(type5, name5, short_name5, tc5) \ - E_PROP(type6, name6, short_name6, tc6) \ - E_PROP(type7, name7, short_name7, tc7) \ - E_END() - -#define E_CONSUMER() \ -private: \ - std::vector> event_consumers_ - -#define E_CONSUMER_RELEASE() event_consumers_.clear() - -#define E_SUBSCRIBE(name, callback) \ - event_consumers_.emplace_back(std::make_shared( \ - #name, [this](const event &evt) { callback(evt); })) - -#define E_SUBSCRIBE_EXACT(name, callback) \ - event_consumers_.emplace_back(std::make_shared( \ - #name, [this](const event &evt) { \ - callback(dynamic_cast(evt)); \ - })) - -#define E_SUBSCRIBE_ALL(callback) \ - event_consumers_.emplace_back(std::make_shared( \ - [this](const event &evt) { callback(evt); })) -} // namespace repertory - -#endif // REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ +#define REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ + +namespace repertory { +class i_event; + +class event_system final { +private: + static constexpr const std::uint8_t max_queue_retry{ + 30U, + }; + + const std::uint32_t max_queue_size{ + std::thread::hardware_concurrency() * 4U, + }; + + static constexpr const std::chrono::seconds queue_wait_secs{ + 5s, + }; + +public: + event_system(const event_system &) = delete; + event_system(event_system &&) = delete; + auto operator=(const event_system &) -> event_system & = delete; + auto operator=(event_system &&) -> event_system & = delete; + +protected: + event_system() = default; + + ~event_system() { stop(); } + +public: + class event_consumer final { + public: + explicit event_consumer(std::function callback) + : callback_(std::move(callback)) { + event_system::instance().attach(this); + } + + event_consumer(std::string_view event_name, + std::function callback) + : callback_(std::move(callback)) { + event_system::instance().attach(event_name, this); + } + + ~event_consumer() { event_system::instance().release(this); } + + public: + event_consumer(const event_consumer &) = delete; + event_consumer(event_consumer &&) = delete; + auto operator=(const event_consumer &) -> event_consumer & = delete; + auto operator=(event_consumer &&) -> event_consumer & = delete; + + private: + std::function callback_; + + public: + void notify_event(const i_event &event) { callback_(event); } + }; + +private: + static event_system instance_; + +public: + [[nodiscard]] static auto instance() -> event_system &; + +private: + std::unordered_map> + event_consumers_; + std::recursive_mutex consumer_mutex_; + std::vector> event_list_; + std::condition_variable event_notify_; + std::mutex event_mutex_; + std::unique_ptr event_thread_; + std::mutex run_mutex_; + stop_type stop_requested_{false}; + +private: + [[nodiscard]] auto get_stop_requested() const -> bool; + + void process_events(); + + void queue_event(std::shared_ptr evt); + +public: + void attach(event_consumer *consumer); + + void attach(std::string_view event_name, event_consumer *consumer); + + template void raise(arg_t &&...args) { + queue_event(std::make_shared(std::forward(args)...)); + } + + void release(event_consumer *consumer); + + void start(); + + void stop(); +}; + +using event_consumer = event_system::event_consumer; + +#define E_CONSUMER() \ +private: \ + std::vector> event_consumers_ + +#define E_CONSUMER_RELEASE() event_consumers_.clear() + +#define E_SUBSCRIBE(event, callback) \ + event_consumers_.emplace_back(std::make_shared( \ + event::name, [this](const i_event &evt) { \ + callback(dynamic_cast(evt)); \ + })) + +#define E_SUBSCRIBE_ALL(callback) \ + event_consumers_.emplace_back(std::make_shared( \ + [this](const i_event &evt) { callback(evt); })) +} // namespace repertory + +#endif // REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM_HPP_ diff --git a/repertory/librepertory/include/events/events.hpp b/repertory/librepertory/include/events/events.hpp deleted file mode 100644 index de5b5596..00000000 --- a/repertory/librepertory/include/events/events.hpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_EVENTS_EVENTS_HPP_ -#define REPERTORY_INCLUDE_EVENTS_EVENTS_HPP_ - -#include "events/event_system.hpp" -#include "types/repertory.hpp" -#include "utils/utils.hpp" - -namespace repertory { -// clang-format off -E_SIMPLE2(curl_error, error, true, - std::string, url, url, E_FROM_STRING, - CURLcode, res, res, E_FROM_CURL_CODE -); - -E_SIMPLE3(debug_log, debug, true, - std::string, function, func, E_FROM_STRING, - std::string, api_path, ap, E_FROM_STRING, - std::string, data, data, E_FROM_STRING -); - -E_SIMPLE1(directory_removed, info, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE2(directory_removed_externally, warn, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE2(directory_remove_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE2(drive_mount_failed, error, true, - std::string, location, loc, E_FROM_STRING, - std::string, result, res, E_FROM_STRING -); - -E_SIMPLE1(drive_mounted, info, true, - std::string, location, loc, E_FROM_STRING -); - -E_SIMPLE1(drive_mount_result, info, true, - std::string, result, res, E_FROM_STRING -); - -E_SIMPLE1(drive_unmount_pending, info, true, - std::string, location, loc, E_FROM_STRING -); - -E_SIMPLE1(drive_unmounted, info, true, - std::string, location, loc, E_FROM_STRING -); - -E_SIMPLE1(event_level_changed, info, true, - std::string, new_event_level, level, E_FROM_STRING -); - -E_SIMPLE1(failed_upload_queued, error, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE1(failed_upload_removed, warn, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE1(failed_upload_retry, info, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE2(file_get_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE1(file_get_api_list_failed, error, true, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE1(file_pinned, info, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE3(file_read_bytes_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, error, err, E_FROM_STRING, - std::size_t, retry, retry, E_FROM_SIZE_T -); - -E_SIMPLE1(file_removed, debug, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE2(file_removed_externally, warn, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE2(file_remove_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE3(file_rename_failed, error, true, - std::string, from_api_path, FROM, E_FROM_STRING, - std::string, to_api_path, TO, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE2(file_get_size_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE3(filesystem_item_added, debug, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, parent, parent, E_FROM_STRING, - bool, directory, dir, E_FROM_BOOL -); - -E_SIMPLE4(filesystem_item_closed, trace, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - bool, directory, dir, E_FROM_BOOL, - bool, changed, changed, E_FROM_BOOL -); - -E_SIMPLE5(filesystem_item_handle_closed, trace, true, - std::string, api_path, ap, E_FROM_STRING, - std::uint64_t, handle, handle, E_FROM_UINT64, - std::string, source, src, E_FROM_STRING, - bool, directory, dir, E_FROM_BOOL, - bool, changed, changed, E_FROM_BOOL -); - -E_SIMPLE4(filesystem_item_handle_opened, trace, true, - std::string, api_path, ap, E_FROM_STRING, - std::uint64_t, handle, handle, E_FROM_UINT64, - std::string, source, src, E_FROM_STRING, - bool, directory, dir, E_FROM_BOOL -); - -E_SIMPLE2(filesystem_item_evicted, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE3(filesystem_item_opened, trace, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - bool, directory, dir, E_FROM_BOOL -); - -E_SIMPLE1(file_unpinned, info, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE4(file_upload_completed, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - api_error, result, res, E_FROM_API_FILE_ERROR, - bool, cancelled, cancel, E_FROM_BOOL -); - -E_SIMPLE3(file_upload_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE2(file_upload_not_found, warn, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE2(file_upload_queued, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE1(file_upload_removed, debug, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE3(file_upload_retry, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - api_error, result, res, E_FROM_API_FILE_ERROR -); - -E_SIMPLE2(file_upload_started, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE1(orphaned_file_deleted, warn, true, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE1(orphaned_file_detected, warn, true, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE3(orphaned_file_processing_failed, error, true, - std::string, source, src, E_FROM_STRING, - std::string, dest, dest, E_FROM_STRING, - std::string, result, res, E_FROM_STRING -); - -E_SIMPLE1(orphaned_source_file_detected, info, true, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE1(orphaned_source_file_removed, info, true, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE1(polling_item_begin, debug, true, - std::string, item_name, item, E_FROM_STRING -); - -E_SIMPLE1(polling_item_end, debug, true, - std::string, item_name, item, E_FROM_STRING -); - -E_SIMPLE2(provider_offline, error, true, - std::string, host_name_or_ip, host, E_FROM_STRING, - std::uint16_t, port, port, E_FROM_UINT16 -); - -E_SIMPLE2(provider_upload_begin, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING -); - -E_SIMPLE3(provider_upload_end, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - api_error, result, res, E_FROM_API_FILE_ERROR -); - -E_SIMPLE2(repertory_exception, error, true, - std::string, function, func, E_FROM_STRING, - std::string, message, msg, E_FROM_STRING -); - -E_SIMPLE1(rpc_server_exception, error, true, - std::string, exception, exception, E_FROM_STRING -); - -E_SIMPLE1(service_shutdown_begin, debug, true, - std::string, service, svc, E_FROM_STRING -); - -E_SIMPLE1(service_shutdown_end, debug, true, - std::string, service, svc, E_FROM_STRING -); - -E_SIMPLE1(service_started, debug, true, - std::string, service, svc, E_FROM_STRING -); - -E_SIMPLE(unmount_requested, info, true); -#if !defined(_WIN32) -E_SIMPLE2(unmount_result, info, true, - std::string, location, loc, E_FROM_STRING, - std::string, result, res, E_FROM_STRING -); -#endif -// clang-format on -} // namespace repertory - -#endif // REPERTORY_INCLUDE_EVENTS_EVENTS_HPP_ diff --git a/repertory/librepertory/src/events/t_event_system.cpp b/repertory/librepertory/include/events/i_event.hpp similarity index 69% rename from repertory/librepertory/src/events/t_event_system.cpp rename to repertory/librepertory/include/events/i_event.hpp index d72df0fc..ae70fe5e 100644 --- a/repertory/librepertory/src/events/t_event_system.cpp +++ b/repertory/librepertory/include/events/i_event.hpp @@ -1,36 +1,40 @@ -/* - Copyright <2018-2024> - - 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 "events/t_event_system.hpp" - -#include "events/event.hpp" - -namespace repertory { -template -auto t_event_system::instance() -> t_event_system & { - return event_system_; -} - -template -t_event_system t_event_system::event_system_; - -template class t_event_system; -} // namespace repertory +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_I_EVENT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_I_EVENT_HPP_ + +#include "types/repertory.hpp" + +namespace repertory { +class i_event { + INTERFACE_SETUP(i_event); + +public: + [[nodiscard]] virtual auto get_event_level() const -> event_level = 0; + + [[nodiscard]] virtual auto get_name() const -> std::string_view = 0; + + [[nodiscard]] virtual auto get_single_line() const -> std::string = 0; +}; +} // namespace repertory + +#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_ diff --git a/repertory/librepertory/include/events/t_event_system.hpp b/repertory/librepertory/include/events/t_event_system.hpp deleted file mode 100644 index 6294baa5..00000000 --- a/repertory/librepertory/include/events/t_event_system.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ -#define REPERTORY_INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ - -#include "events/event.hpp" -#include "utils/collection.hpp" -#include "utils/utils.hpp" - -namespace repertory { -template class t_event_system final { -public: - t_event_system(const t_event_system &) = delete; - t_event_system(t_event_system &&) = delete; - auto operator=(const t_event_system &) -> t_event_system & = delete; - auto operator=(t_event_system &&) -> t_event_system & = delete; - -protected: - t_event_system() = default; - - ~t_event_system() { stop(); } - -public: - class event_consumer final { - public: - explicit event_consumer(std::function callback) - : callback_(std::move(callback)) { - t_event_system::instance().attach(this); - } - - event_consumer(const std::string &event_name, - std::function callback) - : callback_(std::move(callback)) { - t_event_system::instance().attach(event_name, this); - } - - ~event_consumer() { t_event_system::instance().release(this); } - - public: - event_consumer(const event_consumer &) = delete; - event_consumer(event_consumer &&) = delete; - auto operator=(const event_consumer &) -> event_consumer & = delete; - auto operator=(event_consumer &&) -> event_consumer & = delete; - - private: - std::function callback_; - - public: - void notify_event(const event &event) { callback_(event); } - }; - -private: - static t_event_system event_system_; - -public: - static auto instance() -> t_event_system &; - -private: - std::unordered_map> - event_consumers_; - std::recursive_mutex consumer_mutex_; - std::vector> event_list_; - std::condition_variable event_notify_; - std::mutex event_mutex_; - std::unique_ptr event_thread_; - std::mutex run_mutex_; - stop_type stop_requested_ = false; - -private: - void process_events() { - std::vector> events; - { - unique_mutex_lock lock(event_mutex_); - if (not stop_requested_ && event_list_.empty()) { - event_notify_.wait_for(lock, 1s); - } - - if (not event_list_.empty()) { - events.insert(events.end(), event_list_.begin(), event_list_.end()); - event_list_.clear(); - } - } - - const auto notify_events = [this](const std::string &name, - const event_type &event) { - std::deque> futures; - recur_mutex_lock lock(consumer_mutex_); - if (event_consumers_.find(name) != event_consumers_.end()) { - for (auto *consumer : event_consumers_[name]) { - if (event.get_allow_async()) { - futures.emplace_back( - std::async(std::launch::async, [consumer, &event]() { - consumer->notify_event(event); - })); - } else { - consumer->notify_event(event); - } - } - } - - while (not futures.empty()) { - futures.front().get(); - futures.pop_front(); - } - }; - - for (const auto &evt : events) { - notify_events("", *evt.get()); - notify_events(evt->get_name(), *evt.get()); - } - } - - void queue_event(std::shared_ptr evt) { - mutex_lock lock(event_mutex_); - event_list_.push_back(std::move(evt)); - event_notify_.notify_all(); - } - -public: - void attach(event_consumer *consumer) { - recur_mutex_lock lock(consumer_mutex_); - event_consumers_[""].push_back(consumer); - } - - void attach(const std::string &event_name, event_consumer *consumer) { - recur_mutex_lock lock(consumer_mutex_); - event_consumers_[event_name].push_back(consumer); - } - - template void raise(arg_t &&...args) { - queue_event(std::make_shared(std::forward(args)...)); - } - - void release(event_consumer *consumer) { - recur_mutex_lock lock(consumer_mutex_); - auto iter = std::find_if(event_consumers_.begin(), event_consumers_.end(), - [&](const auto &item) -> bool { - return utils::collection::includes(item.second, - consumer); - }); - - if (iter != event_consumers_.end()) { - utils::collection::remove_element((*iter).second, consumer); - } - } - - void start() { - mutex_lock lock(run_mutex_); - if (not event_thread_) { - stop_requested_ = false; - event_thread_ = std::make_unique([this]() { - while (not stop_requested_) { - process_events(); - } - }); - } - } - - void stop() { - mutex_lock lock(run_mutex_); - if (event_thread_) { - stop_requested_ = true; - event_notify_.notify_all(); - - event_thread_->join(); - event_thread_.reset(); - - process_events(); - } - } -}; -} // namespace repertory - -#endif // REPERTORY_INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_ diff --git a/repertory/librepertory/include/events/types/curl_error.hpp b/repertory/librepertory/include/events/types/curl_error.hpp new file mode 100644 index 00000000..6d6a547e --- /dev/null +++ b/repertory/librepertory/include/events/types/curl_error.hpp @@ -0,0 +1,74 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct curl_error final : public i_event { + curl_error() = default; + curl_error(CURLcode code_, std::string_view function_name_, std::string url_) + : code(code_), + function_name(std::string{function_name_}), + url(std::move(url_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"curl_error"}; + + CURLcode code{}; + std::string function_name; + std::string url; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|url|{}|code|{}", name, function_name, url, + static_cast(code)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::curl_error &value) { + data["code"] = value.code; + data["function_name"] = value.function_name; + data["url"] = value.url; + } + + static void from_json(const json &data, repertory::curl_error &value) { + data.at("code").get_to(value.code); + data.at("function_name").get_to(value.function_name); + data.at("url").get_to(value.url); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_ diff --git a/repertory/librepertory/include/events/types/debug_log.hpp b/repertory/librepertory/include/events/types/debug_log.hpp new file mode 100644 index 00000000..a5a29da7 --- /dev/null +++ b/repertory/librepertory/include/events/types/debug_log.hpp @@ -0,0 +1,68 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct debug_log final : public i_event { + debug_log() = default; + debug_log(std::string_view function_name_, std::string msg_) + : function_name(std::string(function_name_)), msg(std::move(msg_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"debug_log"}; + + std::string function_name; + std::string msg; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|msg|{}", name, function_name, msg); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::debug_log &value) { + data["function_name"] = value.function_name; + data["msg"] = value.msg; + } + + static void from_json(const json &data, repertory::debug_log &value) { + data.at("function_name").get_to(value.function_name); + data.at("msg").get_to(value.msg); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_ diff --git a/repertory/librepertory/include/events/types/directory_remove_failed.hpp b/repertory/librepertory/include/events/types/directory_remove_failed.hpp new file mode 100644 index 00000000..b79316e2 --- /dev/null +++ b/repertory/librepertory/include/events/types/directory_remove_failed.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct directory_remove_failed final : public i_event { + directory_remove_failed() = default; + directory_remove_failed(std::string api_path_, api_error error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + error(error_), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"directory_remove_failed"}; + + std::string api_path; + api_error error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name, + api_path, api_error_to_string(error)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::directory_remove_failed &value) { + data["api_path"] = value.api_path; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::directory_remove_failed &value) { + data.at("api_path").get_to(value.api_path); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/directory_removed.hpp b/repertory/librepertory/include/events/types/directory_removed.hpp new file mode 100644 index 00000000..862d87fa --- /dev/null +++ b/repertory/librepertory/include/events/types/directory_removed.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct directory_removed final : public i_event { + directory_removed() = default; + directory_removed(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"directory_removed"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::directory_removed &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::directory_removed &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_ diff --git a/repertory/librepertory/include/events/types/directory_removed_externally.hpp b/repertory/librepertory/include/events/types/directory_removed_externally.hpp new file mode 100644 index 00000000..483e376d --- /dev/null +++ b/repertory/librepertory/include/events/types/directory_removed_externally.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct directory_removed_externally final : public i_event { + directory_removed_externally() = default; + directory_removed_externally(std::string api_path_, + std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"directory_removed_externally"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|src|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::directory_removed_externally &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::directory_removed_externally &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_ diff --git a/repertory/librepertory/include/events/types/download_begin.hpp b/repertory/librepertory/include/events/types/download_begin.hpp new file mode 100644 index 00000000..26be0adf --- /dev/null +++ b/repertory/librepertory/include/events/types/download_begin.hpp @@ -0,0 +1,75 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_BEGIN_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_BEGIN_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_begin final : public i_event { + download_begin() = default; + download_begin(std::string api_path_, std::string dest_path_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"download_begin"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}", name, function_name, api_path, + dest_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::download_begin &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::download_begin &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_BEGIN_HPP_ diff --git a/repertory/librepertory/include/events/types/download_end.hpp b/repertory/librepertory/include/events/types/download_end.hpp new file mode 100644 index 00000000..ac74e33e --- /dev/null +++ b/repertory/librepertory/include/events/types/download_end.hpp @@ -0,0 +1,80 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_END_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_END_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_end final : public i_event { + download_end() = default; + download_end(std::string api_path_, std::string dest_path_, api_error error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + error(error_), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"download_end"}; + + std::string api_path; + std::string dest_path; + api_error error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}|error|{}", name, function_name, + api_path, dest_path, api_error_to_string(error)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::download_end &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::download_end &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_END_HPP_ diff --git a/repertory/librepertory/include/events/types/download_progress.hpp b/repertory/librepertory/include/events/types/download_progress.hpp new file mode 100644 index 00000000..289cf6fb --- /dev/null +++ b/repertory/librepertory/include/events/types/download_progress.hpp @@ -0,0 +1,79 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_PROGRESS_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_PROGRESS_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_progress final : public i_event { + download_progress() = default; + download_progress(std::string api_path_, std::string dest_path_, + std::string_view function_name_, double progress_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)), + progress(progress_) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"download_progress"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + double progress{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}|prog|{}", name, function_name, + api_path, dest_path, progress); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::download_progress &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + data["progress"] = value.progress; + } + + static void from_json(const json &data, repertory::download_progress &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + data.at("progress").get_to(value.progress); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_PROGRESS_HPP_ diff --git a/repertory/librepertory/include/events/types/download_restore_failed.hpp b/repertory/librepertory/include/events/types/download_restore_failed.hpp new file mode 100644 index 00000000..f75b6b59 --- /dev/null +++ b/repertory/librepertory/include/events/types/download_restore_failed.hpp @@ -0,0 +1,81 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORE_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORE_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_restore_failed final : public i_event { + download_restore_failed() = default; + download_restore_failed(std::string api_path_, std::string dest_path_, + std::string error_, std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + error(std::move(error_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"download_restore_failed"}; + + std::string api_path; + std::string dest_path; + std::string error; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}|error|{}", name, function_name, + api_path, dest_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::download_restore_failed &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::download_restore_failed &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORE_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/download_restored.hpp b/repertory/librepertory/include/events/types/download_restored.hpp new file mode 100644 index 00000000..cfe17445 --- /dev/null +++ b/repertory/librepertory/include/events/types/download_restored.hpp @@ -0,0 +1,75 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_restored final : public i_event { + download_restored() = default; + download_restored(std::string api_path_, std::string dest_path_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"download_restored"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}", name, function_name, api_path, + dest_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::download_restored &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::download_restored &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESTORED_HPP_ diff --git a/repertory/librepertory/include/events/types/download_resume_add_failed.hpp b/repertory/librepertory/include/events/types/download_resume_add_failed.hpp new file mode 100644 index 00000000..6c044109 --- /dev/null +++ b/repertory/librepertory/include/events/types/download_resume_add_failed.hpp @@ -0,0 +1,82 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADD_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADD_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_resume_add_failed final : public i_event { + download_resume_add_failed() = default; + download_resume_add_failed(std::string api_path_, std::string dest_path_, + std::string error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + error(std::move(error_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"download_resume_add_failed"}; + + std::string api_path; + std::string dest_path; + std::string error; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}|error|{}", name, function_name, + api_path, dest_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::download_resume_add_failed &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::download_resume_add_failed &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADD_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/download_resume_added.hpp b/repertory/librepertory/include/events/types/download_resume_added.hpp new file mode 100644 index 00000000..054e3f1e --- /dev/null +++ b/repertory/librepertory/include/events/types/download_resume_added.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADDED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADDED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_resume_added final : public i_event { + download_resume_added() = default; + download_resume_added(std::string api_path_, std::string dest_path_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"download_resume_added"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}", name, function_name, api_path, + dest_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::download_resume_added &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::download_resume_added &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_ADDED_HPP_ diff --git a/repertory/librepertory/include/events/types/download_resume_removed.hpp b/repertory/librepertory/include/events/types/download_resume_removed.hpp new file mode 100644 index 00000000..f90f2df1 --- /dev/null +++ b/repertory/librepertory/include/events/types/download_resume_removed.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_REMOVED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_REMOVED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_resume_removed final : public i_event { + download_resume_removed() = default; + download_resume_removed(std::string api_path_, std::string dest_path_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"download_resume_removed"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}", name, function_name, api_path, + dest_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::download_resume_removed &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::download_resume_removed &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_RESUME_REMOVED_HPP_ diff --git a/repertory/librepertory/include/events/types/download_type_selected.hpp b/repertory/librepertory/include/events/types/download_type_selected.hpp new file mode 100644 index 00000000..56cad897 --- /dev/null +++ b/repertory/librepertory/include/events/types/download_type_selected.hpp @@ -0,0 +1,82 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_TYPE_SELECTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_TYPE_SELECTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct download_type_selected final : public i_event { + download_type_selected() = default; + download_type_selected(std::string api_path_, std::string dest_path_, + std::string_view function_name_, download_type type_) + : api_path(std::move(api_path_)), + dest_path(std::move(dest_path_)), + function_name(std::string(function_name_)), + type(type_) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"download_type_selected"}; + + std::string api_path; + std::string dest_path; + std::string function_name; + download_type type{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dp|{}|type|{}", name, function_name, + api_path, dest_path, download_type_to_string(type)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::download_type_selected &value) { + data["api_path"] = value.api_path; + data["dest_path"] = value.dest_path; + data["function_name"] = value.function_name; + data["type"] = repertory::download_type_to_string(value.type); + } + + static void from_json(const json &data, + repertory::download_type_selected &value) { + data.at("api_path").get_to(value.api_path); + data.at("dest_path").get_to(value.dest_path); + data.at("function_name").get_to(value.function_name); + value.type = repertory::download_type_from_string( + data.at("type").get()); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DOWNLOAD_TYPE_SELECTED_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_mount_failed.hpp b/repertory/librepertory/include/events/types/drive_mount_failed.hpp new file mode 100644 index 00000000..90a8f8dd --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_mount_failed.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_ +#if defined(_WIN32) + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_mount_failed final : public i_event { + drive_mount_failed() = default; + drive_mount_failed(NTSTATUS error_, std::string_view function_name_, + std::string mount_location_) + : error(error_), + function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"drive_mount_failed"}; + + NTSTATUS error{}; + std::string function_name; + std::string mount_location; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}|status|{}", name, function_name, + mount_location, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::drive_mount_failed &value) { + data["error"] = value.error; + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + } + + static void from_json(const json &data, + repertory::drive_mount_failed &value) { + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // defined(_WIN32) +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_mount_result.hpp b/repertory/librepertory/include/events/types/drive_mount_result.hpp new file mode 100644 index 00000000..5c240d77 --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_mount_result.hpp @@ -0,0 +1,76 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_mount_result final : public i_event { + drive_mount_result() = default; + drive_mount_result(std::string_view function_name_, + std::string mount_location_, std::string result_) + : function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)), + result(std::move(result_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"drive_mount_result"}; + + std::string function_name; + std::string mount_location; + std::string result; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}|result|{}", name, function_name, + mount_location, result); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::drive_mount_result &value) { + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + data["result"] = value.result; + } + + static void from_json(const json &data, + repertory::drive_mount_result &value) { + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + data.at("result").get_to(value.result); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_mounted.hpp b/repertory/librepertory/include/events/types/drive_mounted.hpp new file mode 100644 index 00000000..44b5a157 --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_mounted.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_mounted final : public i_event { + drive_mounted() = default; + drive_mounted(std::string_view function_name_, std::string mount_location_) + : function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"drive_mounted"}; + + std::string function_name; + std::string mount_location; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}", name, function_name, + mount_location); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::drive_mounted &value) { + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + } + + static void from_json(const json &data, repertory::drive_mounted &value) { + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_stop_timed_out.hpp b/repertory/librepertory/include/events/types/drive_stop_timed_out.hpp new file mode 100644 index 00000000..fb50eb62 --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_stop_timed_out.hpp @@ -0,0 +1,67 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_STOP_TIMED_OUT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_STOP_TIMED_OUT_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_stop_timed_out final : public i_event { + drive_stop_timed_out() = default; + drive_stop_timed_out(std::string_view function_name_) + : function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"drive_stop_timed_out"}; + + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}", name, function_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::drive_stop_timed_out &value) { + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::drive_stop_timed_out &value) { + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_STOP_TIMED_OUT_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_unmount_pending.hpp b/repertory/librepertory/include/events/types/drive_unmount_pending.hpp new file mode 100644 index 00000000..f0d0c82b --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_unmount_pending.hpp @@ -0,0 +1,73 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNT_PENDING_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNT_PENDING_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_unmount_pending final : public i_event { + drive_unmount_pending() = default; + drive_unmount_pending(std::string_view function_name_, + std::string mount_location_) + : function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"drive_unmount_pending"}; + + std::string function_name; + std::string mount_location; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}", name, function_name, + mount_location); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::drive_unmount_pending &value) { + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + } + + static void from_json(const json &data, + repertory::drive_unmount_pending &value) { + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNT_PENDING_HPP_ diff --git a/repertory/librepertory/include/events/types/drive_unmounted.hpp b/repertory/librepertory/include/events/types/drive_unmounted.hpp new file mode 100644 index 00000000..8ae128a3 --- /dev/null +++ b/repertory/librepertory/include/events/types/drive_unmounted.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct drive_unmounted final : public i_event { + drive_unmounted() = default; + drive_unmounted(std::string_view function_name_, std::string mount_location_) + : function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"drive_unmounted"}; + + std::string function_name; + std::string mount_location; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}", name, function_name, + mount_location); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::drive_unmounted &value) { + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + } + + static void from_json(const json &data, repertory::drive_unmounted &value) { + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_UNMOUNTED_HPP_ diff --git a/repertory/librepertory/include/events/types/event_level_changed.hpp b/repertory/librepertory/include/events/types/event_level_changed.hpp new file mode 100644 index 00000000..4ebac75e --- /dev/null +++ b/repertory/librepertory/include/events/types/event_level_changed.hpp @@ -0,0 +1,71 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_EVENT_LEVEL_CHANGED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_EVENT_LEVEL_CHANGED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct event_level_changed final : public i_event { + event_level_changed() = default; + event_level_changed(std::string_view function_name_, event_level new_level_) + : function_name(std::string(function_name_)), new_level(new_level_) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"event_level_changed"}; + + std::string function_name; + event_level new_level{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|level|{}", name, function_name, + event_level_to_string(new_level)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::event_level_changed &value) { + data["new_level"] = repertory::event_level_to_string(value.new_level); + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::event_level_changed &value) { + value.new_level = repertory::event_level_from_string( + data.at("new_level").get()); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_EVENT_LEVEL_CHANGED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_pinned.hpp b/repertory/librepertory/include/events/types/file_pinned.hpp new file mode 100644 index 00000000..5551c54d --- /dev/null +++ b/repertory/librepertory/include/events/types/file_pinned.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_PINNED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_PINNED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_pinned final : public i_event { + file_pinned() = default; + file_pinned(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"file_pinned"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_pinned &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::file_pinned &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_PINNED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_remove_failed.hpp b/repertory/librepertory/include/events/types/file_remove_failed.hpp new file mode 100644 index 00000000..ecf7a8c7 --- /dev/null +++ b/repertory/librepertory/include/events/types/file_remove_failed.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVE_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVE_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_remove_failed final : public i_event { + file_remove_failed() = default; + file_remove_failed(std::string api_path_, api_error error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + error(error_), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"file_remove_failed"}; + + std::string api_path; + api_error error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name, + api_path, api_error_to_string(error)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_remove_failed &value) { + data["api_path"] = value.api_path; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::file_remove_failed &value) { + data.at("api_path").get_to(value.api_path); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVE_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_removed.hpp b/repertory/librepertory/include/events/types/file_removed.hpp new file mode 100644 index 00000000..081587ae --- /dev/null +++ b/repertory/librepertory/include/events/types/file_removed.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_removed final : public i_event { + file_removed() = default; + file_removed(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"file_removed"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_removed &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::file_removed &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_removed_externally.hpp b/repertory/librepertory/include/events/types/file_removed_externally.hpp new file mode 100644 index 00000000..854f927c --- /dev/null +++ b/repertory/librepertory/include/events/types/file_removed_externally.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_EXTERNALLY_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_EXTERNALLY_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_removed_externally final : public i_event { + file_removed_externally() = default; + file_removed_externally(std::string api_path_, + std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"file_removed_externally"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|src|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::file_removed_externally &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::file_removed_externally &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_REMOVED_EXTERNALLY_HPP_ diff --git a/repertory/librepertory/include/events/types/file_unpinned.hpp b/repertory/librepertory/include/events/types/file_unpinned.hpp new file mode 100644 index 00000000..2675a805 --- /dev/null +++ b/repertory/librepertory/include/events/types/file_unpinned.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UNPINNED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UNPINNED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_unpinned final : public i_event { + file_unpinned() = default; + file_unpinned(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"file_unpinned"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_unpinned &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::file_unpinned &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UNPINNED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_completed.hpp b/repertory/librepertory/include/events/types/file_upload_completed.hpp new file mode 100644 index 00000000..2e8fb101 --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_completed.hpp @@ -0,0 +1,88 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_COMPLETED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_COMPLETED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_completed final : public i_event { + file_upload_completed() = default; + file_upload_completed(std::string api_path_, bool cancelled_, + api_error error_, std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + cancelled(cancelled_), + error(error_), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"file_upload_completed"}; + + std::string api_path; + bool cancelled{}; + api_error error{}; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|cancelled|{}|error|{}|sp|{}", name, + function_name, api_path, cancelled, + api_error_to_string(error), source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::file_upload_completed &value) { + data["api_path"] = value.api_path; + data["cancelled"] = value.cancelled; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::file_upload_completed &value) { + data.at("api_path").get_to(value.api_path); + data.at("cancelled").get_to(value.cancelled); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_COMPLETED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_failed.hpp b/repertory/librepertory/include/events/types/file_upload_failed.hpp new file mode 100644 index 00000000..d7232f5b --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_failed.hpp @@ -0,0 +1,80 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_failed final : public i_event { + file_upload_failed() = default; + file_upload_failed(std::string api_path_, std::string error_, + std::string_view function_name_, std::string source_path_) + : api_path(std::move(api_path_)), + error(std::move(error_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"file_upload_failed"}; + + std::string api_path; + std::string error; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}|sp|{}", name, function_name, + api_path, error, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_upload_failed &value) { + data["api_path"] = value.api_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::file_upload_failed &value) { + data.at("api_path").get_to(value.api_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_not_found.hpp b/repertory/librepertory/include/events/types/file_upload_not_found.hpp new file mode 100644 index 00000000..90c42ed4 --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_not_found.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_NOT_FOUND_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_NOT_FOUND_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_not_found final : public i_event { + file_upload_not_found() = default; + file_upload_not_found(std::string api_path_, std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"file_upload_not_found"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|sp|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::file_upload_not_found &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::file_upload_not_found &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_NOT_FOUND_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_queued.hpp b/repertory/librepertory/include/events/types/file_upload_queued.hpp new file mode 100644 index 00000000..efa3adae --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_queued.hpp @@ -0,0 +1,76 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_QUEUED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_QUEUED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_queued final : public i_event { + file_upload_queued() = default; + file_upload_queued(std::string api_path_, std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"file_upload_queued"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|sp|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_upload_queued &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::file_upload_queued &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_QUEUED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_removed.hpp b/repertory/librepertory/include/events/types/file_upload_removed.hpp new file mode 100644 index 00000000..e1b60dfd --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_removed.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_REMOVED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_REMOVED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_removed final : public i_event { + file_upload_removed() = default; + file_upload_removed(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"file_upload_removed"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_upload_removed &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::file_upload_removed &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_REMOVED_HPP_ diff --git a/repertory/librepertory/include/events/types/file_upload_retry.hpp b/repertory/librepertory/include/events/types/file_upload_retry.hpp new file mode 100644 index 00000000..50514b42 --- /dev/null +++ b/repertory/librepertory/include/events/types/file_upload_retry.hpp @@ -0,0 +1,80 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_RETRY_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_RETRY_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct file_upload_retry final : public i_event { + file_upload_retry() = default; + file_upload_retry(std::string api_path_, api_error error_, + std::string_view function_name_, std::string source_path_) + : api_path(std::move(api_path_)), + error(std::move(error_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"file_upload_retry"}; + + std::string api_path; + api_error error{}; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|sp|{}|error|{}", name, function_name, + api_path, source_path, api_error_to_string(error)); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::file_upload_retry &value) { + data["api_path"] = value.api_path; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, repertory::file_upload_retry &value) { + data.at("api_path").get_to(value.api_path); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILE_UPLOAD_RETRY_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_added.hpp b/repertory/librepertory/include/events/types/filesystem_item_added.hpp new file mode 100644 index 00000000..1b77df57 --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_added.hpp @@ -0,0 +1,81 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_ADDED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_ADDED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_added final : public i_event { + filesystem_item_added() = default; + filesystem_item_added(std::string api_parent_, std::string api_path_, + bool directory_, std::string_view function_name_) + : api_parent(std::move(api_parent_)), + api_path(std::move(api_path_)), + directory(directory_), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"filesystem_item_added"}; + + std::string api_parent; + std::string api_path; + bool directory{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|parent|{}|dir|{}", name, function_name, + api_path, api_parent, directory); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_added &value) { + data["api_parent"] = value.api_parent; + data["api_path"] = value.api_path; + data["directory"] = value.directory; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::filesystem_item_added &value) { + data.at("api_parent").get_to(value.api_parent); + data.at("api_path").get_to(value.api_path); + data.at("directory").get_to(value.directory); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_ADDED_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_closed.hpp b/repertory/librepertory/include/events/types/filesystem_item_closed.hpp new file mode 100644 index 00000000..22083891 --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_closed.hpp @@ -0,0 +1,87 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_CLOSED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_CLOSED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_closed final : public i_event { + filesystem_item_closed() = default; + filesystem_item_closed(std::string api_path_, bool changed_, bool directory_, + std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + changed(changed_), + directory(directory_), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::trace}; + static constexpr const std::string_view name{"filesystem_item_closed"}; + + std::string api_path; + bool changed{}; + bool directory{}; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|changed|{}|dir|{}|sp|{}", name, + function_name, api_path, changed, directory, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_closed &value) { + data["api_path"] = value.api_path; + data["changed"] = value.changed; + data["directory"] = value.directory; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::filesystem_item_closed &value) { + data.at("api_path").get_to(value.api_path); + data.at("changed").get_to(value.changed); + data.at("directory").get_to(value.directory); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_CLOSED_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_evicted.hpp b/repertory/librepertory/include/events/types/filesystem_item_evicted.hpp new file mode 100644 index 00000000..c58bbace --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_evicted.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_EVICTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_EVICTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_evicted final : public i_event { + filesystem_item_evicted() = default; + filesystem_item_evicted(std::string api_path_, + std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"filesystem_item_evicted"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|sp|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_evicted &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::filesystem_item_evicted &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_EVICTED_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_handle_closed.hpp b/repertory/librepertory/include/events/types/filesystem_item_handle_closed.hpp new file mode 100644 index 00000000..8930b19b --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_handle_closed.hpp @@ -0,0 +1,92 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_CLOSED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_CLOSED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_handle_closed final : public i_event { + filesystem_item_handle_closed() = default; + filesystem_item_handle_closed(std::string api_path_, bool changed_, + bool directory_, + std::string_view function_name_, + std::uint64_t handle_, std::string source_path_) + : api_path(std::move(api_path_)), + changed(changed_), + directory(directory_), + function_name(std::string(function_name_)), + handle(handle_), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::trace}; + static constexpr const std::string_view name{"filesystem_item_handle_closed"}; + + std::string api_path; + bool changed{}; + bool directory{}; + std::string function_name; + std::uint64_t handle{}; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|changed|{}|dir|{}|handle|{}|sp|{}", + name, function_name, api_path, changed, directory, + handle, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_handle_closed &value) { + data["api_path"] = value.api_path; + data["changed"] = value.changed; + data["directory"] = value.directory; + data["function_name"] = value.function_name; + data["handle"] = value.handle; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::filesystem_item_handle_closed &value) { + data.at("api_path").get_to(value.api_path); + data.at("changed").get_to(value.changed); + data.at("directory").get_to(value.directory); + data.at("function_name").get_to(value.function_name); + data.at("handle").get_to(value.handle); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_CLOSED_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_handle_opened.hpp b/repertory/librepertory/include/events/types/filesystem_item_handle_opened.hpp new file mode 100644 index 00000000..e61d6539 --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_handle_opened.hpp @@ -0,0 +1,86 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_OPENED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_OPENED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_handle_opened final : public i_event { + filesystem_item_handle_opened() = default; + filesystem_item_handle_opened(std::string api_path_, bool directory_, + std::string_view function_name_, + std::uint64_t handle_, std::string source_path_) + : api_path(std::move(api_path_)), + directory(directory_), + function_name(std::string(function_name_)), + handle(handle_), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::trace}; + static constexpr const std::string_view name{"filesystem_item_handle_opened"}; + + std::string api_path; + bool directory{}; + std::string function_name; + std::uint64_t handle{}; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dir|{}|handle|{}|sp|{}", name, + function_name, api_path, directory, handle, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_handle_opened &value) { + data["api_path"] = value.api_path; + data["directory"] = value.directory; + data["function_name"] = value.function_name; + data["handle"] = value.handle; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::filesystem_item_handle_opened &value) { + data.at("api_path").get_to(value.api_path); + data.at("directory").get_to(value.directory); + data.at("function_name").get_to(value.function_name); + data.at("handle").get_to(value.handle); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_HANDLE_OPENED_HPP_ diff --git a/repertory/librepertory/include/events/types/filesystem_item_opened.hpp b/repertory/librepertory/include/events/types/filesystem_item_opened.hpp new file mode 100644 index 00000000..b9f508d4 --- /dev/null +++ b/repertory/librepertory/include/events/types/filesystem_item_opened.hpp @@ -0,0 +1,82 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_OPENED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_OPENED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct filesystem_item_opened final : public i_event { + filesystem_item_opened() = default; + filesystem_item_opened(std::string api_path_, bool directory_, + std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + directory(directory_), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::trace}; + static constexpr const std::string_view name{"filesystem_item_opened"}; + + std::string api_path; + bool directory{}; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|dir|{}|sp|{}", name, function_name, + api_path, directory, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::filesystem_item_opened &value) { + data["api_path"] = value.api_path; + data["directory"] = value.directory; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::filesystem_item_opened &value) { + data.at("api_path").get_to(value.api_path); + data.at("directory").get_to(value.directory); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FILESYSTEM_ITEM_OPENED_HPP_ diff --git a/repertory/librepertory/include/events/types/fuse_args_parsed.hpp b/repertory/librepertory/include/events/types/fuse_args_parsed.hpp new file mode 100644 index 00000000..c38a71c2 --- /dev/null +++ b/repertory/librepertory/include/events/types/fuse_args_parsed.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_ARGS_PARSED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_ARGS_PARSED_HPP_ +#if !defined(_WIN32) + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct fuse_args_parsed final : public i_event { + fuse_args_parsed() = default; + fuse_args_parsed(std::string_view args_, std::string_view function_name_) + : args(std::move(args_)), function_name(std::string{function_name_}) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"fuse_args_parsed"}; + + std::string args; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|args|{}", name, function_name, args); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::fuse_args_parsed &value) { + data["args"] = value.args; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::fuse_args_parsed &value) { + data.at("args").get_to(value.args); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // !defined(_WIN32) +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_ARGS_PARSED_HPP_ diff --git a/repertory/librepertory/include/events/types/fuse_event.hpp b/repertory/librepertory/include/events/types/fuse_event.hpp new file mode 100644 index 00000000..5f50c7fa --- /dev/null +++ b/repertory/librepertory/include/events/types/fuse_event.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_EVENT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_EVENT_HPP_ +#if !defined(_WIN32) + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct fuse_event final : public i_event { + fuse_event() = default; + fuse_event(std::string_view api_path_, std::int32_t error_, + std::string_view function_name_) + : api_path(std::string{api_path_}), + error(error_), + function_name(std::string{function_name_}) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"fuse_event"}; + + std::string api_path; + std::int32_t error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name, + api_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::fuse_event &value) { + data["api_path"] = value.api_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::fuse_event &value) { + data.at("api_path").get_to(value.api_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // !defined(_WIN32) +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_FUSE_EVENT_HPP_ diff --git a/repertory/librepertory/include/events/types/invalid_cache_size.hpp b/repertory/librepertory/include/events/types/invalid_cache_size.hpp new file mode 100644 index 00000000..f47e1adb --- /dev/null +++ b/repertory/librepertory/include/events/types/invalid_cache_size.hpp @@ -0,0 +1,76 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_INVALID_CACHE_SIZE_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_INVALID_CACHE_SIZE_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct invalid_cache_size final : public i_event { + invalid_cache_size() = default; + invalid_cache_size(std::uint64_t cache_size_, std::string_view function_name_, + std::uint64_t invalid_size_) + : cache_size(cache_size_), + function_name(std::string{function_name_}), + invalid_size(invalid_size_) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"invalid_cache_size"}; + + std::uint64_t cache_size{}; + std::string function_name; + std::uint64_t invalid_size{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|size|{}|by|{}", name, function_name, + cache_size, invalid_size); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::invalid_cache_size &value) { + data["cache_size"] = value.cache_size; + data["function_name"] = value.function_name; + data["invalid_size"] = value.invalid_size; + } + + static void from_json(const json &data, + repertory::invalid_cache_size &value) { + data.at("cache_size").get_to(value.cache_size); + data.at("function_name").get_to(value.function_name); + data.at("invalid_size").get_to(value.invalid_size); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_INVALID_CACHE_SIZE_HPP_ diff --git a/repertory/librepertory/include/events/types/item_timeout.hpp b/repertory/librepertory/include/events/types/item_timeout.hpp new file mode 100644 index 00000000..f477e90b --- /dev/null +++ b/repertory/librepertory/include/events/types/item_timeout.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_ITEM_TIMEOUT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_ITEM_TIMEOUT_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct item_timeout final : public i_event { + item_timeout() = default; + item_timeout(std::string api_path_, std::string_view function_name_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::trace}; + static constexpr const std::string_view name{"item_timeout"}; + + std::string api_path; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::item_timeout &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::item_timeout &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_ITEM_TIMEOUT_HPP_ diff --git a/repertory/librepertory/include/events/types/max_cache_size_reached.hpp b/repertory/librepertory/include/events/types/max_cache_size_reached.hpp new file mode 100644 index 00000000..55d68dd3 --- /dev/null +++ b/repertory/librepertory/include/events/types/max_cache_size_reached.hpp @@ -0,0 +1,78 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_MAX_CACHE_SIZE_REACHED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_MAX_CACHE_SIZE_REACHED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct max_cache_size_reached final : public i_event { + max_cache_size_reached() = default; + max_cache_size_reached(std::uint64_t cache_size_, + std::string_view function_name_, + std::uint64_t max_cache_size_) + : cache_size(cache_size_), + function_name(std::string{function_name_}), + max_cache_size(max_cache_size_) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"max_cache_size_reached"}; + + std::uint64_t cache_size{}; + std::string function_name; + std::uint64_t max_cache_size{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|size|{}|max|{}", name, function_name, + cache_size, max_cache_size); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::max_cache_size_reached &value) { + data["cache_size"] = value.cache_size; + data["function_name"] = value.function_name; + data["max_cache_size"] = value.max_cache_size; + } + + static void from_json(const json &data, + repertory::max_cache_size_reached &value) { + data.at("cache_size").get_to(value.cache_size); + data.at("function_name").get_to(value.function_name); + data.at("max_cache_size").get_to(value.max_cache_size); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_MAX_CACHE_SIZE_REACHED_HPP_ diff --git a/repertory/librepertory/include/events/types/orphaned_file_detected.hpp b/repertory/librepertory/include/events/types/orphaned_file_detected.hpp new file mode 100644 index 00000000..99078f0b --- /dev/null +++ b/repertory/librepertory/include/events/types/orphaned_file_detected.hpp @@ -0,0 +1,72 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_DETECTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_DETECTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct orphaned_file_detected final : public i_event { + orphaned_file_detected() = default; + orphaned_file_detected(std::string_view function_name_, + std::string source_path_) + : function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"orphaned_file_detected"}; + + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|sp|{}", name, function_name, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::orphaned_file_detected &value) { + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::orphaned_file_detected &value) { + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_DETECTED_HPP_ diff --git a/repertory/librepertory/include/events/types/orphaned_file_processing_failed.hpp b/repertory/librepertory/include/events/types/orphaned_file_processing_failed.hpp new file mode 100644 index 00000000..0ec43dff --- /dev/null +++ b/repertory/librepertory/include/events/types/orphaned_file_processing_failed.hpp @@ -0,0 +1,84 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_PROCESSING_FAILED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_PROCESSING_FAILED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct orphaned_file_processing_failed final : public i_event { + orphaned_file_processing_failed() = default; + orphaned_file_processing_failed(std::string dest_path_, std::string error_, + std::string_view function_name_, + std::string source_path_) + : dest_path(std::move(dest_path_)), + error(std::move(error_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{ + "orphaned_file_processing_failed", + }; + + std::string dest_path; + std::string error; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|sp|{}|dp|{}|error|{}", name, function_name, + source_path, dest_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::orphaned_file_processing_failed &value) { + data["dest_path"] = value.dest_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::orphaned_file_processing_failed &value) { + data.at("dest_path").get_to(value.dest_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_FILE_PROCESSING_FAILED_HPP_ diff --git a/repertory/librepertory/include/events/types/orphaned_source_file_detected.hpp b/repertory/librepertory/include/events/types/orphaned_source_file_detected.hpp new file mode 100644 index 00000000..a51e6566 --- /dev/null +++ b/repertory/librepertory/include/events/types/orphaned_source_file_detected.hpp @@ -0,0 +1,72 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_DETECTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_DETECTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct orphaned_source_file_detected final : public i_event { + orphaned_source_file_detected() = default; + orphaned_source_file_detected(std::string_view function_name_, + std::string source_path_) + : function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"orphaned_source_file_detected"}; + + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|sp|{}", name, function_name, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::orphaned_source_file_detected &value) { + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::orphaned_source_file_detected &value) { + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_DETECTED_HPP_ diff --git a/repertory/librepertory/include/events/types/orphaned_source_file_removed.hpp b/repertory/librepertory/include/events/types/orphaned_source_file_removed.hpp new file mode 100644 index 00000000..289a577f --- /dev/null +++ b/repertory/librepertory/include/events/types/orphaned_source_file_removed.hpp @@ -0,0 +1,72 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_REMOVED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_REMOVED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct orphaned_source_file_removed final : public i_event { + orphaned_source_file_removed() = default; + orphaned_source_file_removed(std::string_view function_name_, + std::string source_path_) + : function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"orphaned_source_file_removed"}; + + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|sp|{}", name, function_name, source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::orphaned_source_file_removed &value) { + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::orphaned_source_file_removed &value) { + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_ORPHANED_SOURCE_FILE_REMOVED_HPP_ diff --git a/repertory/librepertory/include/events/types/packet_client_timeout.hpp b/repertory/librepertory/include/events/types/packet_client_timeout.hpp new file mode 100644 index 00000000..72596b60 --- /dev/null +++ b/repertory/librepertory/include/events/types/packet_client_timeout.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_PACKET_CLIENT_TIMEOUT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_PACKET_CLIENT_TIMEOUT_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct packet_client_timeout final : public i_event { + packet_client_timeout() = default; + packet_client_timeout(std::string event_name_, + std::string_view function_name_, std::string msg_) + : event_name(std::move(event_name_)), + function_name(std::string(function_name_)), + msg(std::move(msg_)) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"packet_client_timeout"}; + + std::string event_name; + std::string function_name; + std::string msg; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|event|{}|msg|{}", name, function_name, + event_name, msg); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::packet_client_timeout &value) { + data["event_name"] = value.event_name; + data["function_name"] = value.function_name; + data["msg"] = value.msg; + } + + static void from_json(const json &data, + repertory::packet_client_timeout &value) { + data.at("event_name").get_to(value.event_name); + data.at("function_name").get_to(value.function_name); + data.at("msg").get_to(value.msg); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_PACKET_CLIENT_TIMEOUT_HPP_ diff --git a/repertory/librepertory/include/events/types/polling_item_begin.hpp b/repertory/librepertory/include/events/types/polling_item_begin.hpp new file mode 100644 index 00000000..e2ae2a9a --- /dev/null +++ b/repertory/librepertory/include/events/types/polling_item_begin.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_BEGIN_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_BEGIN_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct polling_item_begin final : public i_event { + polling_item_begin() = default; + polling_item_begin(std::string_view function_name_, std::string item_name_) + : function_name(std::string(function_name_)), + item_name(std::move(item_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"polling_item_begin"}; + + std::string function_name; + std::string item_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|name|{}", name, function_name, item_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::polling_item_begin &value) { + data["function_name"] = value.function_name; + data["item_name"] = value.item_name; + } + + static void from_json(const json &data, + repertory::polling_item_begin &value) { + data.at("function_name").get_to(value.function_name); + data.at("item_name").get_to(value.item_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_BEGIN_HPP_ diff --git a/repertory/librepertory/include/events/types/polling_item_end.hpp b/repertory/librepertory/include/events/types/polling_item_end.hpp new file mode 100644 index 00000000..3da7e18f --- /dev/null +++ b/repertory/librepertory/include/events/types/polling_item_end.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_END_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_END_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct polling_item_end final : public i_event { + polling_item_end() = default; + polling_item_end(std::string_view function_name_, std::string item_name_) + : function_name(std::string(function_name_)), + item_name(std::move(item_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"polling_item_end"}; + + std::string function_name; + std::string item_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|name|{}", name, function_name, item_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::polling_item_end &value) { + data["function_name"] = value.function_name; + data["item_name"] = value.item_name; + } + + static void from_json(const json &data, repertory::polling_item_end &value) { + data.at("function_name").get_to(value.function_name); + data.at("item_name").get_to(value.item_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_POLLING_ITEM_END_HPP_ diff --git a/repertory/librepertory/include/events/types/provider_offline.hpp b/repertory/librepertory/include/events/types/provider_offline.hpp new file mode 100644 index 00000000..d55a3e7c --- /dev/null +++ b/repertory/librepertory/include/events/types/provider_offline.hpp @@ -0,0 +1,75 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_OFFLINE_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_OFFLINE_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct provider_offline final : public i_event { + provider_offline() = default; + provider_offline(std::string_view function_name_, + std::string host_name_or_ip_, std::uint16_t port_) + : function_name(std::string(function_name_)), + host_name_or_ip(std::move(host_name_or_ip_)), + port(port_) {} + + static constexpr const event_level level{event_level::warn}; + static constexpr const std::string_view name{"provider_offline"}; + + std::string function_name; + std::string host_name_or_ip; + std::uint16_t port{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|host|{}|port|{}", name, function_name, + host_name_or_ip, port); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::provider_offline &value) { + data["function_name"] = value.function_name; + data["host_name_or_ip"] = value.host_name_or_ip; + data["port"] = value.port; + } + + static void from_json(const json &data, repertory::provider_offline &value) { + data.at("function_name").get_to(value.function_name); + data.at("host_name_or_ip").get_to(value.host_name_or_ip); + data.at("port").get_to(value.port); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_OFFLINE_HPP_ diff --git a/repertory/librepertory/include/events/types/provider_upload_begin.hpp b/repertory/librepertory/include/events/types/provider_upload_begin.hpp new file mode 100644 index 00000000..9042e0b3 --- /dev/null +++ b/repertory/librepertory/include/events/types/provider_upload_begin.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_BEGIN_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_BEGIN_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct provider_upload_begin final : public i_event { + provider_upload_begin() = default; + provider_upload_begin(std::string api_path_, std::string_view function_name_, + std::string source_path_) + : api_path(std::move(api_path_)), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"provider_upload_begin"}; + + std::string api_path; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|sp|{}", name, function_name, api_path, + source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, + const repertory::provider_upload_begin &value) { + data["api_path"] = value.api_path; + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::provider_upload_begin &value) { + data.at("api_path").get_to(value.api_path); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_BEGIN_HPP_ diff --git a/repertory/librepertory/include/events/types/provider_upload_end.hpp b/repertory/librepertory/include/events/types/provider_upload_end.hpp new file mode 100644 index 00000000..3cee2a89 --- /dev/null +++ b/repertory/librepertory/include/events/types/provider_upload_end.hpp @@ -0,0 +1,81 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_END_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_END_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct provider_upload_end final : public i_event { + provider_upload_end() = default; + provider_upload_end(std::string api_path_, api_error error_, + std::string_view function_name_, std::string source_path_) + : api_path(std::move(api_path_)), + error(error_), + function_name(std::string(function_name_)), + source_path(std::move(source_path_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"provider_upload_end"}; + + std::string api_path; + api_error error{}; + std::string function_name; + std::string source_path; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}|sp|{}", name, function_name, + api_path, api_error_to_string(error), source_path); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::provider_upload_end &value) { + data["api_path"] = value.api_path; + data["error"] = repertory::api_error_to_string(value.error); + data["function_name"] = value.function_name; + data["source_path"] = value.source_path; + } + + static void from_json(const json &data, + repertory::provider_upload_end &value) { + data.at("api_path").get_to(value.api_path); + value.error = + repertory::api_error_from_string(data.at("error").get()); + data.at("function_name").get_to(value.function_name); + data.at("source_path").get_to(value.source_path); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_PROVIDER_UPLOAD_END_HPP_ diff --git a/repertory/librepertory/include/events/types/remote_server_event.hpp b/repertory/librepertory/include/events/types/remote_server_event.hpp new file mode 100644 index 00000000..52d456e6 --- /dev/null +++ b/repertory/librepertory/include/events/types/remote_server_event.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_REMOTE_SERVER_EVENT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_REMOTE_SERVER_EVENT_HPP_ + +#include "comm/packet/packet.hpp" +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct remote_server_event final : public i_event { + remote_server_event() = default; + remote_server_event(std::string api_path_, packet::error_type error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + error(error_), + function_name(std::string{function_name_}) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"remote_server_event"}; + + std::string api_path; + packet::error_type error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name, + api_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::remote_server_event &value) { + data["api_path"] = value.api_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, + repertory::remote_server_event &value) { + data.at("api_path").get_to(value.api_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_REMOTE_SERVER_EVENT_HPP_ diff --git a/repertory/librepertory/include/events/types/repertory_exception.hpp b/repertory/librepertory/include/events/types/repertory_exception.hpp new file mode 100644 index 00000000..8ffa1ecb --- /dev/null +++ b/repertory/librepertory/include/events/types/repertory_exception.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_REPERTORY_EXCEPTION_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_REPERTORY_EXCEPTION_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct repertory_exception final : public i_event { + repertory_exception() = default; + repertory_exception(std::string_view function_name_, std::string msg_) + : function_name(std::string(function_name_)), msg(std::move(msg_)) {} + + static constexpr const event_level level{event_level::error}; + static constexpr const std::string_view name{"repertory_exception"}; + + std::string function_name; + std::string msg; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|msg|{}", name, function_name, msg); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::repertory_exception &value) { + data["function_name"] = value.function_name; + data["msg"] = value.msg; + } + + static void from_json(const json &data, + repertory::repertory_exception &value) { + data.at("function_name").get_to(value.function_name); + data.at("msg").get_to(value.msg); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_REPERTORY_EXCEPTION_HPP_ diff --git a/repertory/librepertory/include/events/types/service_start_begin.hpp b/repertory/librepertory/include/events/types/service_start_begin.hpp new file mode 100644 index 00000000..74022c3e --- /dev/null +++ b/repertory/librepertory/include/events/types/service_start_begin.hpp @@ -0,0 +1,71 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_BEGIN_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_BEGIN_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct service_start_begin final : public i_event { + service_start_begin() = default; + service_start_begin(std::string_view function_name_, + std::string service_name_) + : function_name(std::string(function_name_)), + service_name(std::move(service_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"service_start_begin"}; + + std::string function_name; + std::string service_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|svc|{}", name, function_name, service_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::service_start_begin &value) { + data["function_name"] = value.function_name; + data["service_name"] = value.service_name; + } + + static void from_json(const json &data, + repertory::service_start_begin &value) { + data.at("function_name").get_to(value.function_name); + data.at("service_name").get_to(value.service_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_BEGIN_HPP_ diff --git a/repertory/librepertory/include/events/types/service_start_end.hpp b/repertory/librepertory/include/events/types/service_start_end.hpp new file mode 100644 index 00000000..7e9c2633 --- /dev/null +++ b/repertory/librepertory/include/events/types/service_start_end.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_END_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_END_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct service_start_end final : public i_event { + service_start_end() = default; + service_start_end(std::string_view function_name_, std::string service_name_) + : function_name(std::string(function_name_)), + service_name(std::move(service_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"service_start_end"}; + + std::string function_name; + std::string service_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|svc|{}", name, function_name, service_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::service_start_end &value) { + data["function_name"] = value.function_name; + data["service_name"] = value.service_name; + } + + static void from_json(const json &data, repertory::service_start_end &value) { + data.at("function_name").get_to(value.function_name); + data.at("service_name").get_to(value.service_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_START_END_HPP_ diff --git a/repertory/librepertory/include/events/types/service_stop_begin.hpp b/repertory/librepertory/include/events/types/service_stop_begin.hpp new file mode 100644 index 00000000..829bfe38 --- /dev/null +++ b/repertory/librepertory/include/events/types/service_stop_begin.hpp @@ -0,0 +1,70 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_BEGIN_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_BEGIN_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct service_stop_begin final : public i_event { + service_stop_begin() = default; + service_stop_begin(std::string_view function_name_, std::string service_name_) + : function_name(std::string(function_name_)), + service_name(std::move(service_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"service_stop_begin"}; + + std::string function_name; + std::string service_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|svc|{}", name, function_name, service_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::service_stop_begin &value) { + data["function_name"] = value.function_name; + data["service_name"] = value.service_name; + } + + static void from_json(const json &data, + repertory::service_stop_begin &value) { + data.at("function_name").get_to(value.function_name); + data.at("service_name").get_to(value.service_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_BEGIN_HPP_ diff --git a/repertory/librepertory/include/events/types/service_stop_end.hpp b/repertory/librepertory/include/events/types/service_stop_end.hpp new file mode 100644 index 00000000..be0b0611 --- /dev/null +++ b/repertory/librepertory/include/events/types/service_stop_end.hpp @@ -0,0 +1,69 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_END_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_END_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct service_stop_end final : public i_event { + service_stop_end() = default; + service_stop_end(std::string_view function_name_, std::string service_name_) + : function_name(std::string(function_name_)), + service_name(std::move(service_name_)) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"service_stop_end"}; + + std::string function_name; + std::string service_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|svc|{}", name, function_name, service_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::service_stop_end &value) { + data["function_name"] = value.function_name; + data["service_name"] = value.service_name; + } + + static void from_json(const json &data, repertory::service_stop_end &value) { + data.at("function_name").get_to(value.function_name); + data.at("service_name").get_to(value.service_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_SERVICE_STOP_END_HPP_ diff --git a/repertory/librepertory/include/events/types/unmount_requested.hpp b/repertory/librepertory/include/events/types/unmount_requested.hpp new file mode 100644 index 00000000..b1f274c8 --- /dev/null +++ b/repertory/librepertory/include/events/types/unmount_requested.hpp @@ -0,0 +1,65 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_REQUESTED_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_REQUESTED_HPP_ + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct unmount_requested final : public i_event { + unmount_requested() = default; + unmount_requested(std::string_view function_name_) + : function_name(std::string(function_name_)) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"unmount_requested"}; + + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}", name, function_name); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::unmount_requested &value) { + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::unmount_requested &value) { + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_REQUESTED_HPP_ diff --git a/repertory/librepertory/include/events/types/unmount_result.hpp b/repertory/librepertory/include/events/types/unmount_result.hpp new file mode 100644 index 00000000..a08da22f --- /dev/null +++ b/repertory/librepertory/include/events/types/unmount_result.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_RESULT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_RESULT_HPP_ +#if !defined(_WIN32) + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct unmount_result final : public i_event { + unmount_result() = default; + unmount_result(std::string_view function_name_, std::string mount_location_, + std::int32_t result_) + : function_name(std::string(function_name_)), + mount_location(std::move(mount_location_)), + result(result_) {} + + static constexpr const event_level level{event_level::info}; + static constexpr const std::string_view name{"unmount_result"}; + + std::string function_name; + std::string mount_location; + std::int32_t result{}; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|location|{}|result|{}", name, function_name, + mount_location, result); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::unmount_result &value) { + data["function_name"] = value.function_name; + data["mount_location"] = value.mount_location; + data["result"] = value.result; + } + + static void from_json(const json &data, repertory::unmount_result &value) { + data.at("function_name").get_to(value.function_name); + data.at("mount_location").get_to(value.mount_location); + data.at("result").get_to(value.result); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // defined(_WIN32) +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_UNMOUNT_RESULT_HPP_ diff --git a/repertory/librepertory/include/events/types/winfsp_event.hpp b/repertory/librepertory/include/events/types/winfsp_event.hpp new file mode 100644 index 00000000..638e2ce3 --- /dev/null +++ b/repertory/librepertory/include/events/types/winfsp_event.hpp @@ -0,0 +1,77 @@ +/* + Copyright <2018-2025> + + 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 REPERTORY_INCLUDE_EVENTS_TYPES_WINFSP_EVENT_HPP_ +#define REPERTORY_INCLUDE_EVENTS_TYPES_WINFSP_EVENT_HPP_ +#if defined(_WIN32) + +#include "events/i_event.hpp" +#include "types/repertory.hpp" + +namespace repertory { +struct winfsp_event final : public i_event { + winfsp_event() = default; + winfsp_event(std::string api_path_, NTSTATUS error_, + std::string_view function_name_) + : api_path(std::move(api_path_)), + error(error_), + function_name(std::string{function_name_}) {} + + static constexpr const event_level level{event_level::debug}; + static constexpr const std::string_view name{"winfsp_event"}; + + std::string api_path; + NTSTATUS error{}; + std::string function_name; + + [[nodiscard]] auto get_event_level() const -> event_level override { + return level; + } + + [[nodiscard]] auto get_name() const -> std::string_view override { + return name; + } + + [[nodiscard]] auto get_single_line() const -> std::string override { + return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name, + api_path, error); + } +}; +} // namespace repertory + +NLOHMANN_JSON_NAMESPACE_BEGIN +template <> struct adl_serializer { + static void to_json(json &data, const repertory::winfsp_event &value) { + data["api_path"] = value.api_path; + data["error"] = value.error; + data["function_name"] = value.function_name; + } + + static void from_json(const json &data, repertory::winfsp_event &value) { + data.at("api_path").get_to(value.api_path); + data.at("error").get_to(value.error); + data.at("function_name").get_to(value.function_name); + } +}; +NLOHMANN_JSON_NAMESPACE_END + +#endif // defined(_WIN32) +#endif // REPERTORY_INCLUDE_EVENTS_TYPES_WINFSP_EVENT_HPP_ diff --git a/repertory/librepertory/include/file_manager/cache_size_mgr.hpp b/repertory/librepertory/include/file_manager/cache_size_mgr.hpp index c1395404..7da3f278 100644 --- a/repertory/librepertory/include/file_manager/cache_size_mgr.hpp +++ b/repertory/librepertory/include/file_manager/cache_size_mgr.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,11 @@ namespace repertory { class app_config; class cache_size_mgr final { +private: + static constexpr const std::chrono::seconds cache_wait_secs{ + 5s, + }; + public: cache_size_mgr(const cache_size_mgr &) = delete; cache_size_mgr(cache_size_mgr &&) = delete; @@ -49,6 +54,9 @@ private: std::condition_variable notify_; stop_type stop_requested_{false}; +private: + [[nodiscard]] auto get_stop_requested() const -> bool; + public: [[nodiscard]] auto expand(std::uint64_t size) -> api_error; diff --git a/repertory/librepertory/include/file_manager/direct_open_file.hpp b/repertory/librepertory/include/file_manager/direct_open_file.hpp index e1b041dd..ff0eebbd 100644 --- a/repertory/librepertory/include/file_manager/direct_open_file.hpp +++ b/repertory/librepertory/include/file_manager/direct_open_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -42,8 +42,8 @@ public: direct_open_file(const direct_open_file &) noexcept = delete; direct_open_file(direct_open_file &&) noexcept = delete; auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete; - auto - operator=(const direct_open_file &) noexcept -> direct_open_file & = delete; + auto operator=(const direct_open_file &) noexcept + -> direct_open_file & = delete; private: std::array ring_data_; @@ -51,22 +51,26 @@ private: protected: [[nodiscard]] auto on_check_start() -> bool override; - [[nodiscard]] auto - on_chunk_downloaded(std::size_t /* chunk */, - const data_buffer & /* buffer */) -> api_error override { + [[nodiscard]] auto on_chunk_downloaded(std::size_t /* chunk */, + const data_buffer & /* buffer */) + -> api_error override { return api_error::success; } - [[nodiscard]] auto - on_read_chunk(std::size_t chunk, std::size_t read_size, - std::uint64_t read_offset, data_buffer &data, - std::size_t &bytes_read) -> api_error override; + [[nodiscard]] auto on_read_chunk(std::size_t chunk, std::size_t read_size, + std::uint64_t read_offset, data_buffer &data, + std::size_t &bytes_read) + -> api_error override; [[nodiscard]] auto use_buffer(std::size_t chunk, std::function func) -> api_error override; public: + [[nodiscard]] auto get_source_path() const -> std::string override { + return "direct"; + } + [[nodiscard]] auto native_operation(native_operation_callback /* callback */) -> api_error override { return api_error::not_supported; diff --git a/repertory/librepertory/include/file_manager/events.hpp b/repertory/librepertory/include/file_manager/events.hpp deleted file mode 100644 index 2e526e40..00000000 --- a/repertory/librepertory/include/file_manager/events.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_FILE_MANAGER_EVENTS_HPP_ -#define REPERTORY_INCLUDE_FILE_MANAGER_EVENTS_HPP_ - -#include "events/events.hpp" -#include "types/repertory.hpp" - -namespace repertory { -// clang-format off -E_SIMPLE2(download_begin, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING -); - -E_SIMPLE3(download_end, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING, - api_error, result, result, E_FROM_API_FILE_ERROR -); - -E_SIMPLE3(download_progress, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING, - double, progress, prog, E_FROM_DOUBLE_PRECISE -); - -E_SIMPLE2(download_restored, info, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING -); - -E_SIMPLE3(download_restore_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE3(download_resume_add_failed, error, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING, - std::string, error, err, E_FROM_STRING -); - -E_SIMPLE2(download_resume_added, debug, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING -); - -E_SIMPLE2(download_resume_removed, debug, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, dest_path, dest, E_FROM_STRING -); - -E_SIMPLE1(item_timeout, trace, true, - std::string, api_path, ap, E_FROM_STRING -); - -E_SIMPLE3(download_type_selected, debug, true, - std::string, api_path, ap, E_FROM_STRING, - std::string, source, src, E_FROM_STRING, - download_type, download_type, type, E_FROM_DOWNLOAD_TYPE -); -// clang-format on -} // namespace repertory - -#endif // REPERTORY_INCLUDE_FILE_MANAGER_EVENTS_HPP_ diff --git a/repertory/librepertory/include/file_manager/file_manager.hpp b/repertory/librepertory/include/file_manager/file_manager.hpp index f1ca770d..b27aee71 100644 --- a/repertory/librepertory/include/file_manager/file_manager.hpp +++ b/repertory/librepertory/include/file_manager/file_manager.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,7 @@ #include "db/i_file_mgr_db.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/file_upload_completed.hpp" #include "file_manager/i_file_manager.hpp" #include "file_manager/i_open_file.hpp" #include "file_manager/i_upload_manager.hpp" @@ -39,6 +39,11 @@ class i_provider; class file_manager final : public i_file_manager, public i_upload_manager { E_CONSUMER(); +private: + static constexpr const std::chrono::seconds queue_wait_secs{ + 5s, + }; + public: file_manager(app_config &config, i_provider &provider); @@ -72,15 +77,19 @@ private: void close_timed_out_files(); - auto get_open_file_by_handle(std::uint64_t handle) const + [[nodiscard]] auto get_open_file_by_handle(std::uint64_t handle) const -> std::shared_ptr; - auto get_open_file_count(const std::string &api_path) const -> std::size_t; + [[nodiscard]] auto get_open_file_count(const std::string &api_path) const + -> std::size_t; - auto open(const std::string &api_path, bool directory, - const open_file_data &ofd, std::uint64_t &handle, - std::shared_ptr &file, - std::shared_ptr closeable_file) -> api_error; + [[nodiscard]] auto get_stop_requested() const -> bool; + + [[nodiscard]] auto open(const std::string &api_path, bool directory, + const open_file_data &ofd, std::uint64_t &handle, + std::shared_ptr &file, + std::shared_ptr closeable_file) + -> api_error; void queue_upload(const std::string &api_path, const std::string &source_path, bool no_lock); diff --git a/repertory/librepertory/include/file_manager/i_file_manager.hpp b/repertory/librepertory/include/file_manager/i_file_manager.hpp index 972406ab..2cab28cf 100644 --- a/repertory/librepertory/include/file_manager/i_file_manager.hpp +++ b/repertory/librepertory/include/file_manager/i_file_manager.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/file_manager/i_open_file.hpp b/repertory/librepertory/include/file_manager/i_open_file.hpp index 871e3c6f..55743e1e 100644 --- a/repertory/librepertory/include/file_manager/i_open_file.hpp +++ b/repertory/librepertory/include/file_manager/i_open_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/file_manager/i_upload_manager.hpp b/repertory/librepertory/include/file_manager/i_upload_manager.hpp index 789c6488..e66d77d6 100644 --- a/repertory/librepertory/include/file_manager/i_upload_manager.hpp +++ b/repertory/librepertory/include/file_manager/i_upload_manager.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/file_manager/open_file.hpp b/repertory/librepertory/include/file_manager/open_file.hpp index a38d1ec3..eaf75c4b 100644 --- a/repertory/librepertory/include/file_manager/open_file.hpp +++ b/repertory/librepertory/include/file_manager/open_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -78,8 +78,8 @@ private: stop_type stop_requested_{false}; private: - [[nodiscard]] auto adjust_cache_size(std::uint64_t file_size, - bool shrink) -> api_error; + [[nodiscard]] auto adjust_cache_size(std::uint64_t file_size, bool shrink) + -> api_error; [[nodiscard]] auto check_start() -> api_error; @@ -88,6 +88,8 @@ private: void download_range(std::size_t begin_chunk, std::size_t end_chunk, bool should_reset); + [[nodiscard]] auto get_stop_requested() const -> bool; + void set_modified(); void set_read_state(std::size_t chunk); @@ -111,12 +113,12 @@ public: return true; } - [[nodiscard]] auto - native_operation(native_operation_callback callback) -> api_error override; + [[nodiscard]] auto native_operation(native_operation_callback callback) + -> api_error override; - [[nodiscard]] auto - native_operation(std::uint64_t new_file_size, - native_operation_callback callback) -> api_error override; + [[nodiscard]] auto native_operation(std::uint64_t new_file_size, + native_operation_callback callback) + -> api_error override; void remove(std::uint64_t handle) override; diff --git a/repertory/librepertory/include/file_manager/open_file_base.hpp b/repertory/librepertory/include/file_manager/open_file_base.hpp index baf824c2..df5d15be 100644 --- a/repertory/librepertory/include/file_manager/open_file_base.hpp +++ b/repertory/librepertory/include/file_manager/open_file_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -161,7 +161,7 @@ protected: void set_source_path(std::string source_path); - void wait_for_io(stop_type &stop_requested); + void wait_for_io(stop_type_callback stop_requested_cb); public: void add(std::uint64_t handle, open_file_data ofd) override; @@ -186,17 +186,17 @@ public: [[nodiscard]] auto get_handles() const -> std::vector override; - [[nodiscard]] auto - get_open_data() -> std::map & override; + [[nodiscard]] auto get_open_data() + -> std::map & override; [[nodiscard]] auto get_open_data() const -> const std::map & override; - [[nodiscard]] auto - get_open_data(std::uint64_t handle) -> open_file_data & override; + [[nodiscard]] auto get_open_data(std::uint64_t handle) + -> open_file_data & override; - [[nodiscard]] auto - get_open_data(std::uint64_t handle) const -> const open_file_data & override; + [[nodiscard]] auto get_open_data(std::uint64_t handle) const + -> const open_file_data & override; [[nodiscard]] auto get_open_file_count() const -> std::size_t override; diff --git a/repertory/librepertory/include/file_manager/ring_buffer_base.hpp b/repertory/librepertory/include/file_manager/ring_buffer_base.hpp index 5c2b1342..863f7a53 100644 --- a/repertory/librepertory/include/file_manager/ring_buffer_base.hpp +++ b/repertory/librepertory/include/file_manager/ring_buffer_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -44,8 +44,8 @@ public: ring_buffer_base(const ring_buffer_base &) noexcept = delete; ring_buffer_base(ring_buffer_base &&) noexcept = delete; auto operator=(ring_buffer_base &&) noexcept -> ring_buffer_base & = delete; - auto - operator=(const ring_buffer_base &) noexcept -> ring_buffer_base & = delete; + auto operator=(const ring_buffer_base &) noexcept + -> ring_buffer_base & = delete; public: static constexpr const auto min_ring_size{5U}; @@ -73,6 +73,8 @@ private: void update_position(std::size_t count, bool is_forward); + [[nodiscard]] auto get_stop_requested() const -> bool; + protected: [[nodiscard]] auto has_reader_thread() const -> bool { return reader_thread_ != nullptr; @@ -84,9 +86,9 @@ protected: [[nodiscard]] virtual auto on_check_start() -> bool = 0; - [[nodiscard]] virtual auto - on_chunk_downloaded(std::size_t chunk, - const data_buffer &buffer) -> api_error = 0; + [[nodiscard]] virtual auto on_chunk_downloaded(std::size_t chunk, + const data_buffer &buffer) + -> api_error = 0; [[nodiscard]] virtual auto on_read_chunk(std::size_t chunk, std::size_t read_size, @@ -94,8 +96,8 @@ protected: std::size_t &bytes_read) -> api_error = 0; [[nodiscard]] virtual auto - use_buffer(std::size_t chunk, - std::function func) -> api_error = 0; + use_buffer(std::size_t chunk, std::function func) + -> api_error = 0; public: auto close() -> bool override; @@ -139,9 +141,10 @@ public: void set_api_path(const std::string &api_path) override; - [[nodiscard]] auto - write(std::uint64_t /* write_offset */, const data_buffer & /* data */, - std::size_t & /* bytes_written */) -> api_error override { + [[nodiscard]] auto write(std::uint64_t /* write_offset */, + const data_buffer & /* data */, + std::size_t & /* bytes_written */) + -> api_error override { return api_error::not_supported; } }; diff --git a/repertory/librepertory/include/file_manager/ring_buffer_open_file.hpp b/repertory/librepertory/include/file_manager/ring_buffer_open_file.hpp index e5e7af1c..650e4562 100644 --- a/repertory/librepertory/include/file_manager/ring_buffer_open_file.hpp +++ b/repertory/librepertory/include/file_manager/ring_buffer_open_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/file_manager/upload.hpp b/repertory/librepertory/include/file_manager/upload.hpp index 8e64c5da..f7a22c8f 100644 --- a/repertory/librepertory/include/file_manager/upload.hpp +++ b/repertory/librepertory/include/file_manager/upload.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -47,8 +47,8 @@ private: private: bool cancelled_{false}; api_error error_{api_error::success}; - std::unique_ptr thread_; stop_type stop_requested_{false}; + std::unique_ptr thread_; private: void upload_thread(); diff --git a/repertory/librepertory/include/platform/platform.hpp b/repertory/librepertory/include/platform/platform.hpp index bc2a87d1..743a3587 100644 --- a/repertory/librepertory/include/platform/platform.hpp +++ b/repertory/librepertory/include/platform/platform.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/platform/unix_platform.hpp b/repertory/librepertory/include/platform/unix_platform.hpp index 2f41ca6c..158be5ad 100644 --- a/repertory/librepertory/include/platform/unix_platform.hpp +++ b/repertory/librepertory/include/platform/unix_platform.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/platform/win32_platform.hpp b/repertory/librepertory/include/platform/win32_platform.hpp index 2f63a32c..e4cf5136 100644 --- a/repertory/librepertory/include/platform/win32_platform.hpp +++ b/repertory/librepertory/include/platform/win32_platform.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/providers/base_provider.hpp b/repertory/librepertory/include/providers/base_provider.hpp index 6a104a88..292e4a58 100644 --- a/repertory/librepertory/include/providers/base_provider.hpp +++ b/repertory/librepertory/include/providers/base_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -53,19 +53,19 @@ private: i_file_manager *fm_{}; private: - void add_all_items(const stop_type &stop_requested); + void add_all_items(stop_type &stop_requested); void process_removed_directories(std::deque removed_list, - const stop_type &stop_requested); + stop_type &stop_requested); void process_removed_files(std::deque removed_list, - const stop_type &stop_requested); + stop_type &stop_requested); - void process_removed_items(const stop_type &stop_requested); + void process_removed_items(stop_type &stop_requested); - void remove_deleted_items(const stop_type &stop_requested); + void remove_deleted_items(stop_type &stop_requested); - void remove_unmatched_source_files(const stop_type &stop_requested); + void remove_unmatched_source_files(stop_type &stop_requested); protected: [[nodiscard]] static auto create_api_file(std::string path, std::string key, diff --git a/repertory/librepertory/include/providers/encrypt/encrypt_provider.hpp b/repertory/librepertory/include/providers/encrypt/encrypt_provider.hpp index da68ba8f..db4b4a3e 100644 --- a/repertory/librepertory/include/providers/encrypt/encrypt_provider.hpp +++ b/repertory/librepertory/include/providers/encrypt/encrypt_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -82,7 +82,7 @@ private: const encrypt_config &cfg, std::string &api_path) const -> bool; - void remove_deleted_files(const stop_type &stop_requested); + void remove_deleted_files(stop_type &stop_requested); public: [[nodiscard]] auto create_directory(const std::string &api_path, diff --git a/repertory/librepertory/include/providers/i_provider.hpp b/repertory/librepertory/include/providers/i_provider.hpp index a7a3d94b..7e4836da 100644 --- a/repertory/librepertory/include/providers/i_provider.hpp +++ b/repertory/librepertory/include/providers/i_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/providers/provider.hpp b/repertory/librepertory/include/providers/provider.hpp index 3070bbb2..0f6c1cab 100644 --- a/repertory/librepertory/include/providers/provider.hpp +++ b/repertory/librepertory/include/providers/provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/providers/s3/s3_provider.hpp b/repertory/librepertory/include/providers/s3/s3_provider.hpp index 343a3244..20804914 100644 --- a/repertory/librepertory/include/providers/s3/s3_provider.hpp +++ b/repertory/librepertory/include/providers/s3/s3_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -54,14 +54,18 @@ private: const std::string &object_name) const -> api_error; + [[nodiscard]] auto + create_directory_object(const std::string &api_path, + const std::string &object_name) const -> api_error; + + [[nodiscard]] auto create_directory_paths(const std::string &api_path, + const std::string &key) const + -> api_error; + [[nodiscard]] auto create_file_extra(const std::string &api_path, api_meta_map &meta) -> api_error override; - [[nodiscard]] auto create_path_directories(const std::string &api_path, - const std::string &key) const - -> api_error; - [[nodiscard]] auto decrypt_object_name(std::string &object_name) const -> api_error; @@ -85,6 +89,9 @@ private: return s3_config_; } + [[nodiscard]] auto set_meta_key(const std::string &api_path, + api_meta_map &meta) -> api_error; + protected: [[nodiscard]] auto create_directory_impl(const std::string &api_path, api_meta_map &meta) diff --git a/repertory/librepertory/include/providers/sia/sia_provider.hpp b/repertory/librepertory/include/providers/sia/sia_provider.hpp index ce411312..d4a07990 100644 --- a/repertory/librepertory/include/providers/sia/sia_provider.hpp +++ b/repertory/librepertory/include/providers/sia/sia_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/rpc/client/client.hpp b/repertory/librepertory/include/rpc/client/client.hpp index 8c2e2c86..b9b27c12 100644 --- a/repertory/librepertory/include/rpc/client/client.hpp +++ b/repertory/librepertory/include/rpc/client/client.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,18 +31,18 @@ public: private: const rpc_host_info host_info_; - std::atomic request_id_; + std::atomic request_id_{0U}; public: [[nodiscard]] auto get_drive_information() -> rpc_response; [[nodiscard]] auto get_config() -> rpc_response; - [[nodiscard]] auto - get_config_value_by_name(const std::string &name) -> rpc_response; + [[nodiscard]] auto get_config_value_by_name(const std::string &name) + -> rpc_response; - [[nodiscard]] auto - get_directory_items(const std::string &api_path) -> rpc_response; + [[nodiscard]] auto get_directory_items(const std::string &api_path) + -> rpc_response; [[nodiscard]] auto get_open_files() -> rpc_response; @@ -52,9 +52,9 @@ public: [[nodiscard]] auto pinned_status(const std::string &api_file) -> rpc_response; - [[nodiscard]] auto - set_config_value_by_name(const std::string &name, - const std::string &value) -> rpc_response; + [[nodiscard]] auto set_config_value_by_name(const std::string &name, + const std::string &value) + -> rpc_response; [[nodiscard]] auto unmount() -> rpc_response; diff --git a/repertory/librepertory/include/rpc/server/full_server.hpp b/repertory/librepertory/include/rpc/server/full_server.hpp index f9231c1d..99176efe 100644 --- a/repertory/librepertory/include/rpc/server/full_server.hpp +++ b/repertory/librepertory/include/rpc/server/full_server.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/rpc/server/server.hpp b/repertory/librepertory/include/rpc/server/server.hpp index 14d2ff84..48735e10 100644 --- a/repertory/librepertory/include/rpc/server/server.hpp +++ b/repertory/librepertory/include/rpc/server/server.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,12 +38,8 @@ private: std::unique_ptr server_; std::unique_ptr server_thread_; std::mutex start_stop_mutex_; - std::atomic started_ = false; private: - // [[nodiscard]] bool check_authorization(const httpserver::http_request - // &request); - [[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool; void handle_get_config(const httplib::Request &req, httplib::Response &res); diff --git a/repertory/librepertory/include/types/remote.hpp b/repertory/librepertory/include/types/remote.hpp index 2548dd85..b5bdc71c 100644 --- a/repertory/librepertory/include/types/remote.hpp +++ b/repertory/librepertory/include/types/remote.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/types/repertory.hpp b/repertory/librepertory/include/types/repertory.hpp index ba3e30ce..7a9d99e7 100644 --- a/repertory/librepertory/include/types/repertory.hpp +++ b/repertory/librepertory/include/types/repertory.hpp @@ -41,8 +41,10 @@ constexpr const auto default_task_wait_ms{100U}; constexpr const auto default_timeout_ms{60000U}; constexpr const auto max_orphaned_file_retention_days{std::uint16_t(31U)}; constexpr const auto max_ring_buffer_file_size{std::uint16_t(1024U)}; +constexpr const auto max_s3_object_name_length{1024U}; constexpr const auto min_cache_size_bytes{ - std::uint64_t(100UL * 1024UL * 1024UL)}; + std::uint64_t(100UL * 1024UL * 1024UL), +}; constexpr const auto min_download_timeout_secs{std::uint8_t(5U)}; constexpr const auto min_online_check_retry_secs{std::uint16_t(15U)}; constexpr const auto min_orphaned_file_retention_days{std::uint16_t(1U)}; @@ -200,6 +202,7 @@ enum class api_error { item_exists, item_not_found, more_data, + name_too_long, no_disk_space, not_implemented, not_supported, @@ -216,31 +219,49 @@ enum class api_error { [[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error; -[[nodiscard]] auto -api_error_to_string(const api_error &error) -> const std::string &; +[[nodiscard]] auto api_error_to_string(const api_error &error) + -> const std::string &; enum class database_type { rocksdb, sqlite, }; -[[nodiscard]] auto database_type_from_string( - std::string type, - database_type default_type = database_type::rocksdb) -> database_type; - [[nodiscard]] auto -database_type_to_string(const database_type &type) -> std::string; +database_type_from_string(std::string type, + database_type default_type = database_type::rocksdb) + -> database_type; + +[[nodiscard]] auto database_type_to_string(const database_type &type) + -> std::string; enum class download_type { default_, direct, ring_buffer, }; -[[nodiscard]] auto download_type_from_string( - std::string type, - download_type default_type = download_type::default_) -> download_type; +[[nodiscard]] auto +download_type_from_string(std::string type, + download_type default_type = download_type::default_) + -> download_type; + +[[nodiscard]] auto download_type_to_string(const download_type &type) + -> std::string; + +enum class event_level { + critical, + error, + warn, + info, + debug, + trace, +}; [[nodiscard]] auto -download_type_to_string(const download_type &type) -> std::string; +event_level_from_string(std::string level, + event_level default_level = event_level::info) + -> event_level; + +[[nodiscard]] auto event_level_to_string(event_level level) -> std::string; enum class exit_code : std::int32_t { success = 0, @@ -267,7 +288,9 @@ enum class exit_code : std::int32_t { enum http_error_codes : std::int32_t { ok = 200, multiple_choices = 300, + unauthorized = 401, not_found = 404, + internal_error = 500, }; enum class lock_result { @@ -650,6 +673,18 @@ template <> struct adl_serializer { value = repertory::download_type_from_string(data.get()); } }; + +template <> struct adl_serializer> { + static void to_json(json &data, + const std::atomic &value) { + data = repertory::event_level_to_string(value.load()); + } + + static void from_json(const json &data, + std::atomic &value) { + value.store(repertory::event_level_from_string(data.get())); + } +}; NLOHMANN_JSON_NAMESPACE_END #endif // REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_ diff --git a/repertory/librepertory/include/types/rpc.hpp b/repertory/librepertory/include/types/rpc.hpp index 4b1ee3da..c7a37663 100644 --- a/repertory/librepertory/include/types/rpc.hpp +++ b/repertory/librepertory/include/types/rpc.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/types/s3.hpp b/repertory/librepertory/include/types/s3.hpp index 01f27eed..1b9f2690 100644 --- a/repertory/librepertory/include/types/s3.hpp +++ b/repertory/librepertory/include/types/s3.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/types/startup_exception.hpp b/repertory/librepertory/include/types/startup_exception.hpp index 99164893..22d672e0 100644 --- a/repertory/librepertory/include/types/startup_exception.hpp +++ b/repertory/librepertory/include/types/startup_exception.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/cli_utils.hpp b/repertory/librepertory/include/utils/cli_utils.hpp index 3ab1488c..06ce1f41 100644 --- a/repertory/librepertory/include/utils/cli_utils.hpp +++ b/repertory/librepertory/include/utils/cli_utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/error_utils.hpp b/repertory/librepertory/include/utils/error_utils.hpp index c5835981..5d3f76de 100644 --- a/repertory/librepertory/include/utils/error_utils.hpp +++ b/repertory/librepertory/include/utils/error_utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/file_utils.hpp b/repertory/librepertory/include/utils/file_utils.hpp index 2fba22fb..a835abac 100644 --- a/repertory/librepertory/include/utils/file_utils.hpp +++ b/repertory/librepertory/include/utils/file_utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/polling.hpp b/repertory/librepertory/include/utils/polling.hpp index 262e19cb..8cd1d692 100644 --- a/repertory/librepertory/include/utils/polling.hpp +++ b/repertory/librepertory/include/utils/polling.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -40,7 +40,7 @@ public: struct polling_item final { std::string name; frequency freq; - std::function action; + std::function action; }; public: @@ -75,6 +75,8 @@ private: void frequency_thread(std::function get_frequency_seconds, frequency freq); + [[nodiscard]] auto get_stop_requested() const -> bool; + public: void remove_callback(const std::string &name); diff --git a/repertory/librepertory/include/utils/single_thread_service_base.hpp b/repertory/librepertory/include/utils/single_thread_service_base.hpp index 54e6e02d..ebf8f696 100644 --- a/repertory/librepertory/include/utils/single_thread_service_base.hpp +++ b/repertory/librepertory/include/utils/single_thread_service_base.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -36,7 +36,7 @@ private: const std::string service_name_; mutable std::mutex mtx_; mutable std::condition_variable notify_; - stop_type stop_requested_ = false; + stop_type stop_requested_{false}; std::unique_ptr thread_; protected: @@ -46,9 +46,7 @@ protected: return notify_; } - [[nodiscard]] auto get_stop_requested() const -> bool { - return stop_requested_; - } + [[nodiscard]] auto get_stop_requested() const -> bool; void notify_all() const; diff --git a/repertory/librepertory/include/utils/tasks.hpp b/repertory/librepertory/include/utils/tasks.hpp index 7b58f04a..390084b1 100644 --- a/repertory/librepertory/include/utils/tasks.hpp +++ b/repertory/librepertory/include/utils/tasks.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ class app_config; class tasks final { public: struct task final { - std::function action; + std::function action; }; class i_task { @@ -104,6 +104,8 @@ private: private: void task_thread(); + [[nodiscard]] auto get_stop_requested() const -> bool; + public: auto schedule(task item) -> task_ptr; diff --git a/repertory/librepertory/include/utils/throttle.hpp b/repertory/librepertory/include/utils/throttle.hpp deleted file mode 100644 index 8ad85253..00000000 --- a/repertory/librepertory/include/utils/throttle.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright <2018-2024> - - 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 REPERTORY_INCLUDE_UTILS_THROTTLE_HPP_ -#define REPERTORY_INCLUDE_UTILS_THROTTLE_HPP_ - -namespace repertory { -class throttle final { -public: - throttle() : max_size_(10u) {} - - explicit throttle(std::size_t max_size) : max_size_(max_size) {} - -public: - throttle(const throttle &) noexcept = delete; - throttle(throttle &&) noexcept = delete; - auto operator=(const throttle &) -> throttle & = delete; - auto operator=(throttle &&) -> throttle & = delete; - -public: - ~throttle() { shutdown(); } - -private: - const std::size_t max_size_; - std::size_t count_ = 0u; - bool shutdown_ = false; - std::mutex mutex_; - std::condition_variable notify_; - -public: - void decrement(); - - void increment_or_wait(); - - void reset(); - - void shutdown(); -}; -} // namespace repertory - -#endif // REPERTORY_INCLUDE_UTILS_THROTTLE_HPP_ diff --git a/repertory/librepertory/include/utils/timeout.hpp b/repertory/librepertory/include/utils/timeout.hpp index 230a00c8..036b6ba6 100644 --- a/repertory/librepertory/include/utils/timeout.hpp +++ b/repertory/librepertory/include/utils/timeout.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -32,13 +32,13 @@ public: public: timeout(std::function timeout_callback, - const std::chrono::system_clock::duration &duration = 10s); + std::chrono::system_clock::duration duration); ~timeout() { disable(); } private: - bool timeout_killed_; - std::unique_ptr timeout_thread_; + std::atomic timeout_killed_; + std::unique_ptr timeout_thread_{nullptr}; std::mutex timeout_mutex_; std::condition_variable timeout_notify_; diff --git a/repertory/librepertory/include/utils/unix/unix_utils.hpp b/repertory/librepertory/include/utils/unix/unix_utils.hpp index a474240f..d7849865 100644 --- a/repertory/librepertory/include/utils/unix/unix_utils.hpp +++ b/repertory/librepertory/include/utils/unix/unix_utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/utils.hpp b/repertory/librepertory/include/utils/utils.hpp index b7843b3f..8e6b3981 100644 --- a/repertory/librepertory/include/utils/utils.hpp +++ b/repertory/librepertory/include/utils/utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/include/utils/windows/windows_utils.hpp b/repertory/librepertory/include/utils/windows/windows_utils.hpp index 1501e4f5..013a260f 100644 --- a/repertory/librepertory/include/utils/windows/windows_utils.hpp +++ b/repertory/librepertory/include/utils/windows/windows_utils.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/app_config.cpp b/repertory/librepertory/src/app_config.cpp index fb271751..8ee5208c 100644 --- a/repertory/librepertory/src/app_config.cpp +++ b/repertory/librepertory/src/app_config.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ #include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/event_level_changed.hpp" #include "file_manager/cache_size_mgr.hpp" #include "platform/platform.hpp" #include "types/startup_exception.hpp" @@ -57,6 +57,12 @@ auto get_value(const json &data, const std::string &name, dest &dst, } // namespace namespace repertory { +stop_type app_config::stop_requested{false}; + +auto app_config::get_stop_requested() -> bool { return stop_requested.load(); } + +void app_config::set_stop_requested() { stop_requested.store(true); } + app_config::app_config(const provider_type &prov, std::string_view data_directory) : prov_(prov), @@ -1140,9 +1146,10 @@ void app_config::set_enable_mount_manager(bool value) { #endif // defined(_WIN32) void app_config::set_event_level(const event_level &value) { + REPERTORY_USES_FUNCTION_NAME(); + if (set_value(event_level_, value)) { - event_system::instance().raise( - event_level_to_string(value)); + event_system::instance().raise(function_name, value); } } diff --git a/repertory/librepertory/src/comm/curl/curl_comm.cpp b/repertory/librepertory/src/comm/curl/curl_comm.cpp index b2f576cd..e4113e8f 100644 --- a/repertory/librepertory/src/comm/curl/curl_comm.cpp +++ b/repertory/librepertory/src/comm/curl/curl_comm.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ const curl_comm::write_callback curl_comm::write_data = auto &info = *reinterpret_cast(outstream); std::copy(buffer, buffer + (size * nitems), std::back_inserter(info.data)); - return info.stop_requested ? 0 : size * nitems; + return info.stop_requested_cb() ? 0 : size * nitems; }); const curl_comm::write_callback curl_comm::write_headers = @@ -102,8 +102,8 @@ auto curl_comm::reset_curl(CURL *curl_handle) -> CURL * { return curl_handle; } -auto curl_comm::create_host_config(const s3_config &cfg, - bool use_s3_path_style) -> host_config { +auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style) + -> host_config { host_config host_cfg{}; host_cfg.api_password = cfg.secret_key; host_cfg.api_user = cfg.access_key; diff --git a/repertory/librepertory/src/comm/curl/multi_request.cpp b/repertory/librepertory/src/comm/curl/multi_request.cpp index 64ef2bcd..63efa2d1 100644 --- a/repertory/librepertory/src/comm/curl/multi_request.cpp +++ b/repertory/librepertory/src/comm/curl/multi_request.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,7 @@ */ #include "comm/curl/multi_request.hpp" +#include "app_config.hpp" #include "utils/utils.hpp" namespace repertory { @@ -46,7 +47,7 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) { auto error = false; int running_handles = 0; curl_multi_perform(multi_handle_, &running_handles); - while (not error && (running_handles > 0) && not stop_requested_) { + while (not error && (running_handles > 0) && not get_stop_requested()) { int ignored{}; curl_multi_wait(multi_handle_, nullptr, 0, timeout_ms, &ignored); @@ -54,7 +55,7 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) { error = (ret != CURLM_CALL_MULTI_PERFORM) && (ret != CURLM_OK); } - if (not stop_requested_) { + if (not get_stop_requested()) { int remaining_messages = 0; auto *multi_result = curl_multi_info_read(multi_handle_, &remaining_messages); @@ -65,4 +66,8 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) { } } } + +auto multi_request::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} } // namespace repertory diff --git a/repertory/librepertory/src/comm/curl/requests/http_post.cpp b/repertory/librepertory/src/comm/curl/requests/http_post.cpp index 4032ffbb..ca052a0a 100644 --- a/repertory/librepertory/src/comm/curl/requests/http_post.cpp +++ b/repertory/librepertory/src/comm/curl/requests/http_post.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,18 +22,11 @@ #include "comm/curl/requests/http_post.hpp" namespace repertory::curl::requests { -http_post::~http_post() { - if (headers != nullptr) { - curl_slist_free_all(headers); - } -} - auto http_post::set_method(CURL *curl, stop_type & /*stop_requested*/) const -> bool { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); if (json.has_value()) { - headers = curl_slist_append(headers, "content-type: application/json"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + headers["content-type"] = "application/json"; json_str = json->dump(); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str->c_str()); diff --git a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp index 565c3fdc..db4eef94 100644 --- a/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp +++ b/repertory/librepertory/src/comm/curl/requests/http_put_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/comm/curl/requests/http_request_base.cpp b/repertory/librepertory/src/comm/curl/requests/http_request_base.cpp index 27db70ad..201b86c7 100644 --- a/repertory/librepertory/src/comm/curl/requests/http_request_base.cpp +++ b/repertory/librepertory/src/comm/curl/requests/http_request_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/comm/packet/client_pool.cpp b/repertory/librepertory/src/comm/packet/client_pool.cpp index f56d2913..73f7cc1a 100644 --- a/repertory/librepertory/src/comm/packet/client_pool.cpp +++ b/repertory/librepertory/src/comm/packet/client_pool.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,10 @@ #include "comm/packet/client_pool.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "platform/platform.hpp" #include "utils/error_utils.hpp" @@ -43,7 +46,8 @@ void client_pool::pool::execute( client_pool::pool::pool(std::uint8_t pool_size) { REPERTORY_USES_FUNCTION_NAME(); - event_system::instance().raise("client_pool"); + event_system::instance().raise(function_name, + "client_pool"); for (std::uint8_t i = 0U; i < pool_size; i++) { pool_queues_.emplace_back(std::make_unique()); @@ -105,6 +109,9 @@ client_pool::pool::pool(std::uint8_t pool_size) { queue_lock.unlock(); }); } + + event_system::instance().raise(function_name, + "client_pool"); } void client_pool::pool::shutdown() { @@ -146,18 +153,24 @@ void client_pool::remove_client(const std::string &client_id) { } void client_pool::shutdown() { - if (not shutdown_) { - event_system::instance().raise("client_pool"); - unique_mutex_lock pool_lock(pool_mutex_); - if (not shutdown_) { - shutdown_ = true; - for (auto &pool_entry : pool_lookup_) { - pool_entry.second->shutdown(); - } - pool_lookup_.clear(); - } - pool_lock.unlock(); - event_system::instance().raise("client_pool"); + REPERTORY_USES_FUNCTION_NAME(); + + if (shutdown_) { + return; } + + event_system::instance().raise(function_name, + "client_pool"); + unique_mutex_lock pool_lock(pool_mutex_); + if (not shutdown_) { + shutdown_ = true; + for (auto &pool_entry : pool_lookup_) { + pool_entry.second->shutdown(); + } + pool_lookup_.clear(); + } + pool_lock.unlock(); + event_system::instance().raise(function_name, + "client_pool"); } } // namespace repertory diff --git a/repertory/librepertory/src/comm/packet/packet.cpp b/repertory/librepertory/src/comm/packet/packet.cpp index fa506e2f..4ff12365 100644 --- a/repertory/librepertory/src/comm/packet/packet.cpp +++ b/repertory/librepertory/src/comm/packet/packet.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/comm/packet/packet_client.cpp b/repertory/librepertory/src/comm/packet/packet_client.cpp index bc9c3b68..8a6ca3a4 100644 --- a/repertory/librepertory/src/comm/packet/packet_client.cpp +++ b/repertory/librepertory/src/comm/packet/packet_client.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,7 @@ #include "comm/packet/packet_client.hpp" #include "events/event_system.hpp" +#include "events/types/packet_client_timeout.hpp" #include "platform/platform.hpp" #include "types/repertory.hpp" #include "utils/collection.hpp" @@ -31,13 +32,6 @@ #include "version.hpp" namespace repertory { -// clang-format off -E_SIMPLE2(packet_client_timeout, error, true, - std::string, event_name, en, E_FROM_STRING, - std::string, message, msg, E_FROM_STRING -); -// clang-format on - packet_client::packet_client(remote::remote_config cfg) : cfg_(std::move(cfg)), unique_id_(utils::create_uuid_string()) {} @@ -49,8 +43,10 @@ packet_client::~packet_client() { void packet_client::close(client &cli) { try { + cli.socket.shutdown(boost::asio::socket_base::shutdown_both); + boost::system::error_code err; - cli.socket.close(err); + [[maybe_unused]] auto res = cli.socket.close(err); } catch (...) { } } @@ -110,7 +106,7 @@ void packet_client::put_client(std::shared_ptr &cli) { } } -auto packet_client::read_packet(client &cli, packet &response) +auto packet_client::read_packet(client &cli, packet &response) const -> packet::error_type { data_buffer buffer(sizeof(std::uint32_t)); const auto read_buffer = [&]() { @@ -118,7 +114,7 @@ auto packet_client::read_packet(client &cli, packet &response) while (offset < buffer.size()) { auto bytes_read = boost::asio::read( cli.socket, - boost::asio::buffer(&buffer[offset], buffer.size() - offset)); + boost::asio::buffer(&buffer.at(offset), buffer.size() - offset)); if (bytes_read <= 0) { throw std::runtime_error("read failed|" + std::to_string(bytes_read)); } @@ -189,7 +185,7 @@ auto packet_client::send(std::string_view method, packet &request, timeout request_timeout( [method, current_client]() { event_system::instance().raise( - "request", std::string{method}); + "request", function_name, std::string{method}); packet_client::close(*current_client); }, std::chrono::milliseconds(cfg_.send_timeout_ms)); @@ -211,7 +207,7 @@ auto packet_client::send(std::string_view method, packet &request, timeout response_timeout( [method, current_client]() { event_system::instance().raise( - "response", std::string{method}); + "response", function_name, std::string{method}); packet_client::close(*current_client); }, std::chrono::milliseconds(cfg_.recv_timeout_ms)); diff --git a/repertory/librepertory/src/comm/packet/packet_server.cpp b/repertory/librepertory/src/comm/packet/packet_server.cpp index 5c5abb11..d714e7da 100644 --- a/repertory/librepertory/src/comm/packet/packet_server.cpp +++ b/repertory/librepertory/src/comm/packet/packet_server.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,10 @@ #include "comm/packet/packet.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "platform/platform.hpp" #include "types/repertory.hpp" #include "utils/error_utils.hpp" @@ -37,12 +40,20 @@ packet_server::packet_server(std::uint16_t port, std::string token, : encryption_token_(std::move(token)), closed_(std::move(closed)), message_handler_(std::move(message_handler)) { + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "packet_server"); initialize(port, pool_size); - event_system::instance().raise("packet_server"); + event_system::instance().raise(function_name, + "packet_server"); } packet_server::~packet_server() { - event_system::instance().raise("packet_server"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "packet_server"); std::thread([this]() { for (std::size_t i = 0U; i < service_threads_.size(); i++) { io_context_.stop(); @@ -51,7 +62,8 @@ packet_server::~packet_server() { server_thread_->join(); server_thread_.reset(); - event_system::instance().raise("packet_server"); + event_system::instance().raise(function_name, + "packet_server"); } void packet_server::add_client(connection &conn, const std::string &client_id) { diff --git a/repertory/librepertory/src/db/file_db.cpp b/repertory/librepertory/src/db/file_db.cpp index 53de46bc..3a346ff5 100644 --- a/repertory/librepertory/src/db/file_db.cpp +++ b/repertory/librepertory/src/db/file_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/db/file_mgr_db.cpp b/repertory/librepertory/src/db/file_mgr_db.cpp index dfdf3c73..a231c0f2 100644 --- a/repertory/librepertory/src/db/file_mgr_db.cpp +++ b/repertory/librepertory/src/db/file_mgr_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/db/impl/rdb_file_db.cpp b/repertory/librepertory/src/db/impl/rdb_file_db.cpp index 9cc063a2..8e1e1810 100644 --- a/repertory/librepertory/src/db/impl/rdb_file_db.cpp +++ b/repertory/librepertory/src/db/impl/rdb_file_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -149,6 +149,54 @@ auto rdb_file_db::count() const -> std::uint64_t { return ret; } +void rdb_file_db::enumerate_item_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const { + std::vector list; + { + auto iter = create_iterator(file_family_); + for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid(); + iter->Next()) { + auto json_data = json::parse(iter->value().ToString()); + list.emplace_back(i_file_db::file_info{ + iter->key().ToString(), + false, + json_data.at("source_path").get(), + }); + + if (list.size() < 100U) { + continue; + } + + callback(list); + list.clear(); + } + } + + { + auto iter = create_iterator(directory_family_); + for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid(); + iter->Next()) { + list.emplace_back(i_file_db::file_info{ + iter->key().ToString(), + true, + iter->value().ToString(), + }); + + if (list.size() < 100U) { + continue; + } + + callback(list); + list.clear(); + } + } + + if (not list.empty()) { + callback(list); + } +} + auto rdb_file_db::get_api_path(const std::string &source_path, std::string &api_path) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); @@ -264,11 +312,13 @@ auto rdb_file_db::get_file_source_path( return result; } -auto rdb_file_db::get_item_list() const -> std::vector { +auto rdb_file_db::get_item_list(stop_type_callback stop_requested_cb) const + -> std::vector { std::vector ret{}; { auto iter = create_iterator(directory_family_); - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid(); + iter->Next()) { ret.emplace_back(i_file_db::file_info{ iter->key().ToString(), true, @@ -279,11 +329,12 @@ auto rdb_file_db::get_item_list() const -> std::vector { { auto iter = create_iterator(file_family_); - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid(); + iter->Next()) { auto json_data = json::parse(iter->value().ToString()); ret.emplace_back(i_file_db::file_info{ iter->key().ToString(), - true, + false, json_data.at("source_path").get(), }); } diff --git a/repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp b/repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp index 573ac00e..7ac0e852 100644 --- a/repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp +++ b/repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/db/impl/rdb_meta_db.cpp b/repertory/librepertory/src/db/impl/rdb_meta_db.cpp index 7a9b49a7..538f3d90 100644 --- a/repertory/librepertory/src/db/impl/rdb_meta_db.cpp +++ b/repertory/librepertory/src/db/impl/rdb_meta_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -64,6 +64,29 @@ auto rdb_meta_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const db_->NewIterator(rocksdb::ReadOptions{}, family)); } +void rdb_meta_db::enumerate_api_path_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const { + std::vector list{}; + + auto iter = create_iterator(meta_family_); + for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid(); + iter->Next()) { + list.push_back(iter->key().ToString()); + + if (list.size() < 100U) { + continue; + } + + callback(list); + list.clear(); + } + + if (not list.empty()) { + callback(list); + } +} + auto rdb_meta_db::get_api_path(const std::string &source_path, std::string &api_path) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); @@ -295,10 +318,9 @@ void rdb_meta_db::remove_api_path(const std::string &api_path) { } } -auto rdb_meta_db::remove_api_path(const std::string &api_path, - const std::string &source_path, - rocksdb::Transaction *txn) - -> rocksdb::Status { +auto rdb_meta_db::remove_api_path( + const std::string &api_path, const std::string &source_path, + rocksdb::Transaction *txn) -> rocksdb::Status { auto txn_res = txn->Delete(pinned_family_, api_path); if (not txn_res.ok()) { return txn_res; diff --git a/repertory/librepertory/src/db/impl/sqlite_file_db.cpp b/repertory/librepertory/src/db/impl/sqlite_file_db.cpp index b6ffb95c..c7cdd024 100644 --- a/repertory/librepertory/src/db/impl/sqlite_file_db.cpp +++ b/repertory/librepertory/src/db/impl/sqlite_file_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -65,9 +65,8 @@ sqlite_file_db::sqlite_file_db(const app_config &cfg) { sqlite_file_db::~sqlite_file_db() { db_.reset(); } -auto sqlite_file_db::add_directory(const std::string &api_path, - const std::string &source_path) - -> api_error { +auto sqlite_file_db::add_directory( + const std::string &api_path, const std::string &source_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); auto result = utils::db::sqlite::db_insert{*db_, file_table} @@ -133,6 +132,37 @@ auto sqlite_file_db::count() const -> std::uint64_t { return 0U; } +void sqlite_file_db::enumerate_item_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const { + std::vector list; + + auto result = utils::db::sqlite::db_select{*db_, file_table}.go(); + while (not stop_requested_cb() && result.has_row()) { + std::optional row; + if (result.get_row(row) && row.has_value()) { + list.emplace_back(i_file_db::file_info{ + .api_path = row->get_column("api_path").get_value(), + .directory = + row->get_column("directory").get_value() == 1, + .source_path = + row->get_column("source_path").get_value(), + }); + + if (list.size() < 100U) { + continue; + } + + callback(list); + list.clear(); + } + } + + if (not list.empty()) { + callback(list); + } +} + auto sqlite_file_db::get_api_path(const std::string &source_path, std::string &api_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} @@ -152,9 +182,8 @@ auto sqlite_file_db::get_api_path(const std::string &source_path, return api_error::item_not_found; } -auto sqlite_file_db::get_directory_api_path(const std::string &source_path, - std::string &api_path) const - -> api_error { +auto sqlite_file_db::get_directory_api_path( + const std::string &source_path, std::string &api_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} .column("api_path") .where("source_path") @@ -175,9 +204,8 @@ auto sqlite_file_db::get_directory_api_path(const std::string &source_path, return api_error::directory_not_found; } -auto sqlite_file_db::get_directory_source_path(const std::string &api_path, - std::string &source_path) const - -> api_error { +auto sqlite_file_db::get_directory_source_path( + const std::string &api_path, std::string &source_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} .column("source_path") .where("api_path") @@ -198,9 +226,8 @@ auto sqlite_file_db::get_directory_source_path(const std::string &api_path, return api_error::directory_not_found; } -auto sqlite_file_db::get_file_api_path(const std::string &source_path, - std::string &api_path) const - -> api_error { +auto sqlite_file_db::get_file_api_path( + const std::string &source_path, std::string &api_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} .column("api_path") .where("source_path") @@ -259,9 +286,8 @@ auto sqlite_file_db::get_file_data(const std::string &api_path, return api_error::item_not_found; } -auto sqlite_file_db::get_file_source_path(const std::string &api_path, - std::string &source_path) const - -> api_error { +auto sqlite_file_db::get_file_source_path( + const std::string &api_path, std::string &source_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} .column("source_path") .where("api_path") @@ -282,30 +308,29 @@ auto sqlite_file_db::get_file_source_path(const std::string &api_path, return api_error::item_not_found; } -auto sqlite_file_db::get_item_list() const +auto sqlite_file_db::get_item_list(stop_type_callback stop_requested_cb) const -> std::vector { std::vector ret; auto result = utils::db::sqlite::db_select{*db_, file_table}.go(); - while (result.has_row()) { + while (not stop_requested_cb() && result.has_row()) { std::optional row; if (result.get_row(row) && row.has_value()) { ret.emplace_back(i_file_db::file_info{ - row->get_column("api_path").get_value(), - row->get_column("directory").get_value() == 1, - row->get_column("source_path").get_value(), + .api_path = row->get_column("api_path").get_value(), + .directory = + row->get_column("directory").get_value() == 1, + .source_path = + row->get_column("source_path").get_value(), }); } - - result.next_row(); } return ret; } -auto sqlite_file_db::get_source_path(const std::string &api_path, - std::string &source_path) const - -> api_error { +auto sqlite_file_db::get_source_path( + const std::string &api_path, std::string &source_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, file_table} .column("source_path") .where("api_path") diff --git a/repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp b/repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp index 95dd3270..68633447 100644 --- a/repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp +++ b/repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/db/impl/sqlite_meta_db.cpp b/repertory/librepertory/src/db/impl/sqlite_meta_db.cpp index e3f0fbf1..3bf829a7 100644 --- a/repertory/librepertory/src/db/impl/sqlite_meta_db.cpp +++ b/repertory/librepertory/src/db/impl/sqlite_meta_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -75,6 +75,32 @@ void sqlite_meta_db::clear() { std::to_string(result.get_error())); } +void sqlite_meta_db::enumerate_api_path_list( + std::function &)> callback, + stop_type_callback stop_requested_cb) const { + auto result = + utils::db::sqlite::db_select{*db_, table_name}.column("api_path").go(); + + std::vector list{}; + while (not stop_requested_cb() && result.has_row()) { + std::optional row; + if (result.get_row(row) && row.has_value()) { + list.push_back(row->get_column("api_path").get_value()); + + if (list.size() < 100U) { + continue; + } + + callback(list); + list.clear(); + } + } + + if (not list.empty()) { + callback(list); + } +} + auto sqlite_meta_db::get_api_path(const std::string &source_path, std::string &api_path) const -> api_error { auto result = utils::db::sqlite::db_select{*db_, table_name} @@ -321,7 +347,7 @@ auto sqlite_meta_db::set_item_meta(const std::string &api_path, // TODO handle error } - for (auto &&item : meta) { + for (const auto &item : meta) { existing_meta[item.first] = item.second; } diff --git a/repertory/librepertory/src/db/meta_db.cpp b/repertory/librepertory/src/db/meta_db.cpp index 8db99bac..21ce79ec 100644 --- a/repertory/librepertory/src/db/meta_db.cpp +++ b/repertory/librepertory/src/db/meta_db.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/drives/directory_cache.cpp b/repertory/librepertory/src/drives/directory_cache.cpp index 025c2844..30827215 100644 --- a/repertory/librepertory/src/drives/directory_cache.cpp +++ b/repertory/librepertory/src/drives/directory_cache.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,14 +38,14 @@ void directory_cache::execute_action(const std::string &api_path, auto directory_cache::get_directory(std::uint64_t handle) -> std::shared_ptr { recur_mutex_lock directory_lock(directory_mutex_); - auto it = std::find_if(directory_lookup_.begin(), directory_lookup_.end(), - [handle](auto &&kv) -> bool { - auto &&handles = kv.second.handles; - return std::find(handles.begin(), handles.end(), - handle) != kv.second.handles.end(); - }); - if (it != directory_lookup_.end()) { - return it->second.iterator; + auto iter = + std::ranges::find_if(directory_lookup_, [handle](auto &&item) -> bool { + auto &&handles = item.second.handles; + return std::find(handles.begin(), handles.end(), handle) != + item.second.handles.end(); + }); + if (iter != directory_lookup_.end()) { + return iter->second.iterator; } return nullptr; @@ -66,39 +66,19 @@ auto directory_cache::remove_directory(const std::string &api_path) void directory_cache::remove_directory(std::uint64_t handle) { recur_mutex_lock directory_lock(directory_mutex_); - auto it = std::find_if(directory_lookup_.begin(), directory_lookup_.end(), - [handle](auto &&kv) -> bool { - auto &&handles = kv.second.handles; - return std::find(handles.begin(), handles.end(), - handle) != kv.second.handles.end(); - }); - if (it != directory_lookup_.end()) { - utils::collection::remove_element(it->second.handles, handle); - if (it->second.handles.empty()) { - directory_lookup_.erase(it); - } - } -} - -void directory_cache::service_function() { - unique_recur_mutex_lock directory_lock(directory_mutex_); - auto lookup = directory_lookup_; - directory_lock.unlock(); - - for (auto &&kv : lookup) { - if (std::chrono::duration_cast( - std::chrono::system_clock::now() - kv.second.last_update) >= 120s) { - directory_lock.lock(); - directory_lookup_.erase(kv.first); - directory_lock.unlock(); - } + auto iter = + std::ranges::find_if(directory_lookup_, [handle](auto &&item) -> bool { + auto &&handles = item.second.handles; + return std::find(handles.begin(), handles.end(), handle) != + item.second.handles.end(); + }); + if (iter == directory_lookup_.end()) { + return; } - if (not get_stop_requested()) { - unique_mutex_lock shutdown_lock(get_mutex()); - if (not get_stop_requested()) { - get_notify().wait_for(shutdown_lock, 15s); - } + utils::collection::remove_element(iter->second.handles, handle); + if (iter->second.handles.empty()) { + directory_lookup_.erase(iter); } } diff --git a/repertory/librepertory/src/drives/directory_iterator.cpp b/repertory/librepertory/src/drives/directory_iterator.cpp index 5eae21c0..00e78a9d 100644 --- a/repertory/librepertory/src/drives/directory_iterator.cpp +++ b/repertory/librepertory/src/drives/directory_iterator.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -33,102 +33,102 @@ auto directory_iterator::fill_buffer(const remote::file_offset &offset, -> int { REPERTORY_USES_FUNCTION_NAME(); - if (offset < items_.size()) { - try { - std::string item_name; - struct stat st{}; - struct stat *pst = nullptr; - switch (offset) { - case 0: { - item_name = "."; - } break; + if (offset >= items_.size()) { + errno = 120; + return -1; + } - case 1: { - item_name = ".."; - } break; + try { + std::string item_name; + struct stat st{}; + struct stat *pst = nullptr; + switch (offset) { + case 0: { + item_name = "."; + } break; - default: { - const auto &item = items_[offset]; - item_name = utils::path::strip_to_file_name(item.api_path); - populate_stat(item.api_path, item.size, item.meta, item.directory, &st); - pst = &st; - } break; - } + case 1: { + item_name = ".."; + } break; -#if FUSE_USE_VERSION >= 30 - if (filler_function(buffer, item_name.data(), pst, - static_cast(offset + 1), - FUSE_FILL_DIR_PLUS) != 0) { -#else - if (filler_function(buffer, item_name.data(), pst, - static_cast(offset + 1)) != 0) { -#endif - errno = ENOMEM; - return -1; - } - } catch (const std::exception &e) { - utils::error::raise_error(function_name, e, - "failed to fill fuse directory buffer"); + default: { + const auto &item = items_[offset]; + item_name = utils::path::strip_to_file_name(item.api_path); + populate_stat(item.api_path, item.size, item.meta, item.directory, &st); + pst = &st; + } break; } - return 0; +#if FUSE_USE_VERSION >= 30 + if (filler_function(buffer, item_name.data(), pst, + static_cast(offset + 1), + FUSE_FILL_DIR_PLUS) != 0) +#else // FUSE_USE_VERSION < 30 + if (filler_function(buffer, item_name.data(), pst, + static_cast(offset + 1)) != 0) +#endif // FUSE_USE_VERSION >= 30 + { + errno = ENOMEM; + return -1; + } + } catch (const std::exception &e) { + utils::error::raise_error(function_name, e, + "failed to fill fuse directory buffer"); } - errno = 120; - return -1; + return 0; } -#endif // !_WIN32 +#endif // !defined(_WIN32) auto directory_iterator::get(std::size_t offset, std::string &item) -> int { - if (offset < items_.size()) { - item = items_[offset].api_path; - return 0; + if (offset >= items_.size()) { + errno = 120; + return -1; } - errno = 120; - return -1; + item = items_[offset].api_path; + return 0; } auto directory_iterator::get_directory_item(std::size_t offset, directory_item &di) -> api_error { - if (offset < items_.size()) { - di = items_[offset]; - return api_error::success; + if (offset >= items_.size()) { + return api_error::directory_end_of_files; } - return api_error::directory_end_of_files; + di = items_[offset]; + return api_error::success; } auto directory_iterator::get_directory_item(const std::string &api_path, directory_item &di) -> api_error { - auto iter = - std::find_if(items_.begin(), items_.end(), [&](const auto &item) -> bool { - return api_path == item.api_path; - }); - if (iter != items_.end()) { - di = *iter; - return api_error::success; + auto iter = std::ranges::find_if(items_, [&api_path](auto &&item) -> bool { + return api_path == item.api_path; + }); + if (iter == items_.end()) { + return api_error::item_not_found; } - return api_error::item_not_found; + di = *iter; + return api_error::success; } auto directory_iterator::get_json(std::size_t offset, json &item) -> int { - if (offset < items_.size()) { - item = json(items_.at(offset)); - return 0; + if (offset >= items_.size()) { + errno = 120; + return -1; } - errno = 120; - return -1; + item = json(items_.at(offset)); + return 0; } auto directory_iterator::get_next_directory_offset( const std::string &api_path) const -> std::size_t { - const auto iter = std::find_if(items_.begin(), items_.end(), - [&api_path](const auto &dir_item) -> bool { - return api_path == dir_item.api_path; - }); + const auto iter = + std::ranges::find_if(items_, [&api_path](auto &&dir_item) -> bool { + return api_path == dir_item.api_path; + }); return (iter == items_.end()) ? 0U : static_cast( diff --git a/repertory/librepertory/src/drives/eviction.cpp b/repertory/librepertory/src/drives/eviction.cpp index b93b8525..8f93d387 100644 --- a/repertory/librepertory/src/drives/eviction.cpp +++ b/repertory/librepertory/src/drives/eviction.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,6 @@ #include "utils/file_utils.hpp" #include "utils/time.hpp" #include "utils/utils.hpp" -#include namespace repertory { auto eviction::check_minimum_requirements(const std::string &file_path) diff --git a/repertory/librepertory/src/drives/fuse/fuse_base.cpp b/repertory/librepertory/src/drives/fuse/fuse_base.cpp index 731719ce..54b51252 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_base.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,9 +24,11 @@ #include "drives/fuse/fuse_base.hpp" #include "app_config.hpp" -#include "drives/fuse/events.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/fuse_args_parsed.hpp" +#include "events/types/fuse_event.hpp" +#include "events/types/unmount_requested.hpp" +#include "events/types/unmount_result.hpp" #include "initialize.hpp" #include "platform/platform.hpp" #include "utils/collection.hpp" @@ -90,7 +92,7 @@ fuse_base::fuse_base(app_config &config) : config_(config) { fuse_ops_.flag_reserved = 0; #endif // FUSE_USE_VERSION < 30 - E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) { + E_SUBSCRIBE(unmount_requested, [this](const unmount_requested &) { std::thread([this]() { this->shutdown(); }).detach(); }); } @@ -118,8 +120,8 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int { #endif // __APPLE__ #if FUSE_USE_VERSION >= 30 -auto fuse_base::chmod_(const char *path, mode_t mode, - struct fuse_file_info *fi) -> int { +auto fuse_base::chmod_(const char *path, mode_t mode, struct fuse_file_info *fi) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -186,7 +188,7 @@ void fuse_base::display_options( #if FUSE_USE_VERSION >= 30 fuse_cmdline_help(); #else - struct fuse_operations fuse_ops {}; + struct fuse_operations fuse_ops{}; fuse_main(args.size(), reinterpret_cast(const_cast(args.data())), &fuse_ops, nullptr); @@ -196,7 +198,7 @@ void fuse_base::display_options( } void fuse_base::display_version_information(std::vector args) { - struct fuse_operations fuse_ops {}; + struct fuse_operations fuse_ops{}; fuse_main(static_cast(args.size()), reinterpret_cast(const_cast(args.data())), &fuse_ops, nullptr); @@ -334,8 +336,8 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime, #endif // __APPLE__ #if FUSE_USE_VERSION >= 30 -auto fuse_base::init_(struct fuse_conn_info *conn, - struct fuse_config *cfg) -> void * { +auto fuse_base::init_(struct fuse_conn_info *conn, struct fuse_config *cfg) + -> void * { REPERTORY_USES_FUNCTION_NAME(); return execute_void_pointer_callback(function_name, [&]() -> void * { @@ -408,7 +410,7 @@ auto fuse_base::mount(std::vector args) -> int { char *mount_location{nullptr}; #if FUSE_USE_VERSION >= 30 - struct fuse_cmdline_opts opts {}; + struct fuse_cmdline_opts opts{}; fuse_parse_cmdline(&fa, &opts); mount_location = opts.mountpoint; #else @@ -477,8 +479,8 @@ auto fuse_base::read_(const char *path, char *buffer, size_t read_size, #if FUSE_USE_VERSION >= 30 auto fuse_base::readdir_(const char *path, void *buf, fuse_fill_dir_t fuse_fill_dir, off_t offset, - struct fuse_file_info *fi, - fuse_readdir_flags flags) -> int { + struct fuse_file_info *fi, fuse_readdir_flags flags) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -510,8 +512,8 @@ auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int { }); } -auto fuse_base::releasedir_(const char *path, - struct fuse_file_info *fi) -> int { +auto fuse_base::releasedir_(const char *path, struct fuse_file_info *fi) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -521,8 +523,8 @@ auto fuse_base::releasedir_(const char *path, } #if FUSE_USE_VERSION >= 30 -auto fuse_base::rename_(const char *from, const char *to, - unsigned int flags) -> int { +auto fuse_base::rename_(const char *from, const char *to, unsigned int flags) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -601,12 +603,17 @@ auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int { } void fuse_base::notify_fuse_args_parsed(const std::vector &args) { - event_system::instance().raise(std::accumulate( - args.begin(), args.end(), std::string(), - [](std::string command_line, const auto &arg) { - command_line += (command_line.empty() ? arg : (" " + std::string(arg))); - return command_line; - })); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise( + std::accumulate(args.begin(), args.end(), std::string(), + [](auto &&command_line, auto &&arg) -> auto { + command_line += + (command_line.empty() ? arg + : (" " + std::string(arg))); + return command_line; + }), + function_name); } auto fuse_base::parse_args(std::vector &args) -> int { @@ -632,7 +639,7 @@ auto fuse_base::parse_args(std::vector &args) -> int { } const auto option_parts = utils::string::split(options, ',', true); - for (auto &&option : option_parts) { + for (const auto &option : option_parts) { if (option.find("gid") == 0) { const auto parts = utils::string::split(option, '=', true); if (parts.size() == 2u) { @@ -701,7 +708,7 @@ void fuse_base::raise_fuse_event(std::string_view function_name, (config_.get_event_level() >= event_level::trace)) { std::string func{function_name}; event_system::instance().raise( - utils::string::right_trim(func, '_'), std::string{api_path}, ret); + api_path, ret, utils::string::right_trim(func, '_')); } } @@ -750,9 +757,11 @@ auto fuse_base::setxattr_(const char *path, const char *name, const char *value, #endif // HAS_SETXATTR void fuse_base::shutdown() { - const auto res = unmount(get_mount_location()); - event_system::instance().raise(get_mount_location(), - std::to_string(res)); + REPERTORY_USES_FUNCTION_NAME(); + + auto res = unmount(get_mount_location()); + event_system::instance().raise(function_name, + get_mount_location(), res); } #if defined(__APPLE__) @@ -765,8 +774,8 @@ auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int { }); } -auto fuse_base::setbkuptime_(const char *path, - const struct timespec *bkuptime) -> int { +auto fuse_base::setbkuptime_(const char *path, const struct timespec *bkuptime) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -775,8 +784,8 @@ auto fuse_base::setbkuptime_(const char *path, }); } -auto fuse_base::setchgtime_(const char *path, - const struct timespec *chgtime) -> int { +auto fuse_base::setchgtime_(const char *path, const struct timespec *chgtime) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( @@ -785,8 +794,8 @@ auto fuse_base::setchgtime_(const char *path, }); } -auto fuse_base::setcrtime_(const char *path, - const struct timespec *crtime) -> int { +auto fuse_base::setcrtime_(const char *path, const struct timespec *crtime) + -> int { REPERTORY_USES_FUNCTION_NAME(); return instance().execute_callback( diff --git a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp index 2c9a4ade..a84fe21b 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,7 +31,11 @@ #include "events/consumers/console_consumer.hpp" #include "events/consumers/logging_consumer.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/drive_mount_result.hpp" +#include "events/types/drive_mounted.hpp" +#include "events/types/drive_stop_timed_out.hpp" +#include "events/types/drive_unmount_pending.hpp" +#include "events/types/drive_unmounted.hpp" #include "platform/platform.hpp" #include "providers/i_provider.hpp" #include "rpc/server/full_server.hpp" @@ -246,48 +250,62 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode, return api_error::success; } -void fuse_drive::destroy_impl(void *ptr) { +void fuse_drive::stop_all() { REPERTORY_USES_FUNCTION_NAME(); - event_system::instance().raise(get_mount_location()); + mutex_lock lock(stop_all_mtx_); - remote_server_.reset(); + auto future = std::async(std::launch::async, [this]() { + remote_server_.reset(); - if (server_) { - server_->stop(); + if (server_) { + server_->stop(); + } + + polling::instance().stop(); + + if (eviction_) { + eviction_->stop(); + } + + if (fm_) { + fm_->stop(); + } + + provider_.stop(); + + directory_cache_.reset(); + eviction_.reset(); + server_.reset(); + + fm_.reset(); + }); + + if (future.wait_for(30s) == std::future_status::timeout) { + event_system::instance().raise(function_name); + app_config::set_stop_requested(); + future.wait(); } - polling::instance().stop(); - - if (eviction_) { - eviction_->stop(); - } - - if (fm_) { - fm_->stop(); - } - - provider_.stop(); - - if (directory_cache_) { - directory_cache_->stop(); - } - - directory_cache_.reset(); - eviction_.reset(); - server_.reset(); - - fm_.reset(); - - event_system::instance().raise(get_mount_location()); - - config_.save(); - if (not lock_data_.set_mount_state(false, "", -1)) { utils::error::raise_error(function_name, "failed to set mount state"); } +} + +void fuse_drive::destroy_impl(void *ptr) { + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + get_mount_location()); + + stop_all(); + + config_.save(); fuse_base::destroy_impl(ptr); + + event_system::instance().raise(function_name, + get_mount_location()); } auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode, @@ -363,13 +381,8 @@ auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *unix_st, return res; } - bool directory{}; - res = provider_.is_directory(api_path, directory); - if (res != api_error::success) { - return res; - } fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta, - directory, provider_, unix_st); + open_file->is_directory(), provider_, unix_st); return api_error::success; } @@ -491,33 +504,16 @@ auto fuse_drive::getattr_impl(std::string api_path, return res; } - auto found = false; - directory_cache_->execute_action(parent, [&](directory_iterator &iter) { - directory_item dir_item{}; - found = (iter.get_directory_item(api_path, dir_item) == api_error::success); - if (found) { - fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta, - dir_item.directory, provider_, unix_st); - } - }); - - if (not found) { - api_meta_map meta{}; - res = provider_.get_item_meta(api_path, meta); - if (res != api_error::success) { - return res; - } - - bool directory{}; - res = provider_.is_directory(api_path, directory); - if (res != api_error::success) { - return res; - } - fuse_drive_base::populate_stat(api_path, - utils::string::to_uint64(meta[META_SIZE]), - meta, directory, provider_, unix_st); + api_meta_map meta{}; + res = provider_.get_item_meta(api_path, meta); + if (res != api_error::success) { + return res; } + fuse_drive_base::populate_stat( + api_path, utils::string::to_uint64(meta[META_SIZE]), meta, + utils::string::to_bool(meta[META_DIRECTORY]), provider_, unix_st); + return api_error::success; } @@ -578,25 +574,24 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) { auto *ret = fuse_drive_base::init_impl(conn); #endif - if (console_enabled_) { - console_consumer_ = - std::make_unique(config_.get_event_level()); - } - - logging_consumer_ = std::make_unique( - config_.get_event_level(), config_.get_log_directory()); - event_system::instance().start(); - was_mounted_ = true; - - fm_ = std::make_unique(config_, provider_); - server_ = std::make_unique(config_, provider_, *fm_); - if (not provider_.is_read_only()) { - eviction_ = std::make_unique(provider_, config_, *fm_); - } - directory_cache_ = std::make_unique(); - try { - directory_cache_->start(); + if (console_enabled_) { + console_consumer_ = + std::make_unique(config_.get_event_level()); + } + + logging_consumer_ = std::make_unique( + config_.get_event_level(), config_.get_log_directory()); + event_system::instance().start(); + was_mounted_ = true; + + fm_ = std::make_unique(config_, provider_); + server_ = std::make_unique(config_, provider_, *fm_); + if (not provider_.is_read_only()) { + eviction_ = std::make_unique(provider_, config_, *fm_); + } + + directory_cache_ = std::make_unique(); server_->start(); if (not provider_.start( @@ -617,13 +612,14 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) { config_, *this, get_mount_location()); } + polling::instance().start(&config_); + if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) { utils::error::raise_error(function_name, "failed to set mount state"); } - polling::instance().start(&config_); - - event_system::instance().raise(get_mount_location()); + event_system::instance().raise(function_name, + get_mount_location()); } catch (const std::exception &e) { utils::error::raise_error(function_name, e, "exception during fuse init"); @@ -670,12 +666,17 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error { } void fuse_drive::notify_fuse_main_exit(int &ret) { - if (was_mounted_) { - event_system::instance().raise(std::to_string(ret)); - event_system::instance().stop(); - logging_consumer_.reset(); - console_consumer_.reset(); + REPERTORY_USES_FUNCTION_NAME(); + + if (not was_mounted_) { + return; } + + event_system::instance().raise( + function_name, get_mount_location(), std::to_string(ret)); + event_system::instance().stop(); + logging_consumer_.reset(); + console_consumer_.reset(); } auto fuse_drive::open_impl(std::string api_path, @@ -732,6 +733,9 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size, if (not fm_->get_open_file(file_info->fh, false, open_file)) { return api_error::item_not_found; } + if (open_file->is_directory()) { + return api_error::directory_exists; + } auto res = check_readable(open_file->get_open_data(file_info->fh), api_error::invalid_handle); @@ -898,19 +902,7 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name, } api_meta_map meta; - auto found{false}; - directory_cache_->execute_action( - utils::path::get_parent_api_path(api_path), - [&](directory_iterator &iterator) { - directory_item dir_item{}; - found = (iterator.get_directory_item(api_path, dir_item) == - api_error::success); - if (found) { - meta = dir_item.meta; - } - }); - - res = found ? api_error::success : provider_.get_item_meta(api_path, meta); + res = provider_.get_item_meta(api_path, meta); if (res != api_error::success) { return res; } @@ -964,7 +956,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, api_meta_map meta; res = provider_.get_item_meta(api_path, meta); if (res == api_error::success) { - for (auto &&meta_item : meta) { + for (const auto &meta_item : meta) { if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) { auto attribute_name = meta_item.first; #if defined(__APPLE__) @@ -1401,6 +1393,10 @@ auto fuse_drive::write_impl(std::string /*api_path*/ return api_error::item_not_found; } + if (open_file->is_directory()) { + return api_error::directory_exists; + } + auto res = check_writeable(open_file->get_open_data(file_info->fh), api_error::invalid_handle); if (res != api_error::success) { diff --git a/repertory/librepertory/src/drives/fuse/fuse_drive_base.cpp b/repertory/librepertory/src/drives/fuse/fuse_drive_base.cpp index 295ea60b..3a05d683 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_drive_base.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_drive_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,11 @@ #include "drives/fuse/fuse_drive_base.hpp" -#include "events/events.hpp" #include "platform/platform.hpp" #include "providers/i_provider.hpp" #include "utils/common.hpp" +#include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/time.hpp" namespace repertory { diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp index ae2361ad..93fb144a 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_client.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp index bda66542..982d9c57 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_fuse_drive.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,11 +24,14 @@ #include "drives/fuse/remotefuse/remote_fuse_drive.hpp" #include "app_config.hpp" -#include "drives/fuse/events.hpp" #include "events/consumers/console_consumer.hpp" #include "events/consumers/logging_consumer.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/drive_mount_result.hpp" +#include "events/types/drive_mounted.hpp" +#include "events/types/drive_unmount_pending.hpp" +#include "events/types/drive_unmounted.hpp" +#include "events/types/unmount_requested.hpp" #include "platform/platform.hpp" #include "rpc/server/server.hpp" #include "types/remote.hpp" @@ -90,7 +93,8 @@ auto remote_fuse_drive::create_impl(std::string api_path, mode_t mode, void remote_fuse_drive::destroy_impl(void *ptr) { REPERTORY_USES_FUNCTION_NAME(); - event_system::instance().raise(get_mount_location()); + event_system::instance().raise(function_name, + get_mount_location()); if (server_) { server_->stop(); @@ -111,7 +115,8 @@ void remote_fuse_drive::destroy_impl(void *ptr) { utils::error::raise_error(function_name, "failed to set mount state"); } - event_system::instance().raise(get_mount_location()); + event_system::instance().raise(function_name, + get_mount_location()); fuse_base::destroy_impl(ptr); } @@ -257,7 +262,8 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * { } else { server_ = std::make_shared(config_); server_->start(); - event_system::instance().raise(get_mount_location()); + event_system::instance().raise(function_name, + get_mount_location()); } return ret; @@ -270,8 +276,11 @@ auto remote_fuse_drive::mkdir_impl(std::string api_path, } void remote_fuse_drive::notify_fuse_main_exit(int &ret) { + REPERTORY_USES_FUNCTION_NAME(); + if (was_mounted_) { - event_system::instance().raise(std::to_string(ret)); + event_system::instance().raise( + function_name, get_mount_location(), std::to_string(ret)); event_system::instance().stop(); logging_consumer_.reset(); console_consumer_.reset(); @@ -300,10 +309,15 @@ auto remote_fuse_drive::opendir_impl( void remote_fuse_drive::populate_stat(const remote::stat &r_stat, bool directory, struct stat &unix_st) { std::memset(&unix_st, 0, sizeof(struct stat)); + unix_st.st_blksize = r_stat.st_blksize; + unix_st.st_blocks = static_cast(r_stat.st_blocks); + unix_st.st_gid = r_stat.st_gid; + unix_st.st_mode = (directory ? S_IFDIR : S_IFREG) | r_stat.st_mode; + unix_st.st_nlink = r_stat.st_nlink; + unix_st.st_size = static_cast(r_stat.st_size); + unix_st.st_uid = r_stat.st_uid; #if defined(__APPLE__) - unix_st.st_blksize = 0; - unix_st.st_atimespec.tv_nsec = r_stat.st_atimespec % utils::time::NANOS_PER_SECOND; unix_st.st_atimespec.tv_sec = @@ -326,8 +340,6 @@ void remote_fuse_drive::populate_stat(const remote::stat &r_stat, unix_st.st_flags = r_stat.st_flags; #else // !defined(__APPLE__) - unix_st.st_blksize = 4096; - unix_st.st_atim.tv_nsec = static_cast( r_stat.st_atimespec % utils::time::NANOS_PER_SECOND); unix_st.st_atim.tv_sec = static_cast( @@ -343,25 +355,6 @@ void remote_fuse_drive::populate_stat(const remote::stat &r_stat, unix_st.st_mtim.tv_sec = static_cast( r_stat.st_mtimespec / utils::time::NANOS_PER_SECOND); #endif // defined(__APPLE__) - - if (not directory) { - const auto block_size_stat = static_cast(512U); - const auto block_size = static_cast(4096U); - const auto size = - utils::divide_with_ceiling(static_cast(unix_st.st_size), - block_size) * - block_size; - unix_st.st_blocks = static_cast( - std::max(block_size / block_size_stat, - utils::divide_with_ceiling(size, block_size_stat))); - } - - unix_st.st_gid = r_stat.st_gid; - unix_st.st_mode = (directory ? S_IFDIR : S_IFREG) | r_stat.st_mode; - - unix_st.st_nlink = r_stat.st_nlink; - unix_st.st_size = static_cast(r_stat.st_size); - unix_st.st_uid = r_stat.st_uid; } auto remote_fuse_drive::read_impl(std::string api_path, char *buffer, diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp index 219f3448..ca917165 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,7 @@ #include "drives/directory_iterator.hpp" #include "drives/remote/remote_open_file_table.hpp" #include "events/event_system.hpp" +#include "events/types/remote_server_event.hpp" #include "platform/platform.hpp" #include "types/remote.hpp" #include "types/repertory.hpp" @@ -36,23 +37,15 @@ #include "utils/file.hpp" #include "utils/path.hpp" #include "utils/time.hpp" +#include "utils/utils.hpp" namespace repertory::remote_fuse { #define RAISE_REMOTE_FUSE_SERVER_EVENT(func, file, ret) \ if (config_.get_enable_drive_events() && \ - (((config_.get_event_level() >= remote_fuse_server_event::level) && \ - (ret < 0)) || \ + (((config_.get_event_level() >= remote_server_event::level) && \ + ((ret) < 0)) || \ (config_.get_event_level() >= event_level::trace))) \ - event_system::instance().raise(std::string{func}, \ - file, ret) - -// clang-format off -E_SIMPLE3(remote_fuse_server_event, debug, true, - std::string, function, func, E_FROM_STRING, - std::string, api_path, ap, E_FROM_STRING, - packet::error_type, result, res, E_FROM_INT32 -); -// clang-format on + event_system::instance().raise(file, ret, func) remote_server::remote_server(app_config &config, i_fuse_drive &drive, const std::string &mount_location) @@ -208,8 +201,8 @@ auto remote_server::fuse_access(const char *path, const std::int32_t &mask) return ret; } -auto remote_server::fuse_chflags(const char *path, - std::uint32_t flags) -> packet::error_type { +auto remote_server::fuse_chflags(const char *path, std::uint32_t flags) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -321,9 +314,10 @@ length); ret = ((res < 0) ? -errno : 0); #endif return ret; }*/ -auto remote_server::fuse_fgetattr( - const char *path, remote::stat &r_stat, bool &directory, - const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_fgetattr(const char *path, remote::stat &r_stat, + bool &directory, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); r_stat = {}; @@ -333,7 +327,7 @@ auto remote_server::fuse_fgetattr( auto res = has_open_info(static_cast(handle), EBADF); if (res == 0) { directory = utils::file::directory(file_path).exists(); - struct stat64 unix_st {}; + struct stat64 unix_st{}; res = fstat64(static_cast(handle), &unix_st); if (res == 0) { populate_stat(unix_st, r_stat); @@ -345,9 +339,10 @@ auto remote_server::fuse_fgetattr( return ret; } -auto remote_server::fuse_fsetattr_x( - const char *path, const remote::setattr_x &attr, - const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_fsetattr_x(const char *path, + const remote::setattr_x &attr, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -463,9 +458,10 @@ auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync, return ret; } -auto remote_server::fuse_ftruncate( - const char *path, const remote::file_offset &size, - const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_ftruncate(const char *path, + const remote::file_offset &size, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -493,7 +489,7 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_stat, directory = utils::file::directory(file_path).exists(); - struct stat64 unix_st {}; + struct stat64 unix_st{}; auto res = stat64(file_path.c_str(), &unix_st); if (res == 0) { populate_stat(unix_st, r_stat); @@ -558,9 +554,10 @@ STATUS_NOT_IMPLEMENTED; #endif RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); return ret; }*/ -auto remote_server::fuse_getxtimes( - const char *path, remote::file_time &bkuptime, - remote::file_time &crtime) -> packet::error_type { +auto remote_server::fuse_getxtimes(const char *path, + remote::file_time &bkuptime, + remote::file_time &crtime) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -665,10 +662,11 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle) return ret; } -auto remote_server::fuse_read( - const char *path, char *buffer, const remote::file_size &read_size, - const remote::file_offset &read_offset, - const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_read(const char *path, char *buffer, + const remote::file_size &read_size, + const remote::file_offset &read_offset, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -689,8 +687,8 @@ auto remote_server::fuse_read( return static_cast(ret); } -auto remote_server::fuse_rename(const char *from, - const char *to) -> packet::error_type { +auto remote_server::fuse_rename(const char *from, const char *to) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto from_path = utils::path::combine(mount_location_, {from}); @@ -728,8 +726,9 @@ auto remote_server::fuse_readdir(const char *path, return ret; } -auto remote_server::fuse_release( - const char *path, const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_release(const char *path, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); packet::error_type ret = 0; @@ -746,8 +745,9 @@ auto remote_server::fuse_release( return ret; } -auto remote_server::fuse_releasedir( - const char *path, const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_releasedir(const char *path, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -774,13 +774,7 @@ auto remote_server::fuse_rmdir(const char *path) -> packet::error_type { const auto file_path = construct_path(path); const auto res = rmdir(file_path.c_str()); if (res == 0) { - auto iter = - directory_cache_.remove_directory(utils::path::create_api_path(path)); - if (iter == nullptr) { - utils::error::raise_error( - function_name, - "unexpected nullptr for directory iterator|sp|" + file_path); - } + directory_cache_.remove_directory(utils::path::create_api_path(path)); } auto ret = ((res < 0) ? -errno : 0); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); @@ -798,8 +792,9 @@ auto remote_server::fuse_setattr_x(const char *path, remote::setattr_x &attr) return ret; } -auto remote_server::fuse_setbkuptime( - const char *path, const remote::file_time &bkuptime) -> packet::error_type { +auto remote_server::fuse_setbkuptime(const char *path, + const remote::file_time &bkuptime) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -818,8 +813,9 @@ auto remote_server::fuse_setbkuptime( return ret; } -auto remote_server::fuse_setchgtime( - const char *path, const remote::file_time &chgtime) -> packet::error_type { +auto remote_server::fuse_setchgtime(const char *path, + const remote::file_time &chgtime) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -838,8 +834,9 @@ auto remote_server::fuse_setchgtime( return ret; } -auto remote_server::fuse_setcrtime( - const char *path, const remote::file_time &crtime) -> packet::error_type { +auto remote_server::fuse_setcrtime(const char *path, + const remote::file_time &crtime) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -930,8 +927,9 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize, return 0; } -auto remote_server::fuse_truncate( - const char *path, const remote::file_offset &size) -> packet::error_type { +auto remote_server::fuse_truncate(const char *path, + const remote::file_offset &size) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -952,8 +950,8 @@ auto remote_server::fuse_unlink(const char *path) -> packet::error_type { } auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv, - std::uint64_t op0, - std::uint64_t op1) -> packet::error_type { + std::uint64_t op0, std::uint64_t op1) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -980,10 +978,11 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv, return ret; } -auto remote_server::fuse_write( - const char *path, const char *buffer, const remote::file_size &write_size, - const remote::file_offset &write_offset, - const remote::file_handle &handle) -> packet::error_type { +auto remote_server::fuse_write(const char *path, const char *buffer, + const remote::file_size &write_size, + const remote::file_offset &write_offset, + const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); @@ -1013,8 +1012,8 @@ auto remote_server::fuse_write_base64( } // WinFSP Layer -auto remote_server::winfsp_can_delete(PVOID file_desc, - PWSTR file_name) -> packet::error_type { +auto remote_server::winfsp_can_delete(PVOID file_desc, PWSTR file_name) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto relative_path = utils::string::to_utf8(file_name); @@ -1039,8 +1038,8 @@ auto remote_server::winfsp_can_delete(PVOID file_desc, } auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name, - UINT32 flags, - BOOLEAN &was_deleted) -> packet::error_type { + UINT32 flags, BOOLEAN &was_deleted) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto relative_path = utils::string::to_utf8(file_name); @@ -1117,8 +1116,8 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access, UINT32 attributes, UINT64 /*allocation_size*/, PVOID *file_desc, remote::file_info *file_info, - std::string &normalized_name, - BOOLEAN &exists) -> packet::error_type { + std::string &normalized_name, BOOLEAN &exists) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto relative_path = utils::string::to_utf8(file_name); @@ -1190,8 +1189,9 @@ auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info) return ret; } -auto remote_server::winfsp_get_file_info( - PVOID file_desc, remote::file_info *file_info) -> packet::error_type { +auto remote_server::winfsp_get_file_info(PVOID file_desc, + remote::file_info *file_info) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto handle = reinterpret_cast(file_desc); @@ -1234,9 +1234,10 @@ auto remote_server::winfsp_get_security_by_name( return ret; } -auto remote_server::winfsp_get_volume_info( - UINT64 &total_size, UINT64 &free_size, - std::string &volume_label) -> packet::error_type { +auto remote_server::winfsp_get_volume_info(UINT64 &total_size, + UINT64 &free_size, + std::string &volume_label) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); drive_.get_volume_info(total_size, free_size, volume_label); @@ -1253,10 +1254,11 @@ auto remote_server::winfsp_mounted(const std::wstring &location) return STATUS_SUCCESS; } -auto remote_server::winfsp_open( - PWSTR file_name, UINT32 create_options, UINT32 granted_access, - PVOID *file_desc, remote::file_info *file_info, - std::string &normalized_name) -> packet::error_type { +auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options, + UINT32 granted_access, PVOID *file_desc, + remote::file_info *file_info, + std::string &normalized_name) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto relative_path = utils::string::to_utf8(file_name); @@ -1297,10 +1299,11 @@ auto remote_server::winfsp_open( return ret; } -auto remote_server::winfsp_overwrite( - PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes, - UINT64 /*allocation_size*/, - remote::file_info *file_info) -> packet::error_type { +auto remote_server::winfsp_overwrite(PVOID file_desc, UINT32 attributes, + BOOLEAN replace_attributes, + UINT64 /*allocation_size*/, + remote::file_info *file_info) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto handle = reinterpret_cast(file_desc); @@ -1416,9 +1419,10 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, return ret; } -auto remote_server::winfsp_rename( - PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name, - BOOLEAN replace_if_exists) -> packet::error_type { +auto remote_server::winfsp_rename(PVOID /*file_desc*/, PWSTR file_name, + PWSTR new_file_name, + BOOLEAN replace_if_exists) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto relative_path = utils::string::to_utf8(file_name); @@ -1512,9 +1516,10 @@ auto remote_server::winfsp_set_basic_info( return ret; } -auto remote_server::winfsp_set_file_size( - PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, - remote::file_info *file_info) -> packet::error_type { +auto remote_server::winfsp_set_file_size(PVOID file_desc, UINT64 new_size, + BOOLEAN set_allocation_size, + remote::file_info *file_info) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto handle = reinterpret_cast(file_desc); @@ -1550,10 +1555,12 @@ auto remote_server::winfsp_unmounted(const std::wstring &location) return STATUS_SUCCESS; } -auto remote_server::winfsp_write( - PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, - BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred, - remote::file_info *file_info) -> packet::error_type { +auto remote_server::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, + UINT32 length, BOOLEAN write_to_end, + BOOLEAN constrained_io, + PUINT32 bytes_transferred, + remote::file_info *file_info) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); *bytes_transferred = 0; @@ -1601,8 +1608,9 @@ auto remote_server::winfsp_write( return ret; } -auto remote_server::json_create_directory_snapshot( - const std::string &path, json &json_data) -> packet::error_type { +auto remote_server::json_create_directory_snapshot(const std::string &path, + json &json_data) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto api_path = utils::path::create_api_path(path); @@ -1661,8 +1669,8 @@ auto remote_server::json_read_directory_snapshot( } auto remote_server::json_release_directory_snapshot( - const std::string &path, - const remote::file_handle &handle) -> packet::error_type { + const std::string &path, const remote::file_handle &handle) + -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); const auto file_path = construct_path(path); diff --git a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp index 7f224d2b..7b765afa 100644 --- a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp +++ b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,6 @@ #include "drives/remote/remote_open_file_table.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" #include "utils/collection.hpp" #include "utils/config.hpp" #include "utils/utils.hpp" @@ -42,7 +41,7 @@ void remote_open_file_table::close_all(const std::string &client_id) { auto compat_handles = std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(), std::vector(), - [&client_id](auto &&list, auto &&value) { + [&client_id](auto &&list, auto &&value) -> auto { auto &&op_info = value.second; if (op_info->client_id == client_id) { list.insert(list.end(), op_info->handles.begin(), @@ -54,7 +53,7 @@ void remote_open_file_table::close_all(const std::string &client_id) { auto handles = std::accumulate( file_lookup_.begin(), file_lookup_.end(), std::vector(), - [&client_id](auto &&list, auto &&value) { + [&client_id](auto &&list, auto &&value) -> auto { auto &&op_info = value.second; if (op_info->client_id == client_id) { list.insert(list.end(), op_info->handles.begin(), @@ -65,7 +64,7 @@ void remote_open_file_table::close_all(const std::string &client_id) { }); lock.unlock(); - for (auto &&handle : compat_handles) { + for (const auto &handle : compat_handles) { #if defined(_WIN32) _close(static_cast(handle)); #else @@ -74,7 +73,7 @@ void remote_open_file_table::close_all(const std::string &client_id) { remove_compat_open_info(handle); } - for (auto &&handle : handles) { + for (const auto &handle : handles) { #if defined(_WIN32) ::CloseHandle(handle); #else // !defined(_WIN32) @@ -85,14 +84,14 @@ void remote_open_file_table::close_all(const std::string &client_id) { std::vector dirs; lock.lock(); - for (auto &&kv : directory_lookup_) { + for (const auto &kv : directory_lookup_) { if (kv.first == client_id) { dirs.insert(dirs.end(), kv.second.begin(), kv.second.end()); } } lock.unlock(); - for (auto &&dir : dirs) { + for (const auto &dir : dirs) { remove_directory(client_id, dir); } } @@ -161,21 +160,21 @@ auto remote_open_file_table::has_compat_open_info( void remote_open_file_table::remove_all(const std::string &file_path) { unique_recur_mutex_lock lock(file_mutex_); - auto compat_open_list = std::accumulate( - compat_file_lookup_.begin(), compat_file_lookup_.end(), - std::vector(), - [&file_path](auto &&list, auto &&kv) -> std::vector { - if (kv.first == file_path) { - auto *op_info = kv.second.get(); - list.insert(list.end(), op_info->handles.begin(), - op_info->handles.end()); - } - return list; - }); + auto compat_open_list = + std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(), + std::vector(), + [&file_path](auto &&list, auto &&kv) -> auto { + if (kv.first == file_path) { + auto *op_info = kv.second.get(); + list.insert(list.end(), op_info->handles.begin(), + op_info->handles.end()); + } + return list; + }); auto open_list = std::accumulate( file_lookup_.begin(), file_lookup_.end(), std::vector(), - [&file_path](auto &&list, auto &&kv) -> std::vector { + [&file_path](auto &&list, auto &&kv) -> auto { if (kv.first == file_path) { auto *op_info = kv.second.get(); list.insert(list.end(), op_info->handles.begin(), @@ -185,11 +184,11 @@ void remote_open_file_table::remove_all(const std::string &file_path) { }); lock.unlock(); - for (auto &&handle : compat_open_list) { + for (const auto &handle : compat_open_list) { remove_compat_open_info(handle); } - for (auto &&handle : open_list) { + for (const auto &handle : open_list) { remove_open_info(handle); } } @@ -262,7 +261,7 @@ void remote_open_file_table::remove_and_close_all(const native_handle &handle) { auto op_info = *file_lookup_.at(handle_lookup_.at(handle)); lock.unlock(); - for (auto &&open_handle : op_info.handles) { + for (const auto &open_handle : op_info.handles) { #if defined(_WIN32) ::CloseHandle(open_handle); #else // !defined(_WIN32) diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp index ef7f8bb2..0b9737a3 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,28 +24,14 @@ #include "app_config.hpp" #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/drive_mounted.hpp" +#include "events/types/drive_unmount_pending.hpp" +#include "events/types/drive_unmounted.hpp" #include "types/repertory.hpp" #include "utils/path.hpp" #include "version.hpp" namespace repertory::remote_winfsp { -#define RAISE_REMOTE_WINFSP_CLIENT_EVENT(func, file, ret) \ - if (config_.get_enable_drive_events() && \ - (((config_.get_event_level() >= remote_winfsp_client_event::level) && \ - (ret != STATUS_SUCCESS)) || \ - (config_.get_event_level() >= event_level::trace))) \ - event_system::instance().raise( \ - std::string{func}, file, ret) - -// clang-format off -E_SIMPLE3(remote_winfsp_client_event, debug, true, - std::string, function, func, E_FROM_STRING, - std::string, api_path, ap, E_FROM_STRING, - packet::error_type, result, res, E_FROM_INT32 -); -// clang-format on - remote_client::remote_client(const app_config &config) : config_(config), packet_client_(config.get_remote_config()) {} @@ -62,9 +48,6 @@ auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name) packet_client_.send(function_name, request, service_flags), }; - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, - utils::path::create_api_path(utils::string::to_utf8(file_name)), ret); return ret; } @@ -85,7 +68,6 @@ auto remote_client::json_create_directory_snapshot(const std::string &path, ret = packet::decode_json(response, json_data); } - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret); return ret; } @@ -108,7 +90,6 @@ auto remote_client::json_read_directory_snapshot( ret = packet::decode_json(response, json_data); } - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret); return ret; } @@ -126,7 +107,6 @@ auto remote_client::json_release_directory_snapshot( packet_client_.send(function_name, request, service_flags), }; - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, path, ret); return ret; } @@ -161,7 +141,6 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name, remove_all(file_path); } - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret); return ret; } @@ -186,7 +165,6 @@ auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type { if ((ret == STATUS_SUCCESS) || (ret == static_cast(STATUS_INVALID_HANDLE))) { remove_open_info(handle); - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret); } } @@ -237,8 +215,6 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options, } } - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(*file_desc)), ret); return ret; } @@ -256,8 +232,6 @@ auto remote_client::winfsp_flush(PVOID file_desc, remote::file_info *file_info) }; DECODE_OR_IGNORE(&response, *file_info); - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -287,8 +261,6 @@ auto remote_client::winfsp_get_file_info(PVOID file_desc, }; DECODE_OR_IGNORE(&response, *file_info); - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -321,8 +293,6 @@ auto remote_client::winfsp_get_security_by_name(PWSTR file_name, DECODE_OR_IGNORE(&response, *attributes); } - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, - utils::string::to_utf8(file_name), ret); return ret; } @@ -361,9 +331,8 @@ auto remote_client::winfsp_mounted(const std::wstring &location) auto mount_location{ utils::string::to_utf8(location), }; - event_system::instance().raise(mount_location); + event_system::instance().raise(function_name, mount_location); - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret); return ret; } @@ -402,8 +371,6 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options, } } - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(*file_desc)), ret); return ret; } @@ -427,8 +394,6 @@ auto remote_client::winfsp_overwrite(PVOID file_desc, UINT32 attributes, }; DECODE_OR_IGNORE(&response, *file_info); - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -458,11 +423,6 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, #endif } - if (ret != STATUS_SUCCESS) { - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); - } - return ret; } @@ -485,8 +445,6 @@ auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern, ret = packet::decode_json(response, item_list); } - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -507,11 +465,6 @@ auto remote_client::winfsp_rename(PVOID file_desc, PWSTR file_name, packet_client_.send(function_name, request, service_flags), }; - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, - utils::path::create_api_path(utils::string::to_utf8(file_name)) + "|" + - utils::path::create_api_path(utils::string::to_utf8(new_file_name)), - ret); return ret; } @@ -536,8 +489,6 @@ auto remote_client::winfsp_set_basic_info( }; DECODE_OR_IGNORE(&response, *file_info); - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -559,8 +510,6 @@ auto remote_client::winfsp_set_file_size(PVOID file_desc, UINT64 new_size, }; DECODE_OR_IGNORE(&response, *file_info); - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); return ret; } @@ -571,7 +520,8 @@ auto remote_client::winfsp_unmounted(const std::wstring &location) auto mount_location{ utils::string::to_utf8(location), }; - event_system::instance().raise(mount_location); + event_system::instance().raise(function_name, + mount_location); packet request; request.encode(location); @@ -579,9 +529,9 @@ auto remote_client::winfsp_unmounted(const std::wstring &location) auto ret{ packet_client_.send(function_name, request, service_flags), }; - event_system::instance().raise(mount_location); + event_system::instance().raise(function_name, + mount_location); - RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret); return ret; } @@ -611,10 +561,6 @@ auto remote_client::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, DECODE_OR_IGNORE(&response, *bytes_transferred); DECODE_OR_IGNORE(&response, *file_info); - if (ret != STATUS_SUCCESS) { - RAISE_REMOTE_WINFSP_CLIENT_EVENT( - function_name, get_open_file_path(to_handle(file_desc)), ret); - } return ret; } diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp index 16c89776..c0cac798 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ #include "drives/remote/remote_open_file_table.hpp" #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/remote_server_event.hpp" #include "platform/platform.hpp" #include "types/remote.hpp" #include "types/repertory.hpp" @@ -42,23 +42,15 @@ #include "utils/file_utils.hpp" #include "utils/path.hpp" #include "utils/time.hpp" +#include "utils/utils.hpp" namespace repertory::remote_winfsp { #define RAISE_REMOTE_WINFSP_SERVER_EVENT(func, file, ret) \ if (config_.get_enable_drive_events() && \ - (((config_.get_event_level() >= remote_winfsp_server_event::level) && \ - (ret != STATUS_SUCCESS)) || \ + (((config_.get_event_level() >= remote_server_event::level) && \ + ((ret) != STATUS_SUCCESS)) || \ (config_.get_event_level() >= event_level::trace))) \ - event_system::instance().raise( \ - std::string{func}, file, ret) - -// clang-format off -E_SIMPLE3(remote_winfsp_server_event, debug, true, - std::string, function, FUNC, E_FROM_STRING, - std::string, api_path, AP, E_FROM_STRING, - packet::error_type, result, RES, E_FROM_INT32 -); -// clang-format on + event_system::instance().raise(file, ret, func) auto remote_server::get_next_handle() -> std::uint64_t { if (++next_handle_ == 0U) { diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp index d3bf976e..6dc41b1e 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_winfsp_drive.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,10 @@ #include "app_config.hpp" #include "events/consumers/console_consumer.hpp" #include "events/consumers/logging_consumer.hpp" -#include "events/events.hpp" +#include "events/event_system.hpp" +#include "events/types/drive_mount_failed.hpp" +#include "events/types/drive_mount_result.hpp" +#include "events/types/unmount_requested.hpp" #include "platform/platform.hpp" #include "rpc/server/server.hpp" #include "utils/collection.hpp" @@ -74,8 +77,8 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS { } if (ret != STATUS_SUCCESS) { - event_system::instance().raise(mount_location, - std::to_string(ret)); + event_system::instance().raise(ret, function_name, + mount_location); if (not lock_.set_mount_state(false, "", -1)) { utils::error::raise_error(function_name, "failed to set mount state"); } @@ -102,7 +105,7 @@ remote_winfsp_drive::remote_winfsp_drive(app_config &config, config_(config), lock_(lock), factory_(std::move(factory)) { - E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) { + E_SUBSCRIBE(unmount_requested, [this](const unmount_requested &) { std::thread([this]() { this->shutdown(); }).detach(); }); } @@ -233,12 +236,14 @@ auto remote_winfsp_drive::Init(PVOID host) -> NTSTATUS { auto remote_winfsp_drive::mount(const std::vector &drive_args) -> int { + REPERTORY_USES_FUNCTION_NAME(); + std::vector parsed_drive_args; auto force_no_console = utils::collection::includes(drive_args, "-nc"); auto enable_console = false; - for (auto &&arg : drive_args) { + for (const auto &arg : drive_args) { if (arg == "-f") { if (not force_no_console) { enable_console = true; @@ -254,8 +259,11 @@ auto remote_winfsp_drive::mount(const std::vector &drive_args) c = std::make_unique(config_.get_event_level()); } event_system::instance().start(); + auto ret = winfsp_service(lock_, *this, parsed_drive_args, config_).Run(); - event_system::instance().raise(std::to_string(ret)); + + event_system::instance().raise(function_name, "", + std::to_string(ret)); event_system::instance().stop(); c.reset(); return static_cast(ret); @@ -352,7 +360,7 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc, directory_buffer, static_cast(nullptr == marker), &ret)) { auto item_found = false; - for (auto &&item : item_list) { + for (const auto &item : item_list) { auto item_path = item["path"].get(); auto display_name = utils::string::from_utf8( utils::path::strip_to_file_name(item_path)); diff --git a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp index f07a01d2..1b954019 100644 --- a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,15 @@ #include "drives/directory_iterator.hpp" #include "events/consumers/console_consumer.hpp" #include "events/consumers/logging_consumer.hpp" -#include "events/events.hpp" +#include "events/event_system.hpp" +#include "events/types/drive_mount_failed.hpp" +#include "events/types/drive_mount_result.hpp" +#include "events/types/drive_mounted.hpp" +#include "events/types/drive_stop_timed_out.hpp" +#include "events/types/drive_unmount_pending.hpp" +#include "events/types/drive_unmounted.hpp" +#include "events/types/unmount_requested.hpp" +#include "events/types/winfsp_event.hpp" #include "platform/platform.hpp" #include "providers/i_provider.hpp" #include "types/repertory.hpp" @@ -39,23 +47,16 @@ #include "utils/polling.hpp" #include "utils/string.hpp" #include "utils/time.hpp" +#include "utils/timeout.hpp" #include "utils/utils.hpp" namespace repertory { -// clang-format off -E_SIMPLE3(winfsp_event, debug, true, - std::string, function, func, E_FROM_STRING, - std::string, api_path, ap, E_FROM_STRING, - NTSTATUS, result, res, E_FROM_INT32 -); -// clang-format on - #define RAISE_WINFSP_EVENT(func, file, ret) \ if (config_.get_enable_drive_events() && \ (((config_.get_event_level() >= winfsp_event::level) && \ - (ret != STATUS_SUCCESS)) || \ + ((ret) != STATUS_SUCCESS)) || \ (config_.get_event_level() >= event_level::trace))) \ - event_system::instance().raise(std::string{func}, file, ret) + event_system::instance().raise(file, ret, func) winfsp_drive::winfsp_service::winfsp_service( lock_data &lock, winfsp_drive &drive, std::vector drive_args, @@ -100,7 +101,9 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/) ((mount_location.size() == 3U) && (mount_location[2U] == '\\'))) && (mount_location[1U] == ':'); - auto ret = drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED; + auto ret{ + drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED, + }; if ((drive_letter && not utils::file::directory(mount_location).exists())) { auto unicode_mount_location = utils::string::from_utf8(mount_location); host_.SetFileSystemName(unicode_mount_location.data()); @@ -116,23 +119,33 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/) << mount_location << std::endl; } - if (ret != STATUS_SUCCESS) { - if (not lock_.set_mount_state(false, "", -1)) { - utils::error::raise_error(function_name, ret, - "failed to set mount state"); - } - event_system::instance().raise(mount_location, - std::to_string(ret)); + if (ret == STATUS_SUCCESS) { + return ret; } + if (not lock_.set_mount_state(false, "", -1)) { + utils::error::raise_error(function_name, ret, "failed to set mount state"); + } + + event_system::instance().raise(ret, function_name, + mount_location); + return ret; } auto winfsp_drive::winfsp_service::OnStop() -> NTSTATUS { REPERTORY_USES_FUNCTION_NAME(); + timeout stop_timeout( + []() { + event_system::instance().raise(function_name); + app_config::set_stop_requested(); + }, + 30s); host_.Unmount(); + stop_timeout.disable(); + if (not lock_.set_mount_state(false, "", -1)) { utils::error::raise_error(function_name, "failed to set mount state"); } @@ -143,7 +156,7 @@ auto winfsp_drive::winfsp_service::OnStop() -> NTSTATUS { winfsp_drive::winfsp_drive(app_config &config, lock_data &lock, i_provider &provider) : provider_(provider), config_(config), lock_(lock) { - E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) { + E_SUBSCRIBE(unmount_requested, [this](const unmount_requested &) { std::thread([this]() { this->shutdown(); }).detach(); }); } @@ -578,12 +591,14 @@ auto winfsp_drive::Init(PVOID host) -> NTSTATUS { } auto winfsp_drive::mount(const std::vector &drive_args) -> int { + REPERTORY_USES_FUNCTION_NAME(); + std::vector parsed_drive_args; auto force_no_console = utils::collection::includes(drive_args, "-nc"); auto enable_console = false; - for (auto &&arg : drive_args) { + for (const auto &arg : drive_args) { if (arg == "-f") { if (not force_no_console) { enable_console = true; @@ -598,35 +613,40 @@ auto winfsp_drive::mount(const std::vector &drive_args) -> int { if (enable_console) { cons = std::make_unique(config_.get_event_level()); } + event_system::instance().start(); + auto svc = winfsp_service(lock_, *this, parsed_drive_args, config_); auto ret = svc.Run(); - event_system::instance().raise(std::to_string(ret)); + event_system::instance().raise(function_name, "", + std::to_string(ret)); event_system::instance().stop(); cons.reset(); + return static_cast(ret); } auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS { REPERTORY_USES_FUNCTION_NAME(); - auto ret{STATUS_SUCCESS}; - if (not utils::file::change_to_process_directory()) { - return static_cast(utils::get_last_error_code()); - } - - auto *file_system_host{ - reinterpret_cast(host), - }; - fm_ = std::make_unique(config_, provider_); - server_ = std::make_unique(config_, provider_, *fm_); - if (not provider_.is_read_only()) { - eviction_ = std::make_unique(provider_, config_, *fm_); - } - try { + if (not utils::file::change_to_process_directory()) { + return static_cast(utils::get_last_error_code()); + } + + auto *file_system_host{ + reinterpret_cast(host), + }; + + fm_ = std::make_unique(config_, provider_); + server_ = std::make_unique(config_, provider_, *fm_); + if (not provider_.is_read_only()) { + eviction_ = std::make_unique(provider_, config_, *fm_); + } + server_->start(); + if (not provider_.start( [this](bool directory, api_file &file) -> api_error { return provider_meta_handler(provider_, directory, file); @@ -646,30 +666,22 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS { config_, *this, mount_location); } + polling::instance().start(&config_); + if (not lock_.set_mount_state(true, mount_location, ::GetCurrentProcessId())) { utils::error::raise_error(function_name, "failed to set mount state"); } - polling::instance().start(&config_); - - event_system::instance().raise(mount_location); + event_system::instance().raise(function_name, + mount_location); + return STATUS_SUCCESS; } catch (const std::exception &e) { utils::error::raise_error(function_name, e, "exception occurred"); - if (remote_server_) { - remote_server_.reset(); - } - server_->stop(); - polling::instance().stop(); - if (eviction_) { - eviction_->stop(); - } - fm_->stop(); - provider_.stop(); - ret = STATUS_INTERNAL_ERROR; } - return ret; + stop_all(); + return STATUS_INTERNAL_ERROR; } auto winfsp_drive::Open(PWSTR file_name, UINT32 create_options, @@ -896,103 +908,97 @@ auto winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc, std::shared_ptr file; if (fm_->get_open_file(handle, false, file)) { api_path = file->get_api_path(); - bool exists{}; - error = provider_.is_directory(api_path, exists); - if (error == api_error::success) { - if (exists) { - directory_item_list list{}; - error = provider_.get_directory_items(api_path, list); - if (error == api_error::success) { - directory_iterator iterator(std::move(list)); - auto status_result = STATUS_SUCCESS; - auto **directory_buffer = - &file->get_open_data(handle).directory_buffer; - if (FspFileSystemAcquireDirectoryBuffer( - directory_buffer, static_cast(nullptr == marker), - &status_result) != 0U) { - directory_item dir_item{}; - auto offset = - marker == nullptr - ? 0U - : iterator.get_next_directory_offset( - utils::path::create_api_path(utils::path::combine( - api_path, {utils::string::to_utf8(marker)}))); - while ((error = iterator.get_directory_item( - offset++, dir_item)) == api_error::success) { - if (dir_item.api_path == ".") { - auto res = provider_.get_item_meta(api_path, dir_item.meta); - if (res != api_error::success) { - error = res; - utils::error::raise_api_path_error(function_name, - dir_item.api_path, error, - "failed to get . meta"); - break; - } - } else if (dir_item.api_path == "..") { - // TODO handle '/' parent - auto res = provider_.get_item_meta( - utils::path::get_parent_api_path(api_path), - dir_item.meta); - if (res != api_error::success) { - error = res; - utils::error::raise_api_path_error(function_name, - dir_item.api_path, error, - "failed to get .. meta"); - break; - } - } - - if (dir_item.meta.empty()) { - error = api_error::error; - utils::error::raise_api_path_error( - function_name, dir_item.api_path, api_error::error, - "item meta is empty"); + if (file->is_directory()) { + directory_item_list list{}; + error = provider_.get_directory_items(api_path, list); + if (error == api_error::success) { + directory_iterator iterator(std::move(list)); + auto status_result = STATUS_SUCCESS; + auto **directory_buffer = + &file->get_open_data(handle).directory_buffer; + if (FspFileSystemAcquireDirectoryBuffer( + directory_buffer, static_cast(nullptr == marker), + &status_result) != 0U) { + directory_item dir_item{}; + auto offset = + marker == nullptr + ? 0U + : iterator.get_next_directory_offset( + utils::path::create_api_path(utils::path::combine( + api_path, {utils::string::to_utf8(marker)}))); + while ((error = iterator.get_directory_item(offset++, dir_item)) == + api_error::success) { + if (dir_item.api_path == ".") { + auto res = provider_.get_item_meta(api_path, dir_item.meta); + if (res != api_error::success) { + error = res; + utils::error::raise_api_path_error(function_name, + dir_item.api_path, error, + "failed to get . meta"); + break; + } + } else if (dir_item.api_path == "..") { + // TODO handle '/' parent + auto res = provider_.get_item_meta( + utils::path::get_parent_api_path(api_path), dir_item.meta); + if (res != api_error::success) { + error = res; + utils::error::raise_api_path_error(function_name, + dir_item.api_path, error, + "failed to get .. meta"); break; } - - auto display_name = utils::string::from_utf8( - utils::path::strip_to_file_name(dir_item.api_path)); - union { - UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + - ((repertory::max_path_length + 1U) * sizeof(WCHAR))]; - FSP_FSCTL_DIR_INFO D; - } directory_info_buffer; - - auto *directory_info = &directory_info_buffer.D; - ::ZeroMemory(directory_info, sizeof(*directory_info)); - directory_info->Size = static_cast( - FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + - (std::min(static_cast(repertory::max_path_length), - display_name.size()) * - sizeof(WCHAR))); - - populate_file_info(dir_item.size, dir_item.meta, - directory_info->FileInfo); - ::wcscpy_s(&directory_info->FileNameBuf[0U], - repertory::max_path_length, display_name.data()); - - FspFileSystemFillDirectoryBuffer( - directory_buffer, directory_info, &status_result); } - FspFileSystemReleaseDirectoryBuffer(directory_buffer); + if (dir_item.meta.empty()) { + error = api_error::error; + utils::error::raise_api_path_error( + function_name, dir_item.api_path, api_error::error, + "item meta is empty"); + break; + } + + auto display_name = utils::string::from_utf8( + utils::path::strip_to_file_name(dir_item.api_path)); + union { + UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + + ((repertory::max_path_length + 1U) * sizeof(WCHAR))]; + FSP_FSCTL_DIR_INFO D; + } directory_info_buffer; + + auto *directory_info = &directory_info_buffer.D; + ::ZeroMemory(directory_info, sizeof(*directory_info)); + directory_info->Size = static_cast( + FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + + (std::min(static_cast(repertory::max_path_length), + display_name.size()) * + sizeof(WCHAR))); + + populate_file_info(dir_item.size, dir_item.meta, + directory_info->FileInfo); + ::wcscpy_s(&directory_info->FileNameBuf[0U], + repertory::max_path_length, display_name.data()); + + FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info, + &status_result); } - if (status_result == STATUS_SUCCESS) { - FspFileSystemReadDirectoryBuffer(directory_buffer, marker, buffer, - buffer_length, - bytes_transferred); - if (error == api_error::directory_end_of_files) { - error = api_error::success; - } - } else { - RAISE_WINFSP_EVENT(function_name, api_path, status_result); - return status_result; - } + FspFileSystemReleaseDirectoryBuffer(directory_buffer); + } + + if (status_result == STATUS_SUCCESS) { + FspFileSystemReadDirectoryBuffer(directory_buffer, marker, buffer, + buffer_length, bytes_transferred); + if (error == api_error::directory_end_of_files) { + error = api_error::success; + } + } else { + RAISE_WINFSP_EVENT(function_name, api_path, status_result); + return status_result; } - } else { - error = api_error::directory_not_found; } + } else { + error = api_error::directory_not_found; } } } @@ -1162,31 +1168,58 @@ auto winfsp_drive::SetFileSize(PVOID /*file_node*/, PVOID file_desc, })); } +void winfsp_drive::stop_all() { + REPERTORY_USES_FUNCTION_NAME(); + + mutex_lock lock(stop_all_mtx_); + + auto future = std::async(std::launch::async, [this]() { + remote_server_.reset(); + + if (server_) { + server_->stop(); + } + + polling::instance().stop(); + + if (eviction_) { + eviction_->stop(); + } + + if (fm_) { + fm_->stop(); + } + + provider_.stop(); + + eviction_.reset(); + fm_.reset(); + server_.reset(); + }); + + if (future.wait_for(30s) == std::future_status::timeout) { + event_system::instance().raise(function_name); + app_config::set_stop_requested(); + future.wait(); + } + + if (not lock_.set_mount_state(false, "", -1)) { + utils::error::raise_error(function_name, "failed to set mount state"); + } +} + VOID winfsp_drive::Unmounted(PVOID host) { REPERTORY_USES_FUNCTION_NAME(); auto *file_system_host = reinterpret_cast(host); auto mount_location = parse_mount_location(file_system_host->MountPoint()); - event_system::instance().raise(mount_location); - if (remote_server_) { - remote_server_.reset(); - } - server_->stop(); - polling::instance().stop(); - if (eviction_) { - eviction_->stop(); - } - fm_->stop(); - provider_.stop(); - server_.reset(); - fm_.reset(); - eviction_.reset(); + event_system::instance().raise(function_name, + mount_location); - if (not lock_.set_mount_state(false, "", -1)) { - utils::error::raise_error(function_name, "failed to set mount state"); - } + stop_all(); - event_system::instance().raise(mount_location); + event_system::instance().raise(function_name, + mount_location); config_.save(); } diff --git a/repertory/librepertory/src/events/consumers/console_consumer.cpp b/repertory/librepertory/src/events/consumers/console_consumer.cpp index c0fda9be..3e293fe0 100644 --- a/repertory/librepertory/src/events/consumers/console_consumer.cpp +++ b/repertory/librepertory/src/events/consumers/console_consumer.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,10 +21,11 @@ */ #include "events/consumers/console_consumer.hpp" -#include "events/events.hpp" +#include "events/i_event.hpp" +#include "events/types/event_level_changed.hpp" #include "spdlog/async.h" -#include "spdlog/spdlog.h" #include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/spdlog.h" namespace repertory { console_consumer::console_consumer() : console_consumer(event_level::info) {} @@ -62,35 +63,32 @@ console_consumer::console_consumer(event_level level) { set_level(level); E_SUBSCRIBE_ALL(process_event); - E_SUBSCRIBE_EXACT(event_level_changed, - [](const event_level_changed &changed) { - set_level(event_level_from_string( - changed.get_new_event_level().get())); - }); + E_SUBSCRIBE(event_level_changed, + [](auto &&event) { set_level(event.new_level); }); } console_consumer::~console_consumer() { E_CONSUMER_RELEASE(); } -void console_consumer::process_event(const event &event) const { - switch (event.get_event_level()) { +void console_consumer::process_event(const i_event &evt) { + switch (evt.get_event_level()) { case event_level::critical: - spdlog::get("console")->critical(event.get_single_line()); + spdlog::get("console")->critical(evt.get_single_line()); break; case event_level::error: - spdlog::get("console")->error(event.get_single_line()); + spdlog::get("console")->error(evt.get_single_line()); break; case event_level::warn: - spdlog::get("console")->warn(event.get_single_line()); + spdlog::get("console")->warn(evt.get_single_line()); break; case event_level::info: - spdlog::get("console")->info(event.get_single_line()); + spdlog::get("console")->info(evt.get_single_line()); break; case event_level::debug: - spdlog::get("console")->debug(event.get_single_line()); + spdlog::get("console")->debug(evt.get_single_line()); break; case event_level::trace: default: - spdlog::get("console")->trace(event.get_single_line()); + spdlog::get("console")->trace(evt.get_single_line()); break; } } diff --git a/repertory/librepertory/src/events/consumers/logging_consumer.cpp b/repertory/librepertory/src/events/consumers/logging_consumer.cpp index b761183f..2995f0cd 100644 --- a/repertory/librepertory/src/events/consumers/logging_consumer.cpp +++ b/repertory/librepertory/src/events/consumers/logging_consumer.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,7 +21,8 @@ */ #include "events/consumers/logging_consumer.hpp" -#include "events/events.hpp" +#include "events/i_event.hpp" +#include "events/types/event_level_changed.hpp" #include "spdlog/async.h" #include "spdlog/sinks/rotating_file_sink.h" #include "spdlog/spdlog.h" @@ -66,35 +67,32 @@ logging_consumer::logging_consumer(event_level level, set_level(level); E_SUBSCRIBE_ALL(process_event); - E_SUBSCRIBE_EXACT(event_level_changed, - [](const event_level_changed &changed) { - set_level(event_level_from_string( - changed.get_new_event_level().get())); - }); + E_SUBSCRIBE(event_level_changed, + [](auto &&event) { set_level(event.new_level); }); } logging_consumer::~logging_consumer() { E_CONSUMER_RELEASE(); } -void logging_consumer::process_event(const event &event) const { - switch (event.get_event_level()) { +void logging_consumer::process_event(const i_event &evt) { + switch (evt.get_event_level()) { case event_level::critical: - spdlog::get("file")->critical(event.get_single_line()); + spdlog::get("file")->critical(evt.get_single_line()); break; case event_level::error: - spdlog::get("file")->error(event.get_single_line()); + spdlog::get("file")->error(evt.get_single_line()); break; case event_level::warn: - spdlog::get("file")->warn(event.get_single_line()); + spdlog::get("file")->warn(evt.get_single_line()); break; case event_level::info: - spdlog::get("file")->info(event.get_single_line()); + spdlog::get("file")->info(evt.get_single_line()); break; case event_level::debug: - spdlog::get("file")->debug(event.get_single_line()); + spdlog::get("file")->debug(evt.get_single_line()); break; case event_level::trace: default: - spdlog::get("file")->trace(event.get_single_line()); + spdlog::get("file")->trace(evt.get_single_line()); break; } } diff --git a/repertory/librepertory/src/events/event.cpp b/repertory/librepertory/src/events/event.cpp deleted file mode 100644 index 62e79fa5..00000000 --- a/repertory/librepertory/src/events/event.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright <2018-2024> - - 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 "events/event.hpp" - -#include "utils/string.hpp" - -namespace repertory { -auto event_level_from_string(std::string level, event_level default_level) - -> event_level { - level = utils::string::to_lower(level); - if (level == "critical" || level == "event_level::critical") { - return event_level::critical; - } - - if (level == "debug" || level == "event_level::debug") { - return event_level::debug; - } - - if (level == "warn" || level == "event_level::warn") { - return event_level::warn; - } - - if (level == "info" || level == "event_level::info") { - return event_level::info; - } - - if (level == "error" || level == "event_level::error") { - return event_level::error; - } - - if (level == "trace" || level == "event_level::trace") { - return event_level::trace; - } - - return default_level; -} - -auto event_level_to_string(event_level level) -> std::string { - switch (level) { - case event_level::critical: - return "critical"; - case event_level::debug: - return "debug"; - case event_level::error: - return "error"; - case event_level::info: - return "info"; - case event_level::warn: - return "warn"; - case event_level::trace: - return "trace"; - default: - return "info"; - } -} -} // namespace repertory diff --git a/repertory/librepertory/src/events/event_system.cpp b/repertory/librepertory/src/events/event_system.cpp new file mode 100644 index 00000000..efcc4b7e --- /dev/null +++ b/repertory/librepertory/src/events/event_system.cpp @@ -0,0 +1,165 @@ +/* + Copyright <2018-2025> + + 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 "events/event_system.hpp" + +#include "app_config.hpp" +#include "events/i_event.hpp" +#include "utils/collection.hpp" + +namespace repertory { +event_system event_system::instance_{}; + +auto event_system::instance() -> event_system & { return instance_; } + +void event_system::attach(event_consumer *consumer) { + recur_mutex_lock lock(consumer_mutex_); + event_consumers_[""].push_back(consumer); +} + +void event_system::attach(std::string_view event_name, + event_consumer *consumer) { + recur_mutex_lock lock(consumer_mutex_); + event_consumers_[std::string{event_name}].push_back(consumer); +} + +auto event_system::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + +void event_system::process_events() { + unique_mutex_lock lock(event_mutex_); + const auto lock_and_notify = [this, &lock]() { + lock.lock(); + event_notify_.notify_all(); + lock.unlock(); + }; + + if (not get_stop_requested() && event_list_.empty()) { + event_notify_.wait_for(lock, queue_wait_secs); + } + + std::vector> event_list; + std::swap(event_list, event_list_); + lock.unlock(); + + if (event_list.empty()) { + lock_and_notify(); + return; + } + + const auto notify_events = [this](std::string_view name, + const i_event &event) { + std::deque> futures; + recur_mutex_lock consumer_lock(consumer_mutex_); + for (auto *consumer : event_consumers_[std::string{name}]) { + futures.emplace_back(std::async(std::launch::async, [consumer, &event]() { + consumer->notify_event(event); + })); + } + + while (not futures.empty()) { + futures.front().get(); + futures.pop_front(); + } + }; + + for (const auto &evt : event_list) { + notify_events("", *evt); + notify_events(evt->get_name(), *evt); + } + + lock_and_notify(); +} + +void event_system::queue_event(std::shared_ptr evt) { + unique_mutex_lock lock(event_mutex_); + event_list_.push_back(std::move(evt)); + auto size = event_list_.size(); + event_notify_.notify_all(); + lock.unlock(); + + for (std::uint8_t retry{0U}; + size > max_queue_size && retry < max_queue_retry && + not get_stop_requested(); + ++retry) { + lock.lock(); + size = event_list_.size(); + if (size > max_queue_size) { + event_notify_.wait_for(lock, queue_wait_secs); + size = event_list_.size(); + } + + event_notify_.notify_all(); + lock.unlock(); + } +} + +void event_system::release(event_consumer *consumer) { + recur_mutex_lock lock(consumer_mutex_); + auto iter = + std::ranges::find_if(event_consumers_, [&consumer](auto &&item) -> bool { + return utils::collection::includes(item.second, consumer); + }); + + if (iter != event_consumers_.end()) { + utils::collection::remove_element(iter->second, consumer); + } +} + +void event_system::start() { + mutex_lock lock(run_mutex_); + if (event_thread_) { + event_notify_.notify_all(); + return; + } + + stop_requested_ = false; + + event_thread_ = std::make_unique([this]() { + while (not get_stop_requested()) { + process_events(); + } + }); + event_notify_.notify_all(); +} + +void event_system::stop() { + unique_mutex_lock lock(run_mutex_); + if (not event_thread_) { + event_notify_.notify_all(); + return; + } + + stop_requested_ = true; + + std::unique_ptr thread{nullptr}; + std::swap(thread, event_thread_); + + event_notify_.notify_all(); + lock.unlock(); + + thread->join(); + thread.reset(); + + process_events(); +} +} // namespace repertory diff --git a/repertory/librepertory/src/file_manager/cache_size_mgr.cpp b/repertory/librepertory/src/file_manager/cache_size_mgr.cpp index 5dde8fa1..b661ecf7 100644 --- a/repertory/librepertory/src/file_manager/cache_size_mgr.cpp +++ b/repertory/librepertory/src/file_manager/cache_size_mgr.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,52 +22,55 @@ #include "file_manager/cache_size_mgr.hpp" #include "app_config.hpp" -#include "events/event.hpp" #include "events/event_system.hpp" +#include "events/types/invalid_cache_size.hpp" +#include "events/types/max_cache_size_reached.hpp" #include "types/startup_exception.hpp" #include "utils/file_utils.hpp" namespace repertory { -// clang-format off -E_SIMPLE2(invalid_cache_size, warn, true, - std::uint64_t, cache_size, sz, E_FROM_UINT64, - std::uint64_t, by, by, E_FROM_UINT64 -); - -E_SIMPLE2(max_cache_size_reached, warn, true, - std::uint64_t, cache_size, sz, E_FROM_UINT64, - std::uint64_t, max_cache_size, max, E_FROM_UINT64 -); -// clang-format on - cache_size_mgr cache_size_mgr::instance_{}; -// TODO add timeout auto cache_size_mgr::expand(std::uint64_t size) -> api_error { - if (size == 0U) { - return api_error::success; - } + REPERTORY_USES_FUNCTION_NAME(); unique_mutex_lock lock(mtx_); + if (cfg_ == nullptr) { + notify_.notify_all(); return api_error::cache_not_initialized; } + if (size == 0U) { + notify_.notify_all(); + return api_error::success; + } + + auto last_cache_size{cache_size_}; cache_size_ += size; - auto max_cache_size = cfg_->get_max_cache_size_bytes(); + auto max_cache_size{cfg_->get_max_cache_size_bytes()}; - auto cache_dir = utils::file::directory{cfg_->get_cache_directory()}; - while (not stop_requested_ && cache_size_ > max_cache_size && + auto cache_dir{ + utils::file::directory{cfg_->get_cache_directory()}, + }; + while (not get_stop_requested() && cache_size_ > max_cache_size && cache_dir.count() > 1U) { - event_system::instance().raise(cache_size_, - max_cache_size); - notify_.wait(lock); + if (last_cache_size != cache_size_) { + event_system::instance().raise( + cache_size_, function_name, max_cache_size); + last_cache_size = cache_size_; + } + notify_.wait_for(lock, cache_wait_secs); } notify_.notify_all(); - return api_error::success; + return get_stop_requested() ? api_error::error : api_error::success; +} + +auto cache_size_mgr::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); } void cache_size_mgr::initialize(app_config *cfg) { @@ -80,7 +83,9 @@ void cache_size_mgr::initialize(app_config *cfg) { stop_requested_ = false; - auto cache_dir = utils::file::directory{cfg_->get_cache_directory()}; + auto cache_dir{ + utils::file::directory{cfg_->get_cache_directory()}, + }; if (not cache_dir.create_directory()) { throw startup_exception(fmt::format("failed to create cache directory|{}", cache_dir.get_path())); @@ -92,6 +97,8 @@ void cache_size_mgr::initialize(app_config *cfg) { } auto cache_size_mgr::shrink(std::uint64_t size) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + mutex_lock lock(mtx_); if (size == 0U) { notify_.notify_all(); @@ -101,7 +108,8 @@ auto cache_size_mgr::shrink(std::uint64_t size) -> api_error { if (cache_size_ >= size) { cache_size_ -= size; } else { - event_system::instance().raise(cache_size_, size); + event_system::instance().raise(cache_size_, + function_name, size); cache_size_ = 0U; } diff --git a/repertory/librepertory/src/file_manager/direct_open_file.cpp b/repertory/librepertory/src/file_manager/direct_open_file.cpp index 581af339..f48fb35e 100644 --- a/repertory/librepertory/src/file_manager/direct_open_file.cpp +++ b/repertory/librepertory/src/file_manager/direct_open_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/file_manager/file_manager.cpp b/repertory/librepertory/src/file_manager/file_manager.cpp index ae739866..8d8d512c 100644 --- a/repertory/librepertory/src/file_manager/file_manager.cpp +++ b/repertory/librepertory/src/file_manager/file_manager.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,25 @@ #include "app_config.hpp" #include "db/file_mgr_db.hpp" +#include "events/types/download_restore_failed.hpp" +#include "events/types/download_restored.hpp" +#include "events/types/download_resume_add_failed.hpp" +#include "events/types/download_resume_added.hpp" +#include "events/types/download_resume_removed.hpp" +#include "events/types/download_type_selected.hpp" +#include "events/types/file_upload_failed.hpp" +#include "events/types/file_upload_not_found.hpp" +#include "events/types/file_upload_queued.hpp" +#include "events/types/file_upload_removed.hpp" +#include "events/types/file_upload_retry.hpp" +#include "events/types/filesystem_item_evicted.hpp" +#include "events/types/item_timeout.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "file_manager/cache_size_mgr.hpp" #include "file_manager/direct_open_file.hpp" -#include "file_manager/events.hpp" #include "file_manager/open_file.hpp" #include "file_manager/open_file_base.hpp" #include "file_manager/ring_buffer_open_file.hpp" @@ -49,10 +65,8 @@ file_manager::file_manager(app_config &config, i_provider &provider) return; } - E_SUBSCRIBE_EXACT(file_upload_completed, - [this](const file_upload_completed &completed) { - this->upload_completed(completed); - }); + E_SUBSCRIBE(file_upload_completed, + [this](auto &&event) { this->upload_completed(event); }); } file_manager::~file_manager() { @@ -93,11 +107,13 @@ auto file_manager::close_all(const std::string &api_path) -> bool { } void file_manager::close_timed_out_files() { + REPERTORY_USES_FUNCTION_NAME(); + unique_recur_mutex_lock file_lock(open_file_mtx_); auto closeable_list = std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(), std::vector>{}, - [](auto items, const auto &item) -> auto { + [](auto &&items, auto &&item) -> auto { if (item.second->get_open_file_count() == 0U && item.second->can_close()) { items.push_back(item.second); @@ -111,8 +127,8 @@ void file_manager::close_timed_out_files() { for (auto &closeable_file : closeable_list) { closeable_file->close(); - event_system::instance().raise( - closeable_file->get_api_path()); + event_system::instance().raise(closeable_file->get_api_path(), + function_name); } closeable_list.clear(); } @@ -187,8 +203,8 @@ auto file_manager::evict_file(const std::string &api_path) -> bool { auto removed = remove_source_and_shrink_cache(api_path, fsi.source_path, fsi.size, allocated); if (removed) { - event_system::instance().raise(api_path, - fsi.source_path); + event_system::instance().raise( + api_path, function_name, fsi.source_path); } return removed; @@ -218,10 +234,9 @@ auto file_manager::get_next_handle() -> std::uint64_t { auto file_manager::get_open_file_by_handle(std::uint64_t handle) const -> std::shared_ptr { auto file_iter = - std::find_if(open_file_lookup_.begin(), open_file_lookup_.end(), - [&handle](auto &&item) -> bool { - return item.second->has_handle(handle); - }); + std::ranges::find_if(open_file_lookup_, [&handle](auto &&item) -> bool { + return item.second->has_handle(handle); + }); return (file_iter == open_file_lookup_.end()) ? nullptr : file_iter->second; } @@ -235,6 +250,10 @@ auto file_manager::get_open_file_count(const std::string &api_path) const auto file_manager::get_open_file(std::uint64_t handle, bool write_supported, std::shared_ptr &file) -> bool { + if (write_supported && provider_.is_read_only()) { + return false; + } + unique_recur_mutex_lock open_lock(open_file_mtx_); auto file_ptr = get_open_file_by_handle(handle); if (not file_ptr) { @@ -265,23 +284,26 @@ auto file_manager::get_open_file_count() const -> std::size_t { auto file_manager::get_open_files() const -> std::unordered_map { - std::unordered_map ret; - recur_mutex_lock open_lock(open_file_mtx_); - for (const auto &item : open_file_lookup_) { - ret[item.first] = item.second->get_open_file_count(); - } - - return ret; + return std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(), + std::unordered_map{}, + [](auto &&map, auto &&item) -> auto { + map[item.first] = item.second->get_open_file_count(); + return map; + }); } auto file_manager::get_open_handle_count() const -> std::size_t { recur_mutex_lock open_lock(open_file_mtx_); - return std::accumulate( - open_file_lookup_.begin(), open_file_lookup_.end(), std::size_t(0U), - [](std::size_t count, const auto &item) -> std::size_t { - return count + item.second->get_open_file_count(); - }); + return std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(), + std::size_t(0U), + [](auto &&count, auto &&item) -> auto { + return count + item.second->get_open_file_count(); + }); +} + +auto file_manager::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); } auto file_manager::get_stored_downloads() const @@ -380,10 +402,11 @@ auto file_manager::open(const std::string &api_path, bool directory, return open(api_path, directory, ofd, handle, file, nullptr); } -auto file_manager::open( - const std::string &api_path, bool directory, const open_file_data &ofd, - std::uint64_t &handle, std::shared_ptr &file, - std::shared_ptr closeable_file) -> api_error { +auto file_manager::open(const std::string &api_path, bool directory, + const open_file_data &ofd, std::uint64_t &handle, + std::shared_ptr &file, + std::shared_ptr closeable_file) + -> api_error { REPERTORY_USES_FUNCTION_NAME(); const auto create_and_add_handle = @@ -435,6 +458,10 @@ auto file_manager::open( auto ring_size{ring_buffer_file_size / chunk_size}; const auto get_download_type = [&](download_type type) -> download_type { + if (not directory && provider_.is_read_only()) { + return download_type::direct; + } + if (directory || fsi.size == 0U || is_processing(api_path)) { return download_type::default_; } @@ -479,7 +506,7 @@ auto file_manager::open( : preferred_type); if (not directory) { event_system::instance().raise( - fsi.api_path, fsi.source_path, type); + fsi.api_path, fsi.source_path, function_name, type); } switch (type) { @@ -512,6 +539,8 @@ void file_manager::queue_upload(const i_open_file &file) { void file_manager::queue_upload(const std::string &api_path, const std::string &source_path, bool no_lock) { + REPERTORY_USES_FUNCTION_NAME(); + if (provider_.is_read_only()) { return; } @@ -528,10 +557,11 @@ void file_manager::queue_upload(const std::string &api_path, source_path, })) { remove_resume(api_path, source_path, true); - event_system::instance().raise(api_path, source_path); + event_system::instance().raise(api_path, function_name, + source_path); } else { event_system::instance().raise( - api_path, source_path, "failed to queue upload"); + api_path, "failed to queue upload", function_name, source_path); } if (not no_lock) { @@ -575,6 +605,8 @@ void file_manager::remove_resume(const std::string &api_path, void file_manager::remove_resume(const std::string &api_path, const std::string &source_path, bool no_lock) { + REPERTORY_USES_FUNCTION_NAME(); + if (provider_.is_read_only()) { return; } @@ -585,8 +617,8 @@ void file_manager::remove_resume(const std::string &api_path, } if (mgr_db_->remove_resume(api_path)) { - event_system::instance().raise(api_path, - source_path); + event_system::instance().raise( + api_path, source_path, function_name); } if (not no_lock) { @@ -662,7 +694,8 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock) { } if (removed) { - event_system::instance().raise(api_path); + event_system::instance().raise(api_path, + function_name); } if (not no_lock) { @@ -747,8 +780,8 @@ auto file_manager::rename_directory(const std::string &from_api_path, } auto file_manager::rename_file(const std::string &from_api_path, - const std::string &to_api_path, - bool overwrite) -> api_error { + const std::string &to_api_path, bool overwrite) + -> api_error { if (not provider_.is_rename_supported()) { return api_error::not_implemented; } @@ -826,6 +859,8 @@ void file_manager::start() { return; } + event_system::instance().raise(function_name, + "file_manager"); stop_requested_ = false; polling::instance().set_callback({ @@ -836,6 +871,8 @@ void file_manager::start() { if (provider_.is_read_only()) { stop_requested_ = false; + event_system::instance().raise(function_name, + "file_manager"); return; } @@ -850,15 +887,18 @@ void file_manager::start() { if (res != api_error::success) { event_system::instance().raise( entry.api_path, entry.source_path, - "failed to get filesystem item|" + api_error_to_string(res)); + fmt::format("failed to get filesystem item|{}", + api_error_to_string(res)), + function_name); continue; } if (entry.source_path != fsi.source_path) { event_system::instance().raise( fsi.api_path, fsi.source_path, - "source path mismatch|expected|" + entry.source_path + "|actual|" + - fsi.source_path); + fmt::format("source path mismatch|expected|{}|actual|{}", + entry.source_path, fsi.source_path), + function_name); continue; } @@ -866,8 +906,9 @@ void file_manager::start() { if (not opt_size.has_value()) { event_system::instance().raise( fsi.api_path, fsi.source_path, - "failed to get file size: " + - std::to_string(utils::get_last_error_code())); + fmt::format("failed to get file size|{}", + utils::get_last_error_code()), + function_name); continue; } @@ -875,8 +916,9 @@ void file_manager::start() { if (file_size != fsi.size) { event_system::instance().raise( fsi.api_path, fsi.source_path, - "file size mismatch|expected|" + std::to_string(fsi.size) + - "|actual|" + std::to_string(file_size)); + fmt::format("file size mismatch|expected|{}|actual|{}", fsi.size, + file_size), + function_name); continue; } @@ -887,23 +929,27 @@ void file_manager::start() { : 0U, fsi, provider_, entry.read_state, *this); open_file_lookup_[entry.api_path] = closeable_file; - event_system::instance().raise(fsi.api_path, - fsi.source_path); + event_system::instance().raise( + fsi.api_path, fsi.source_path, function_name); } catch (const std::exception &ex) { utils::error::raise_error(function_name, ex, "query error"); } } upload_thread_ = std::make_unique([this] { upload_handler(); }); - event_system::instance().raise("file_manager"); + event_system::instance().raise(function_name, + "file_manager"); } void file_manager::stop() { + REPERTORY_USES_FUNCTION_NAME(); + if (stop_requested_) { return; } - event_system::instance().raise("file_manager"); + event_system::instance().raise(function_name, + "file_manager"); stop_requested_ = true; @@ -937,10 +983,13 @@ void file_manager::stop() { upload_thread_.reset(); - event_system::instance().raise("file_manager"); + event_system::instance().raise(function_name, + "file_manager"); } void file_manager::store_resume(const i_open_file &file) { + REPERTORY_USES_FUNCTION_NAME(); + if (provider_.is_read_only()) { return; } @@ -952,12 +1001,13 @@ void file_manager::store_resume(const i_open_file &file) { file.get_source_path(), })) { event_system::instance().raise( - file.get_api_path(), file.get_source_path()); + file.get_api_path(), file.get_source_path(), function_name); return; } event_system::instance().raise( - file.get_api_path(), file.get_source_path(), "failed to store resume"); + file.get_api_path(), file.get_source_path(), "failed to store resume", + function_name); } void file_manager::swap_renamed_items(std::string from_api_path, @@ -990,32 +1040,29 @@ void file_manager::upload_completed(const file_upload_completed &evt) { unique_mutex_lock upload_lock(upload_mtx_); - if (not utils::string::to_bool(evt.get_cancelled().get())) { - auto err = api_error_from_string(evt.get_result().get()); - if (err == api_error::success) { - if (not mgr_db_->remove_upload_active( - evt.get_api_path().get())) { + if (not evt.cancelled) { + if (evt.error == api_error::success) { + if (not mgr_db_->remove_upload_active(evt.api_path)) { utils::error::raise_api_path_error( - function_name, evt.get_api_path().get(), - evt.get_source().get(), + function_name, evt.api_path, evt.source_path, evt.error, "failed to remove from upload_active table"); } - upload_lookup_.erase(evt.get_api_path()); + upload_lookup_.erase(evt.api_path); } else { bool exists{}; - auto res = provider_.is_file(evt.get_api_path(), exists); + auto res = provider_.is_file(evt.api_path, exists); if ((res == api_error::success && not exists) || - not utils::file::file(evt.get_source().get()).exists()) { + not utils::file::file(evt.source_path).exists()) { event_system::instance().raise( - evt.get_api_path(), evt.get_source()); - remove_upload(evt.get_api_path(), true); + evt.api_path, function_name, evt.source_path); + remove_upload(evt.api_path, true); } else { event_system::instance().raise( - evt.get_api_path(), evt.get_source(), err); + evt.api_path, evt.error, function_name, evt.source_path); - queue_upload(evt.get_api_path(), evt.get_source(), true); - upload_notify_.wait_for(upload_lock, 5s); + queue_upload(evt.api_path, evt.source_path, true); + upload_notify_.wait_for(upload_lock, queue_wait_secs); } } } @@ -1026,10 +1073,10 @@ void file_manager::upload_completed(const file_upload_completed &evt) { void file_manager::upload_handler() { REPERTORY_USES_FUNCTION_NAME(); - while (not stop_requested_) { + while (not get_stop_requested()) { auto should_wait{true}; unique_mutex_lock upload_lock(upload_mtx_); - if (stop_requested_) { + if (get_stop_requested()) { upload_notify_.notify_all(); continue; } @@ -1044,7 +1091,7 @@ void file_manager::upload_handler() { case api_error::item_not_found: { should_wait = false; event_system::instance().raise( - entry->api_path, entry->source_path); + entry->api_path, function_name, entry->source_path); remove_upload(entry->api_path, true); } break; @@ -1068,7 +1115,7 @@ void file_manager::upload_handler() { default: { event_system::instance().raise( - entry->api_path, entry->source_path, res); + entry->api_path, res, function_name, entry->source_path); queue_upload(entry->api_path, entry->source_path, true); } break; } @@ -1079,7 +1126,7 @@ void file_manager::upload_handler() { } if (should_wait) { - upload_notify_.wait_for(upload_lock, 5s); + upload_notify_.wait_for(upload_lock, queue_wait_secs); } upload_notify_.notify_all(); diff --git a/repertory/librepertory/src/file_manager/open_file.cpp b/repertory/librepertory/src/file_manager/open_file.cpp index a6c836e2..a91e23d0 100644 --- a/repertory/librepertory/src/file_manager/open_file.cpp +++ b/repertory/librepertory/src/file_manager/open_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,8 +21,12 @@ */ #include "file_manager/open_file.hpp" +#include "app_config.hpp" +#include "events/event_system.hpp" +#include "events/types/download_begin.hpp" +#include "events/types/download_end.hpp" +#include "events/types/download_progress.hpp" #include "file_manager/cache_size_mgr.hpp" -#include "file_manager/events.hpp" #include "file_manager/file_manager.hpp" #include "file_manager/i_upload_manager.hpp" #include "platform/platform.hpp" @@ -270,6 +274,8 @@ auto open_file::close() -> bool { void open_file::download_chunk(std::size_t chunk, bool skip_active, bool should_reset) { + REPERTORY_USES_FUNCTION_NAME(); + if (should_reset) { reset_timeout(); } @@ -294,8 +300,8 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active, auto data_size = (chunk == read_state.size() - 1U) ? get_last_chunk_size() : get_chunk_size(); if (get_active_downloads().empty() && (read_state.count() == 0U)) { - event_system::instance().raise(get_api_path(), - get_source_path()); + event_system::instance().raise( + get_api_path(), get_source_path(), function_name); } get_active_downloads()[chunk] = std::make_shared(); @@ -318,16 +324,18 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active, static_cast(state.size())) * 100.0; event_system::instance().raise( - get_api_path(), get_source_path(), progress); + get_api_path(), get_source_path(), function_name, progress); if (state.all() && not notified_) { notified_ = true; event_system::instance().raise( - get_api_path(), get_source_path(), get_api_error()); + get_api_path(), get_source_path(), get_api_error(), + function_name); } } else if (not notified_) { notified_ = true; event_system::instance().raise( - get_api_path(), get_source_path(), get_api_error()); + get_api_path(), get_source_path(), get_api_error(), + function_name); } lock.unlock(); @@ -398,11 +406,15 @@ auto open_file::get_read_state(std::size_t chunk) const -> bool { return get_read_state()[chunk]; } +auto open_file::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + auto open_file::is_complete() const -> bool { return get_read_state().all(); } auto open_file::native_operation( i_open_file::native_operation_callback callback) -> api_error { - if (stop_requested_) { + if (get_stop_requested()) { return set_api_error(api_error::download_stopped); } @@ -424,7 +436,7 @@ auto open_file::native_operation( return set_api_error(api_error::invalid_operation); } - if (stop_requested_) { + if (get_stop_requested()) { return set_api_error(api_error::download_stopped); } @@ -535,7 +547,7 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset, return set_api_error(api_error::invalid_operation); } - if (stop_requested_) { + if (get_stop_requested()) { return set_api_error(api_error::download_stopped); } @@ -656,7 +668,7 @@ void open_file::update_reader(std::size_t chunk) { recur_mutex_lock rw_lock(rw_mtx_); read_chunk_ = chunk; - if (reader_thread_ || stop_requested_) { + if (reader_thread_ || get_stop_requested()) { return; } @@ -666,13 +678,13 @@ void open_file::update_reader(std::size_t chunk) { auto read_chunk{read_chunk_}; lock.unlock(); - while (not stop_requested_) { + while (not get_stop_requested()) { lock.lock(); auto read_state = get_read_state(); if ((get_file_size() == 0U) || read_state.all()) { lock.unlock(); - wait_for_io(stop_requested_); + wait_for_io([this]() -> bool { return this->get_stop_requested(); }); continue; } @@ -702,7 +714,7 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data, return api_error::success; } - if (stop_requested_) { + if (get_stop_requested()) { return set_api_error(api_error::download_stopped); } diff --git a/repertory/librepertory/src/file_manager/open_file_base.cpp b/repertory/librepertory/src/file_manager/open_file_base.cpp index 83a5a36a..48935496 100644 --- a/repertory/librepertory/src/file_manager/open_file_base.cpp +++ b/repertory/librepertory/src/file_manager/open_file_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,10 @@ #include "file_manager/open_file_base.hpp" #include "events/event_system.hpp" -#include "file_manager/events.hpp" +#include "events/types/filesystem_item_closed.hpp" +#include "events/types/filesystem_item_handle_closed.hpp" +#include "events/types/filesystem_item_handle_opened.hpp" +#include "events/types/filesystem_item_opened.hpp" #include "providers/i_provider.hpp" #include "utils/path.hpp" @@ -90,15 +93,17 @@ open_file_base::open_file_base( } void open_file_base::add(std::uint64_t handle, open_file_data ofd) { + REPERTORY_USES_FUNCTION_NAME(); + recur_mutex_lock file_lock(file_mtx_); open_data_[handle] = ofd; if (open_data_.size() == 1U) { event_system::instance().raise( - fsi_.api_path, fsi_.source_path, fsi_.directory); + fsi_.api_path, fsi_.directory, function_name, fsi_.source_path); } event_system::instance().raise( - fsi_.api_path, handle, fsi_.source_path, fsi_.directory); + fsi_.api_path, fsi_.directory, function_name, handle, fsi_.source_path); } auto open_file_base::can_close() const -> bool { @@ -309,6 +314,8 @@ void open_file_base::notify_io() { } void open_file_base::remove(std::uint64_t handle) { + REPERTORY_USES_FUNCTION_NAME(); + recur_mutex_lock file_lock(file_mtx_); if (open_data_.find(handle) == open_data_.end()) { return; @@ -316,16 +323,20 @@ void open_file_base::remove(std::uint64_t handle) { open_data_.erase(handle); event_system::instance().raise( - fsi_.api_path, handle, fsi_.source_path, fsi_.directory, modified_); + fsi_.api_path, modified_, fsi_.directory, function_name, handle, + fsi_.source_path); if (not open_data_.empty()) { return; } event_system::instance().raise( - fsi_.api_path, fsi_.source_path, fsi_.directory, modified_); + fsi_.api_path, modified_, fsi_.directory, function_name, + fsi_.source_path); } void open_file_base::remove_all() { + REPERTORY_USES_FUNCTION_NAME(); + recur_mutex_lock file_lock(file_mtx_); if (open_data_.empty()) { return; @@ -336,11 +347,13 @@ void open_file_base::remove_all() { for (const auto &data : open_data) { event_system::instance().raise( - fsi_.api_path, data.first, fsi_.source_path, fsi_.directory, modified_); + fsi_.api_path, modified_, fsi_.directory, function_name, data.first, + fsi_.source_path); } event_system::instance().raise( - fsi_.api_path, fsi_.source_path, fsi_.directory, modified_); + fsi_.api_path, modified_, fsi_.directory, function_name, + fsi_.source_path); } void open_file_base::reset_timeout() { @@ -366,9 +379,9 @@ void open_file_base::set_api_path(const std::string &api_path) { fsi_.api_parent = utils::path::get_parent_api_path(api_path); } -void open_file_base::wait_for_io(stop_type &stop_requested) { +void open_file_base::wait_for_io(stop_type_callback stop_requested_cb) { unique_mutex_lock io_lock(io_thread_mtx_); - if (not stop_requested && io_thread_queue_.empty()) { + if (not stop_requested_cb() && io_thread_queue_.empty()) { io_thread_notify_.wait(io_lock); } io_thread_notify_.notify_all(); diff --git a/repertory/librepertory/src/file_manager/ring_buffer_base.cpp b/repertory/librepertory/src/file_manager/ring_buffer_base.cpp index 7e2f7c33..e818ae76 100644 --- a/repertory/librepertory/src/file_manager/ring_buffer_base.cpp +++ b/repertory/librepertory/src/file_manager/ring_buffer_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,8 +21,11 @@ */ #include "file_manager/ring_buffer_base.hpp" +#include "app_config.hpp" #include "events/event_system.hpp" -#include "file_manager/events.hpp" +#include "events/types/download_begin.hpp" +#include "events/types/download_end.hpp" +#include "events/types/download_progress.hpp" #include "file_manager/open_file_base.hpp" #include "platform/platform.hpp" #include "providers/i_provider.hpp" @@ -65,8 +68,8 @@ auto ring_buffer_base::check_start() -> api_error { return api_error::success; } - event_system::instance().raise(get_api_path(), - get_source_path()); + event_system::instance().raise( + get_api_path(), get_source_path(), function_name); reader_thread_ = std::make_unique([this]() { reader_thread(); }); return api_error::success; @@ -97,6 +100,8 @@ auto ring_buffer_base::close() -> bool { auto ring_buffer_base::download_chunk(std::size_t chunk, bool skip_active) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + unique_mutex_lock chunk_lock(chunk_mtx_); const auto unlock_and_notify = [this, &chunk_lock]() { chunk_notify_.notify_all(); @@ -157,7 +162,7 @@ auto ring_buffer_base::download_chunk(std::size_t chunk, static_cast(total_chunks_)) * 100.0; event_system::instance().raise( - get_api_path(), get_source_path(), progress); + get_api_path(), get_source_path(), function_name, progress); } } @@ -183,6 +188,10 @@ auto ring_buffer_base::get_read_state(std::size_t chunk) const -> bool { return read_state_[chunk % read_state_.size()]; } +auto ring_buffer_base::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset, data_buffer &data) -> api_error { if (is_directory()) { @@ -207,7 +216,8 @@ auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset, } for (std::size_t chunk = begin_chunk; - not stop_requested_ && (res == api_error::success) && (read_size > 0U); + not get_stop_requested() && (res == api_error::success) && + (read_size > 0U); ++chunk) { reset_timeout(); @@ -247,21 +257,23 @@ auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset, read_offset = 0U; } - return stop_requested_ ? api_error::download_stopped : res; + return get_stop_requested() ? api_error::download_stopped : res; } void ring_buffer_base::reader_thread() { + REPERTORY_USES_FUNCTION_NAME(); + unique_mutex_lock chunk_lock(chunk_mtx_); auto next_chunk{ring_pos_}; chunk_notify_.notify_all(); chunk_lock.unlock(); - while (not stop_requested_) { + while (not get_stop_requested()) { chunk_lock.lock(); next_chunk = next_chunk + 1U > ring_end_ ? ring_begin_ : next_chunk + 1U; const auto check_and_wait = [this, &chunk_lock, &next_chunk]() { - if (stop_requested_) { + if (get_stop_requested()) { chunk_notify_.notify_all(); chunk_lock.unlock(); return; @@ -288,7 +300,8 @@ void ring_buffer_base::reader_thread() { } event_system::instance().raise( - get_api_path(), get_source_path(), api_error::download_stopped); + get_api_path(), get_source_path(), api_error::download_stopped, + function_name); } void ring_buffer_base::reverse(std::size_t count) { diff --git a/repertory/librepertory/src/file_manager/ring_buffer_open_file.cpp b/repertory/librepertory/src/file_manager/ring_buffer_open_file.cpp index 0316bfd0..e8b866f5 100644 --- a/repertory/librepertory/src/file_manager/ring_buffer_open_file.cpp +++ b/repertory/librepertory/src/file_manager/ring_buffer_open_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/file_manager/upload.cpp b/repertory/librepertory/src/file_manager/upload.cpp index 78a7e06c..77433627 100644 --- a/repertory/librepertory/src/file_manager/upload.cpp +++ b/repertory/librepertory/src/file_manager/upload.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ #include "file_manager/upload.hpp" #include "events/event_system.hpp" -#include "file_manager/events.hpp" +#include "events/types/file_upload_completed.hpp" #include "platform/platform.hpp" #include "providers/i_provider.hpp" #include "utils/error_utils.hpp" @@ -61,6 +61,7 @@ void upload::upload_thread() { } event_system::instance().raise( - get_api_path(), get_source_path(), get_api_error(), cancelled_); + get_api_path(), cancelled_, get_api_error(), function_name, + get_source_path()); } } // namespace repertory diff --git a/repertory/librepertory/src/initialize.cpp b/repertory/librepertory/src/initialize.cpp index daf0598e..ba021868 100644 --- a/repertory/librepertory/src/initialize.cpp +++ b/repertory/librepertory/src/initialize.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/platform/unix_platform.cpp b/repertory/librepertory/src/platform/unix_platform.cpp index 3bfc99cf..13ff360b 100644 --- a/repertory/librepertory/src/platform/unix_platform.cpp +++ b/repertory/librepertory/src/platform/unix_platform.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,13 +25,14 @@ #include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/filesystem_item_added.hpp" #include "providers/i_provider.hpp" #include "types/startup_exception.hpp" #include "utils/common.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" #include "utils/path.hpp" +#include "utils/string.hpp" #include "utils/unix.hpp" namespace repertory { @@ -150,16 +151,16 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location, (mount_state[mount_id]["Location"].get() != mount_location)))) { const auto lines = utils::file::read_file_lines(get_lock_data_file()); - const auto txt = - std::accumulate(lines.begin(), lines.end(), std::string(), - [](std::string s, const std::string &s2) { - return std::move(s) + s2; - }); - auto json = json::parse(txt.empty() ? "{}" : txt); - json[mount_id] = {{"Active", active}, - {"Location", active ? mount_location : ""}, - {"PID", active ? pid : -1}}; - ret = utils::file::write_json_file(get_lock_data_file(), json); + const auto txt = std::accumulate( + lines.begin(), lines.end(), std::string(), + [](auto &&val, auto &&line) -> auto { return val + line; }); + auto json_data = json::parse(txt.empty() ? "{}" : txt); + json_data[mount_id] = { + {"Active", active}, + {"Location", active ? mount_location : ""}, + {"PID", active ? pid : -1}, + }; + ret = utils::file::write_json_file(get_lock_data_file(), json_data); } else { ret = true; } @@ -225,6 +226,8 @@ auto create_meta_attributes( auto provider_meta_handler(i_provider &provider, bool directory, const api_file &file) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + const auto meta = create_meta_attributes( file.accessed_date, directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE, @@ -236,7 +239,7 @@ auto provider_meta_handler(i_provider &provider, bool directory, auto res = provider.set_item_meta(file.api_path, meta); if (res == api_error::success) { event_system::instance().raise( - file.api_path, file.api_parent, directory); + file.api_parent, file.api_path, directory, function_name); } return res; diff --git a/repertory/librepertory/src/platform/win32_platform.cpp b/repertory/librepertory/src/platform/win32_platform.cpp index 4a19a4d4..da155e3d 100644 --- a/repertory/librepertory/src/platform/win32_platform.cpp +++ b/repertory/librepertory/src/platform/win32_platform.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,13 +24,14 @@ #include "platform/win32_platform.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/filesystem_item_added.hpp" #include "providers/i_provider.hpp" #include "utils/error_utils.hpp" +#include "utils/string.hpp" namespace repertory { -auto lock_data::get_mount_state(const provider_type & /*pt*/, - json &mount_state) -> bool { +auto lock_data::get_mount_state(const provider_type & /*pt*/, json &mount_state) + -> bool { const auto ret = get_mount_state(mount_state); if (ret) { const auto mount_id = @@ -196,6 +197,8 @@ auto create_meta_attributes( auto provider_meta_handler(i_provider &provider, bool directory, const api_file &file) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + const auto meta = create_meta_attributes( file.accessed_date, directory ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_ARCHIVE, @@ -205,7 +208,7 @@ auto provider_meta_handler(i_provider &provider, bool directory, auto res = provider.set_item_meta(file.api_path, meta); if (res == api_error::success) { event_system::instance().raise( - file.api_path, file.api_parent, directory); + file.api_parent, file.api_path, directory, function_name); } return res; diff --git a/repertory/librepertory/src/providers/base_provider.cpp b/repertory/librepertory/src/providers/base_provider.cpp index 59816c51..4ca50567 100644 --- a/repertory/librepertory/src/providers/base_provider.cpp +++ b/repertory/librepertory/src/providers/base_provider.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,10 +24,24 @@ #include "app_config.hpp" #include "db/meta_db.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/directory_remove_failed.hpp" +#include "events/types/directory_removed.hpp" +#include "events/types/directory_removed_externally.hpp" +#include "events/types/file_remove_failed.hpp" +#include "events/types/file_removed.hpp" +#include "events/types/file_removed_externally.hpp" +#include "events/types/orphaned_file_detected.hpp" +#include "events/types/orphaned_file_processing_failed.hpp" +#include "events/types/orphaned_source_file_detected.hpp" +#include "events/types/orphaned_source_file_removed.hpp" +#include "events/types/provider_offline.hpp" +#include "events/types/provider_upload_begin.hpp" +#include "events/types/provider_upload_end.hpp" +#include "events/types/unmount_requested.hpp" #include "file_manager/cache_size_mgr.hpp" #include "file_manager/i_file_manager.hpp" #include "platform/platform.hpp" +#include "utils/config.hpp" #include "utils/error_utils.hpp" #include "utils/file_utils.hpp" #include "utils/path.hpp" @@ -36,13 +50,17 @@ #include "utils/time.hpp" namespace repertory { -void base_provider::add_all_items(const stop_type &stop_requested) { +void base_provider::add_all_items(stop_type &stop_requested) { + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + REPERTORY_USES_FUNCTION_NAME(); api_file_list list{}; std::string marker; auto res{api_error::more_data}; - while (not stop_requested && res == api_error::more_data) { + while (not get_stop_requested() && res == api_error::more_data) { res = get_file_list(list, marker); if (res != api_error::success && res != api_error::more_data) { utils::error::raise_error(function_name, res, "failed to get file list"); @@ -51,8 +69,8 @@ void base_provider::add_all_items(const stop_type &stop_requested) { } auto base_provider::create_api_file(std::string path, std::string key, - std::uint64_t size, std::uint64_t file_time) - -> api_file { + std::uint64_t size, + std::uint64_t file_time) -> api_file { api_file file{}; file.api_path = utils::path::create_api_path(path); file.api_parent = utils::path::get_parent_api_path(file.api_path); @@ -84,8 +102,8 @@ auto base_provider::create_api_file(std::string path, std::uint64_t size, } auto base_provider::create_directory_clone_source_meta( - const std::string &source_api_path, const std::string &api_path) - -> api_error { + const std::string &source_api_path, + const std::string &api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); bool exists{}; @@ -140,76 +158,77 @@ auto base_provider::create_directory(const std::string &api_path, api_meta_map &meta) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - bool exists{}; - auto res = is_directory(api_path, exists); - if (res != api_error::success) { - return res; - } - if (exists) { - utils::error::raise_api_path_error(function_name, api_path, - api_error::directory_exists, - "failed to create directory"); - return api_error::directory_exists; - } - - res = is_file(api_path, exists); - if (res != api_error::success) { - utils::error::raise_api_path_error(function_name, api_path, res, - "failed to create directory"); - return res; - } - if (exists) { - utils::error::raise_api_path_error(function_name, api_path, - api_error::item_exists, - "failed to create directory"); - return api_error::item_exists; - } - try { + bool exists{}; + auto res = is_directory(api_path, exists); + if (res != api_error::success) { + return res; + } + if (exists) { + utils::error::raise_api_path_error(function_name, api_path, + api_error::directory_exists, + "failed to create directory"); + return api_error::directory_exists; + } + + res = is_file(api_path, exists); + if (res != api_error::success) { + utils::error::raise_api_path_error(function_name, api_path, res, + "failed to create directory"); + return res; + } + if (exists) { + utils::error::raise_api_path_error(function_name, api_path, + api_error::item_exists, + "failed to create directory"); + return api_error::item_exists; + } + res = create_directory_impl(api_path, meta); if (res != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, res, "failed to create directory"); return res; } + + meta[META_DIRECTORY] = utils::string::from_bool(true); + return set_item_meta(api_path, meta); } catch (const std::exception &e) { utils::error::raise_api_path_error(function_name, api_path, e, "failed to create directory"); - return api_error::error; } - meta[META_DIRECTORY] = utils::string::from_bool(true); - return set_item_meta(api_path, meta); + return api_error::error; } -auto base_provider::create_file(const std::string &api_path, api_meta_map &meta) - -> api_error { +auto base_provider::create_file(const std::string &api_path, + api_meta_map &meta) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - bool exists{}; - auto res = is_directory(api_path, exists); - if (res != api_error::success && res != api_error::item_not_found) { - return res; - } - if (exists) { - utils::error::raise_api_path_error(function_name, api_path, - api_error::directory_exists, - "failed to create file"); - return api_error::directory_exists; - } - - res = is_file(api_path, exists); - if (res != api_error::success && res != api_error::item_not_found) { - return res; - } - if (exists) { - utils::error::raise_api_path_error(function_name, api_path, - api_error::item_exists, - "failed to create file"); - return api_error::item_exists; - } - try { + bool exists{}; + auto res = is_directory(api_path, exists); + if (res != api_error::success && res != api_error::item_not_found) { + return res; + } + if (exists) { + utils::error::raise_api_path_error(function_name, api_path, + api_error::directory_exists, + "failed to create file"); + return api_error::directory_exists; + } + + res = is_file(api_path, exists); + if (res != api_error::success && res != api_error::item_not_found) { + return res; + } + if (exists) { + utils::error::raise_api_path_error(function_name, api_path, + api_error::item_exists, + "failed to create file"); + return api_error::item_exists; + } + res = create_file_extra(api_path, meta); if (res != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, res, @@ -240,9 +259,8 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta) return api_error::error; } -auto base_provider::get_api_path_from_source(const std::string &source_path, - std::string &api_path) const - -> api_error { +auto base_provider::get_api_path_from_source( + const std::string &source_path, std::string &api_path) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); if (source_path.empty()) { @@ -255,21 +273,20 @@ auto base_provider::get_api_path_from_source(const std::string &source_path, return db3_->get_api_path(source_path, api_path); } -auto base_provider::get_directory_items(const std::string &api_path, - directory_item_list &list) const - -> api_error { +auto base_provider::get_directory_items( + const std::string &api_path, directory_item_list &list) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - bool exists{}; - auto res = is_directory(api_path, exists); - if (res != api_error::success) { - return res; - } - if (not exists) { - return api_error::directory_not_found; - } - try { + bool exists{}; + auto res = is_directory(api_path, exists); + if (res != api_error::success) { + return res; + } + if (not exists) { + return api_error::directory_not_found; + } + res = get_directory_items_impl(api_path, list); if (res != api_error::success) { return res; @@ -291,11 +308,15 @@ auto base_provider::get_directory_items(const std::string &api_path, "..", "", true, + 0U, + {}, }); list.insert(list.begin(), directory_item{ ".", "", true, + 0U, + {}, }); return api_error::success; } @@ -321,10 +342,9 @@ auto base_provider::get_file_size(const std::string &api_path, return api_error::success; } -auto base_provider::get_filesystem_item(const std::string &api_path, - bool directory, - filesystem_item &fsi) const - -> api_error { +auto base_provider::get_filesystem_item( + const std::string &api_path, bool directory, + filesystem_item &fsi) const -> api_error { bool exists{}; auto res = is_directory(api_path, exists); if (res != api_error::success) { @@ -357,10 +377,9 @@ auto base_provider::get_filesystem_item(const std::string &api_path, return api_error::success; } -auto base_provider::get_filesystem_item_and_file(const std::string &api_path, - api_file &file, - filesystem_item &fsi) const - -> api_error { +auto base_provider::get_filesystem_item_and_file( + const std::string &api_path, api_file &file, + filesystem_item &fsi) const -> api_error { auto res = get_file(api_path, file); if (res != api_error::success) { return res; @@ -436,9 +455,15 @@ auto base_provider::is_file_writeable(const std::string &api_path) const } void base_provider::process_removed_directories( - std::deque removed_list, const stop_type &stop_requested) { + std::deque removed_list, stop_type &stop_requested) { + REPERTORY_USES_FUNCTION_NAME(); + + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + for (const auto &item : removed_list) { - if (stop_requested) { + if (get_stop_requested()) { return; } @@ -448,18 +473,23 @@ void base_provider::process_removed_directories( db3_->remove_api_path(item.api_path); event_system::instance().raise( - item.api_path, item.source_path); + item.api_path, function_name, item.source_path); } } void base_provider::process_removed_files(std::deque removed_list, - const stop_type &stop_requested) { + stop_type &stop_requested) { REPERTORY_USES_FUNCTION_NAME(); - auto orphaned_directory = - utils::path::combine(get_config().get_data_directory(), {"orphaned"}); + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + + auto orphaned_directory{ + utils::path::combine(get_config().get_data_directory(), {"orphaned"}), + }; for (const auto &item : removed_list) { - if (stop_requested) { + if (get_stop_requested()) { return; } @@ -468,6 +498,9 @@ void base_provider::process_removed_files(std::deque removed_list, } if (not utils::file::file{item.source_path}.exists()) { + db3_->remove_api_path(item.api_path); + event_system::instance().raise( + item.api_path, function_name, item.source_path); continue; } @@ -483,100 +516,118 @@ void base_provider::process_removed_files(std::deque removed_list, orphaned_directory, {utils::path::strip_to_file_name(item.source_path) + '_' + parts[parts.size() - 1U]}); - event_system::instance().raise(item.source_path); + event_system::instance().raise(function_name, + item.source_path); if (not utils::file::reset_modified_time(item.source_path)) { event_system::instance().raise( - item.source_path, orphaned_file, + orphaned_file, "reset modified failed|" + - std::to_string(utils::get_last_error_code())); + std::to_string(utils::get_last_error_code()), + function_name, item.source_path); continue; } if (not utils::file::file(item.source_path).copy_to(orphaned_file, true)) { [[maybe_unused]] auto removed = utils::file::file{orphaned_file}.remove(); event_system::instance().raise( - item.source_path, orphaned_file, - "copy failed|" + std::to_string(utils::get_last_error_code())); + orphaned_file, + "copy failed|" + std::to_string(utils::get_last_error_code()), + function_name, item.source_path); continue; } if (not fm_->evict_file(item.api_path)) { event_system::instance().raise( - item.source_path, orphaned_file, "eviction failed"); + orphaned_file, "eviction failed", function_name, item.source_path); continue; } db3_->remove_api_path(item.api_path); - event_system::instance().raise(item.api_path, - item.source_path); + event_system::instance().raise( + item.api_path, function_name, item.source_path); } } -void base_provider::process_removed_items(const stop_type &stop_requested) { - auto list = db3_->get_api_path_list(); - [[maybe_unused]] auto res = - std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool { - if (stop_requested) { - return false; - } +void base_provider::process_removed_items(stop_type &stop_requested) { + REPERTORY_USES_FUNCTION_NAME(); - tasks::instance().schedule({ - [this, api_path](auto &&task_stopped) { - api_meta_map meta{}; - if (get_item_meta(api_path, meta) != api_error::success) { - return; + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + + db3_->enumerate_api_path_list( + [this, &get_stop_requested](auto &&list) { + [[maybe_unused]] auto res = + std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool { + if (get_stop_requested()) { + return false; } - if (utils::string::to_bool(meta[META_DIRECTORY])) { - return; - } - // bool exists{}; - // if (is_directory(api_path, exists) != api_error::success) { - // return; - // } - // - // if (exists) { - // return; - // } - // - // // process_removed_directories( - // // { - // // removed_item{api_path, true, ""}, - // // }, - // // stop_requested2); - // - // return; - // } + tasks::instance().schedule({ + [this, api_path](auto &&task_stopped) { + api_meta_map meta{}; + auto result = get_item_meta(api_path, meta); + if (result != api_error::success) { + return; + } - bool exists{}; - if (is_file(api_path, exists) != api_error::success) { - return; - } + if (utils::string::to_bool(meta[META_DIRECTORY])) { + bool exists{}; + if (is_directory(api_path, exists) != + api_error::success) { + return; + } - if (exists) { - return; - } + if (exists) { + return; + } - process_removed_files( - { - removed_item{api_path, false, meta[META_SOURCE]}, + process_removed_directories( + { + removed_item{api_path, true, ""}, + }, + task_stopped); + + return; + } + + bool exists{}; + if (is_file(api_path, exists) != api_error::success) { + return; + } + + if (exists) { + return; + } + + process_removed_files( + { + removed_item{api_path, false, meta[META_SOURCE]}, + }, + task_stopped); }, - task_stopped); - }, - }); + }); - return not stop_requested; - }); + return not get_stop_requested(); + }); + }, + get_stop_requested); } -void base_provider::remove_deleted_items(const stop_type &stop_requested) { +void base_provider::remove_deleted_items(stop_type &stop_requested) { + REPERTORY_USES_FUNCTION_NAME(); + + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + add_all_items(stop_requested); - if (stop_requested) { + if (get_stop_requested()) { return; } remove_unmatched_source_files(stop_requested); - if (stop_requested) { + if (get_stop_requested()) { return; } @@ -584,12 +635,14 @@ void base_provider::remove_deleted_items(const stop_type &stop_requested) { } auto base_provider::remove_file(const std::string &api_path) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + const auto notify_end = [&api_path](api_error error) -> api_error { if (error == api_error::success) { - event_system::instance().raise(api_path); + event_system::instance().raise(api_path, function_name); } else { - event_system::instance().raise( - api_path, api_error_to_string(error)); + event_system::instance().raise(api_path, error, + function_name); } return error; @@ -618,7 +671,7 @@ auto base_provider::remove_file(const std::string &api_path) -> api_error { } if (not exists) { event_system::instance().raise( - api_path, api_error_to_string(api_error::item_not_found)); + api_path, api_error::item_not_found, function_name); return remove_file_meta(); } @@ -631,12 +684,15 @@ auto base_provider::remove_file(const std::string &api_path) -> api_error { } auto base_provider::remove_directory(const std::string &api_path) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + const auto notify_end = [&api_path](api_error error) -> api_error { if (error == api_error::success) { - event_system::instance().raise(api_path); + event_system::instance().raise(api_path, + function_name); } else { - event_system::instance().raise( - api_path, api_error_to_string(error)); + event_system::instance().raise(api_path, error, + function_name); } return error; }; @@ -665,18 +721,23 @@ auto base_provider::remove_item_meta(const std::string &api_path, return db3_->remove_item_meta(api_path, key); } -void base_provider::remove_unmatched_source_files( - const stop_type &stop_requested) { +void base_provider::remove_unmatched_source_files(stop_type &stop_requested) { + REPERTORY_USES_FUNCTION_NAME(); + if (is_read_only()) { return; } + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; + const auto &cfg = get_config(); auto source_list = utils::file::directory{cfg.get_cache_directory()}.get_files(); for (const auto &source_file : source_list) { - if (stop_requested) { + if (get_stop_requested()) { return; } @@ -702,13 +763,13 @@ void base_provider::remove_unmatched_source_files( } event_system::instance().raise( - source_file->get_path()); + function_name, source_file->get_path()); if (not source_file->remove()) { continue; } event_system::instance().raise( - source_file->get_path()); + function_name, source_file->get_path()); } } @@ -725,6 +786,8 @@ auto base_provider::set_item_meta(const std::string &api_path, auto base_provider::start(api_item_added_callback api_item_added, i_file_manager *mgr) -> bool { + REPERTORY_USES_FUNCTION_NAME(); + api_item_added_ = api_item_added; fm_ = mgr; @@ -736,28 +799,33 @@ auto base_provider::start(api_item_added_callback api_item_added, api_item_added_(true, dir); } - auto online{false}; - auto unmount_requested{false}; - { - const auto &cfg = get_config(); + auto stop_requested{false}; + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; - repertory::event_consumer consumer( - "unmount_requested", - [&unmount_requested](const event &) { unmount_requested = true; }); - for (std::uint16_t idx = 0U; not online && not unmount_requested && - (idx < cfg.get_online_check_retry_secs()); - ++idx) { - online = is_online(); - if (not online) { - event_system::instance().raise( - cfg.get_host_config().host_name_or_ip, - cfg.get_host_config().api_port); - std::this_thread::sleep_for(1s); - } + const auto &cfg = get_config(); + + repertory::event_consumer consumer( + unmount_requested::name, + [&stop_requested](const i_event & /* evt */) { stop_requested = true; }); + + auto online{false}; + for (std::uint16_t idx = 0U; not online && not get_stop_requested() && + (idx < cfg.get_online_check_retry_secs()); + ++idx) { + online = is_online(); + if (online) { + continue; } + + event_system::instance().raise( + function_name, cfg.get_host_config().host_name_or_ip, + cfg.get_host_config().api_port); + std::this_thread::sleep_for(1s); } - if (not online || unmount_requested) { + if (not online || get_stop_requested()) { return false; } @@ -766,7 +834,7 @@ auto base_provider::start(api_item_added_callback api_item_added, polling::instance().set_callback({ "check_deleted", polling::frequency::low, - [this](auto &&stop_requested) { remove_deleted_items(stop_requested); }, + [this](auto &&stop) { remove_deleted_items(stop); }, }); return true; @@ -783,16 +851,17 @@ auto base_provider::upload_file(const std::string &api_path, stop_type &stop_requested) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - event_system::instance().raise(api_path, source_path); - const auto notify_end = [&api_path, &source_path](api_error error) -> api_error { - event_system::instance().raise(api_path, source_path, - error); + event_system::instance().raise( + api_path, error, function_name, source_path); return error; }; try { + event_system::instance().raise( + api_path, function_name, source_path); + return notify_end(upload_file_impl(api_path, source_path, stop_requested)); } catch (const std::exception &e) { utils::error::raise_error(function_name, e, "exception occurred"); diff --git a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp index c3a1a1a7..a33b9c3e 100644 --- a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp +++ b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,17 @@ #include "db/file_db.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/directory_removed_externally.hpp" +#include "events/types/file_removed_externally.hpp" +#include "events/types/filesystem_item_added.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "types/repertory.hpp" #include "types/startup_exception.hpp" #include "utils/collection.hpp" +#include "utils/config.hpp" #include "utils/encrypting_reader.hpp" #include "utils/encryption.hpp" #include "utils/error_utils.hpp" @@ -38,10 +45,11 @@ namespace repertory { encrypt_provider::encrypt_provider(app_config &config) : config_(config), encrypt_config_(config.get_encrypt_config()) {} -auto encrypt_provider::create_api_file( - const std::string &api_path, bool directory, - const std::string &source_path) -> api_file { - auto times = utils::file::get_times(source_path); +auto encrypt_provider::create_api_file(const std::string &api_path, + bool directory, + const std::string &source_path) + -> api_file { + auto times{utils::file::get_times(source_path)}; if (not times.has_value()) { throw std::runtime_error("failed to get file times"); } @@ -66,10 +74,10 @@ auto encrypt_provider::create_api_file( void encrypt_provider::create_item_meta(api_meta_map &meta, bool directory, const api_file &file) { #if defined(_WIN32) - struct _stat64 buf {}; + struct _stat64 buf{}; _stat64(file.source_path.c_str(), &buf); #else // !defined(_WIN32) - struct stat buf {}; + struct stat buf{}; stat(file.source_path.c_str(), &buf); #endif // defined(_WIN32) @@ -112,7 +120,7 @@ auto encrypt_provider::do_fs_operation( std::function callback) const -> api_error { - const auto &cfg = get_encrypt_config(); + const auto &cfg{get_encrypt_config()}; std::string source_path{api_path}; if (api_path != "/" && not utils::encryption::decrypt_file_path( @@ -129,7 +137,7 @@ auto encrypt_provider::do_fs_operation( : api_error::item_not_found; } - auto exists = utils::file::file{source_path}.exists(); + auto exists{utils::file::file{source_path}.exists()}; if (exists && directory) { return api_error::item_exists; } @@ -149,8 +157,9 @@ auto encrypt_provider::do_fs_operation( return callback(cfg, source_path); } -auto encrypt_provider::get_api_path_from_source( - const std::string &source_path, std::string &api_path) const -> api_error { +auto encrypt_provider::get_api_path_from_source(const std::string &source_path, + std::string &api_path) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); try { @@ -168,19 +177,20 @@ auto encrypt_provider::get_directory_item_count( REPERTORY_USES_FUNCTION_NAME(); std::uint64_t count{}; - auto res = do_fs_operation( - api_path, true, - [&api_path, &count](const encrypt_config & /* cfg */, - const std::string &source_path) -> api_error { - try { - count = utils::file::directory{source_path}.count(); - } catch (const std::exception &ex) { - utils::error::raise_api_path_error( - function_name, api_path, source_path, ex, - "failed to get directory item count"); - } - return api_error::success; - }); + auto res{ + do_fs_operation(api_path, true, + [&api_path, &count](auto && /* cfg */, + auto &&source_path) -> api_error { + try { + count = utils::file::directory{source_path}.count(); + } catch (const std::exception &ex) { + utils::error::raise_api_path_error( + function_name, api_path, source_path, ex, + "failed to get directory item count"); + } + return api_error::success; + }), + }; if (res != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, res, "failed to get directory item count"); @@ -189,22 +199,24 @@ auto encrypt_provider::get_directory_item_count( return count; } -auto encrypt_provider::get_directory_items( - const std::string &api_path, directory_item_list &list) const -> api_error { +auto encrypt_provider::get_directory_items(const std::string &api_path, + directory_item_list &list) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); return do_fs_operation( api_path, true, - [this, &list](const encrypt_config &cfg, - const std::string &source_path) -> api_error { + [this, &list](auto &&cfg, auto &&source_path) -> api_error { try { for (const auto &dir_entry : utils::file::directory{source_path}.get_items()) { try { std::string current_api_path; if (dir_entry->is_directory_item()) { - auto result = db_->get_directory_api_path(dir_entry->get_path(), - current_api_path); + auto result{ + db_->get_directory_api_path(dir_entry->get_path(), + current_api_path), + }; if (result != api_error::success && result != api_error::directory_not_found) { // TODO raise error @@ -224,8 +236,10 @@ auto encrypt_provider::get_directory_items( } } } else { - auto result = db_->get_file_api_path(dir_entry->get_path(), - current_api_path); + auto result{ + db_->get_file_api_path(dir_entry->get_path(), + current_api_path), + }; if (result != api_error::success && result != api_error::item_not_found) { // TODO raise error @@ -238,9 +252,11 @@ auto encrypt_provider::get_directory_items( } } - auto file = create_api_file(current_api_path, - dir_entry->is_directory_item(), - dir_entry->get_path()); + auto file{ + create_api_file(current_api_path, + dir_entry->is_directory_item(), + dir_entry->get_path()), + }; directory_item dir_item{}; dir_item.api_parent = file.api_parent; @@ -294,7 +310,7 @@ auto encrypt_provider::get_file(const std::string &api_path, try { bool exists{}; - auto res = is_directory(api_path, exists); + auto res{is_directory(api_path, exists)}; if (res != api_error::success) { return res; } @@ -303,7 +319,7 @@ auto encrypt_provider::get_file(const std::string &api_path, } std::string source_path; - auto result = db_->get_file_source_path(api_path, source_path); + auto result{db_->get_file_source_path(api_path, source_path)}; if (result != api_error::success) { return result; } @@ -318,11 +334,12 @@ auto encrypt_provider::get_file(const std::string &api_path, return api_error::error; } -auto encrypt_provider::get_file_list( - api_file_list &list, std::string & /* marker */) const -> api_error { +auto encrypt_provider::get_file_list(api_file_list &list, + std::string & /* marker */) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_encrypt_config(); + const auto &cfg{get_encrypt_config()}; try { for (const auto &dir_entry : utils::file::directory{cfg.path}.get_items()) { @@ -342,13 +359,14 @@ auto encrypt_provider::get_file_list( return api_error::error; } -auto encrypt_provider::get_file_size( - const std::string &api_path, std::uint64_t &file_size) const -> api_error { +auto encrypt_provider::get_file_size(const std::string &api_path, + std::uint64_t &file_size) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); try { std::string source_path; - auto result = db_->get_file_source_path(api_path, source_path); + auto result{db_->get_file_source_path(api_path, source_path)}; if (result != api_error::success) { return result; } @@ -364,12 +382,13 @@ auto encrypt_provider::get_file_size( return api_error::error; } -auto encrypt_provider::get_filesystem_item( - const std::string &api_path, bool directory, - filesystem_item &fsi) const -> api_error { +auto encrypt_provider::get_filesystem_item(const std::string &api_path, + bool directory, + filesystem_item &fsi) const + -> api_error { std::string source_path; if (directory) { - auto result = db_->get_directory_source_path(api_path, source_path); + auto result{db_->get_directory_source_path(api_path, source_path)}; if (result != api_error::success) { return result; } @@ -382,7 +401,7 @@ auto encrypt_provider::get_filesystem_item( return api_error::success; } - auto result = db_->get_file_source_path(api_path, source_path); + auto result{db_->get_file_source_path(api_path, source_path)}; if (result != api_error::success) { return result; } @@ -400,7 +419,7 @@ auto encrypt_provider::get_filesystem_item( auto encrypt_provider::get_filesystem_item_from_source_path( const std::string &source_path, filesystem_item &fsi) const -> api_error { std::string api_path{}; - auto res = get_api_path_from_source(source_path, api_path); + auto res{get_api_path_from_source(source_path, api_path)}; if (res != api_error::success) { return res; } @@ -417,14 +436,15 @@ auto encrypt_provider::get_filesystem_item_from_source_path( return get_filesystem_item(api_path, false, fsi); } -auto encrypt_provider::get_filesystem_item_and_file( - const std::string &api_path, api_file &file, - filesystem_item &fsi) const -> api_error { +auto encrypt_provider::get_filesystem_item_and_file(const std::string &api_path, + api_file &file, + filesystem_item &fsi) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); try { bool exists{}; - auto res = is_directory(api_path, exists); + auto res{is_directory(api_path, exists)}; if (res != api_error::success) { return res; } @@ -432,7 +452,7 @@ auto encrypt_provider::get_filesystem_item_and_file( return api_error::directory_exists; } - auto ret = get_filesystem_item(api_path, exists, fsi); + auto ret{get_filesystem_item(api_path, exists, fsi)}; if (ret != api_error::success) { return ret; } @@ -457,7 +477,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path, try { std::string source_path; - auto result = db_->get_source_path(api_path, source_path); + auto result{db_->get_source_path(api_path, source_path)}; if (result != api_error::success) { return result; } @@ -468,7 +488,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path, return result; } - auto file = create_api_file(api_path, is_dir, source_path); + auto file{create_api_file(api_path, is_dir, source_path)}; create_item_meta(meta, is_dir, file); return api_error::success; } catch (const std::exception &ex) { @@ -483,7 +503,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path, const std::string &key, std::string &value) const -> api_error { api_meta_map meta{}; - auto ret = get_item_meta(api_path, meta); + auto ret{get_item_meta(api_path, meta)}; if (ret != api_error::success) { return ret; } @@ -511,8 +531,9 @@ auto encrypt_provider::get_total_item_count() const -> std::uint64_t { } auto encrypt_provider::get_used_drive_space() const -> std::uint64_t { - auto free_space = - utils::file::get_free_drive_space(get_encrypt_config().path); + auto free_space{ + utils::file::get_free_drive_space(get_encrypt_config().path), + }; return free_space.has_value() ? get_total_drive_space() - free_space.value() : 0U; } @@ -523,7 +544,7 @@ auto encrypt_provider::is_directory(const std::string &api_path, try { std::string source_path; - auto result = db_->get_directory_source_path(api_path, source_path); + auto result{db_->get_directory_source_path(api_path, source_path)}; if (result != api_error::success) { if (result != api_error::directory_not_found) { @@ -544,13 +565,13 @@ auto encrypt_provider::is_directory(const std::string &api_path, return api_error::error; } -auto encrypt_provider::is_file(const std::string &api_path, - bool &exists) const -> api_error { +auto encrypt_provider::is_file(const std::string &api_path, bool &exists) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); try { std::string source_path; - auto result = db_->get_file_source_path(api_path, source_path); + auto result{db_->get_file_source_path(api_path, source_path)}; if (result != api_error::success) { if (result != api_error::item_not_found) { return result; @@ -587,8 +608,10 @@ auto encrypt_provider::process_directory_entry( try { const auto do_add_directory = [this, &cfg](std::string_view dir_path) -> std::string { - auto encrypted_parts = utils::string::split( - utils::path::create_api_path(dir_path), '/', false); + auto encrypted_parts{ + utils::string::split(utils::path::create_api_path(dir_path), '/', + false), + }; for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size(); ++part_idx) { @@ -611,8 +634,9 @@ auto encrypt_provider::process_directory_entry( current_source_path = utils::path::combine(current_source_path, {part}); std::string current_api_path{}; - auto result = - db_->get_directory_api_path(current_source_path, current_api_path); + auto result{ + db_->get_directory_api_path(current_source_path, current_api_path), + }; if (result == api_error::directory_not_found) { current_api_path = utils::path::create_api_path( current_encrypted_path + '/' + encrypted_parts.at(current_idx)); @@ -625,8 +649,8 @@ auto encrypt_provider::process_directory_entry( } event_system::instance().raise( - current_api_path, - utils::path::get_parent_api_path(current_api_path), true); + utils::path::get_parent_api_path(current_api_path), + current_api_path, true, function_name); } else { if (result != api_error::success) { std::runtime_error( @@ -652,11 +676,12 @@ auto encrypt_provider::process_directory_entry( } if (dir_entry.is_file_item() && not dir_entry.is_symlink()) { - auto relative_path = - utils::path::get_relative_path(dir_entry.get_path(), cfg.path); + auto relative_path{ + utils::path::get_relative_path(dir_entry.get_path(), cfg.path), + }; i_file_db::file_data data; - auto file_res = db_->get_file_data(dir_entry.get_path(), data); + auto file_res{db_->get_file_data(dir_entry.get_path(), data)}; if (file_res != api_error::success && file_res != api_error::item_not_found) { // TODO raise error @@ -664,8 +689,10 @@ auto encrypt_provider::process_directory_entry( } std::string api_parent{}; - auto parent_res = db_->get_directory_api_path( - utils::path::get_parent_path(dir_entry.get_path()), api_parent); + auto parent_res{ + db_->get_directory_api_path( + utils::path::get_parent_path(dir_entry.get_path()), api_parent), + }; if (parent_res != api_error::success && parent_res != api_error::directory_not_found) { // TODO raise error @@ -678,11 +705,11 @@ auto encrypt_provider::process_directory_entry( } if (file_res == api_error::item_not_found) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( utils::path::strip_to_file_name(relative_path), - dir_entry.get_path(), stop_requested, cfg.encryption_token, - utils::path::get_parent_path(relative_path)); + dir_entry.get_path(), + []() -> bool { return app_config::get_stop_requested(); }, + cfg.encryption_token, utils::path::get_parent_path(relative_path)); api_path = utils::path::create_api_path( api_parent + "/" + reader.get_encrypted_file_name()); @@ -700,7 +727,7 @@ auto encrypt_provider::process_directory_entry( } event_system::instance().raise( - api_path, api_parent, false); + api_parent, api_path, false, function_name); } return true; @@ -720,29 +747,33 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path, REPERTORY_USES_FUNCTION_NAME(); i_file_db::file_data file_data{}; - auto result = db_->get_file_data(api_path, file_data); + auto result{db_->get_file_data(api_path, file_data)}; if (result != api_error::success) { return result; } - auto opt_size = utils::file::file{file_data.source_path}.size(); + auto opt_size{utils::file::file{file_data.source_path}.size()}; if (not opt_size.has_value()) { return api_error::os_error; } auto file_size{opt_size.value()}; - const auto &cfg = get_encrypt_config(); + const auto &cfg{get_encrypt_config()}; unique_recur_mutex_lock reader_lookup_lock(reader_lookup_mtx_); if (file_data.file_size != file_size) { - auto relative_path = - utils::path::get_relative_path(file_data.source_path, cfg.path); + auto relative_path{ + utils::path::get_relative_path(file_data.source_path, cfg.path), + }; - auto info = std::make_shared(); + auto info{std::make_shared()}; info->reader = std::make_unique( - relative_path, file_data.source_path, stop_requested, + relative_path, file_data.source_path, + [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }, cfg.encryption_token, utils::path::get_parent_path(relative_path)); reader_lookup_[file_data.source_path] = info; file_data.file_size = file_size; @@ -758,10 +789,13 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path, } } else if (reader_lookup_.find(file_data.source_path) == reader_lookup_.end()) { - auto info = std::make_shared(); + auto info{std::make_shared()}; info->reader = std::make_unique( - api_path, file_data.source_path, stop_requested, cfg.encryption_token, - std::move(file_data.iv_list)); + api_path, file_data.source_path, + [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }, + cfg.encryption_token, std::move(file_data.iv_list)); reader_lookup_[file_data.source_path] = info; } @@ -769,7 +803,7 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path, return api_error::success; } - auto info = reader_lookup_.at(file_data.source_path); + auto info{reader_lookup_.at(file_data.source_path)}; info->last_access_time = std::chrono::system_clock::now(); reader_lookup_lock.unlock(); @@ -777,45 +811,60 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path, info->reader->set_read_position(offset); data.resize(size); - auto res = + auto res{ info->reader->reader_function(reinterpret_cast(data.data()), 1U, - data.size(), info->reader.get()); - if (res == 0) { - return api_error::os_error; - } - - return api_error::success; + data.size(), info->reader.get()), + }; + return res == 0 ? api_error::os_error : api_error::success; } -void encrypt_provider::remove_deleted_files(const stop_type &stop_requested) { - std::vector removed_list{}; +void encrypt_provider::remove_deleted_files(stop_type &stop_requested) { + REPERTORY_USES_FUNCTION_NAME(); - for (const auto &item : db_->get_item_list()) { - if (stop_requested) { - return; - } + const auto get_stop_requested = [&stop_requested]() -> bool { + return stop_requested || app_config::get_stop_requested(); + }; - if (not utils::path::exists(item.source_path)) { - removed_list.emplace_back(item); - } - } + db_->enumerate_item_list( + [this, &get_stop_requested](auto &&list) { + std::vector removed_list{}; + for (const auto &item : list) { + if (get_stop_requested()) { + return; + } - for (const auto &item : removed_list) { - if (stop_requested) { - return; - } + if (utils::path::exists(item.source_path)) { + continue; + } - // TODO handle error - auto del_res = db_->remove_item(item.api_path); - if (item.directory) { - event_system::instance().raise( - item.api_path, item.source_path); - continue; - } + removed_list.emplace_back(item); + } - event_system::instance().raise(item.api_path, - item.source_path); - } + for (const auto &item : removed_list) { + if (get_stop_requested()) { + return; + } + + auto res{db_->remove_item(item.api_path)}; + if (res != api_error::success) { + utils::error::raise_api_path_error( + function_name, item.api_path, item.source_path, res, + fmt::format("failed to process externally removed item|dir|{}", + utils::string::from_bool(item.directory))); + continue; + } + + if (item.directory) { + event_system::instance().raise( + item.api_path, function_name, item.source_path); + continue; + } + + event_system::instance().raise( + item.api_path, function_name, item.source_path); + } + }, + get_stop_requested); } auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, @@ -826,23 +875,25 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, return false; } + event_system::instance().raise(function_name, + "encrypt_provider"); db_ = create_file_db(config_); std::string source_path; - auto result = db_->get_directory_source_path("/", source_path); + auto result{db_->get_directory_source_path("/", source_path)}; if (result != api_error::success && result != api_error::directory_not_found) { throw startup_exception( fmt::format("failed to get root|{}", api_error_to_string(result))); } - auto cfg_path = utils::path::absolute(get_encrypt_config().path); + auto cfg_path{utils::path::absolute(get_encrypt_config().path)}; if (result == api_error::success) { - auto cur_path = utils::path::absolute(source_path); + auto cur_path{utils::path::absolute(source_path)}; #if defined(_WIN32) if (utils::string::to_lower(cur_path) != utils::string::to_lower(cfg_path)) { -#else //! defined(_WIN32) +#else // !defined(_WIN32) if (cur_path != cfg_path) { #endif // defined(_WIN32) throw startup_exception(fmt::format( @@ -862,14 +913,19 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, [this](auto &&stop_requested) { remove_deleted_files(stop_requested); }, }); - event_system::instance().raise("encrypt_provider"); + event_system::instance().raise(function_name, + "encrypt_provider"); return true; } void encrypt_provider::stop() { - event_system::instance().raise("encrypt_provider"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "encrypt_provider"); polling::instance().remove_callback("check_deleted"); db_.reset(); - event_system::instance().raise("encrypt_provider"); + event_system::instance().raise(function_name, + "encrypt_provider"); } } // namespace repertory diff --git a/repertory/librepertory/src/providers/provider.cpp b/repertory/librepertory/src/providers/provider.cpp index e9107537..b57c5a2f 100644 --- a/repertory/librepertory/src/providers/provider.cpp +++ b/repertory/librepertory/src/providers/provider.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/providers/s3/s3_provider.cpp b/repertory/librepertory/src/providers/s3/s3_provider.cpp index 780041c0..2b23fa90 100644 --- a/repertory/librepertory/src/providers/s3/s3_provider.cpp +++ b/repertory/librepertory/src/providers/s3/s3_provider.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,10 @@ #include "app_config.hpp" #include "comm/i_http_comm.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "file_manager/i_file_manager.hpp" #include "types/repertory.hpp" #include "types/s3.hpp" @@ -39,6 +42,19 @@ #include "utils/string.hpp" #include "utils/time.hpp" +namespace { +[[nodiscard]] auto +set_request_path(auto &request, + const std::string &object_name) -> repertory::api_error { + request.path = object_name; + if (request.path.substr(1U).size() > repertory::max_s3_object_name_length) { + return repertory::api_error::name_too_long; + } + + return repertory::api_error::success; +} +} // namespace + namespace repertory { s3_provider::s3_provider(app_config &config, i_http_comm &comm) : base_provider(config, comm) {} @@ -46,29 +62,31 @@ s3_provider::s3_provider(app_config &config, i_http_comm &comm) auto s3_provider::add_if_not_found( api_file &file, const std::string &object_name) const -> api_error { api_meta_map meta{}; - if (get_item_meta(file.api_path, meta) == api_error::item_not_found) { - auto err = create_path_directories( - file.api_parent, utils::path::get_parent_api_path(object_name)); - if (err != api_error::success) { - return err; + auto res{get_item_meta(file.api_path, meta)}; + if (res == api_error::item_not_found) { + res = create_directory_paths(file.api_parent, + utils::path::get_parent_api_path(object_name)); + if (res != api_error::success) { + return res; } get_api_item_added()(false, file); } - return api_error::success; + return res; } auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t { // 2009-10-12T17:50:30.000Z - auto date_parts = utils::string::split(date, '.', true); - auto date_time = date_parts.at(0U); - auto nanos = + auto date_parts{utils::string::split(date, '.', true)}; + auto date_time{date_parts.at(0U)}; + auto nanos{ (date_parts.size() <= 1U) ? 0U : utils::string::to_uint64( utils::string::split(date_parts.at(1U), 'Z', true).at(0U)) * - 1000000UL; + 1000000UL, + }; struct tm tm1 {}; #if defined(_WIN32) @@ -81,44 +99,31 @@ auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t { #endif // defined(_WIN32) } -auto s3_provider::create_directory_impl(const std::string &api_path, - api_meta_map &meta) -> api_error { +auto s3_provider::create_directory_object(const std::string &api_path, + const std::string &object_name) const + -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); - stop_type stop_requested{false}; + const auto &cfg{get_s3_config()}; - if (is_encrypted) { - std::string encrypted_file_path; - auto res = get_item_meta(utils::path::get_parent_api_path(api_path), - META_KEY, encrypted_file_path); - if (res != api_error::success) { - utils::error::raise_api_path_error(function_name, api_path, res, - "failed to create file"); - return res; - } + std::string response_data; + curl::requests::http_put_file put_dir{}; + put_dir.allow_timeout = true; + put_dir.aws_service = "aws:amz:" + cfg.region + ":s3"; + put_dir.response_handler = [&response_data](auto &&data, - data_buffer result; - utils::encryption::encrypt_data( - cfg.encryption_token, - *(utils::string::split(api_path, '/', false).end() - 1U), result); + long /*response_code*/) { + response_data = std::string(data.begin(), data.end()); + }; - meta[META_KEY] = utils::path::create_api_path( - utils::path::combine(utils::path::create_api_path(encrypted_file_path), - {utils::collection::to_hex_string(result)})); + auto res{set_request_path(put_dir, object_name + '/')}; + if (res != api_error::success) { + return res; } - auto object_name = - utils::path::create_api_path(is_encrypted ? meta[META_KEY] : api_path); - - curl::requests::http_put_file put_file{}; - put_file.allow_timeout = true; - put_file.aws_service = "aws:amz:" + cfg.region + ":s3"; - put_file.path = object_name + '/'; - + stop_type stop_requested{false}; long response_code{}; - if (not get_comm().make_request(put_file, response_code, stop_requested)) { + if (not get_comm().make_request(put_dir, response_code, stop_requested)) { utils::error::raise_api_path_error(function_name, api_path, api_error::comm_error, "failed to create directory"); @@ -126,43 +131,33 @@ auto s3_provider::create_directory_impl(const std::string &api_path, } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to create directory"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to create directory|response|{}", response_data)); return api_error::comm_error; } return api_error::success; } -auto s3_provider::create_file_extra(const std::string &api_path, - api_meta_map &meta) -> api_error { +auto s3_provider::create_directory_impl(const std::string &api_path, + api_meta_map &meta) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_s3_config(); - if (not cfg.encryption_token.empty()) { - std::string encrypted_file_path; - auto res = get_item_meta(utils::path::get_parent_api_path(api_path), - META_KEY, encrypted_file_path); - if (res != api_error::success) { - utils::error::raise_api_path_error(function_name, api_path, res, - "failed to create file"); - return res; - } - - data_buffer result; - utils::encryption::encrypt_data( - cfg.encryption_token, - *(utils::string::split(api_path, '/', false).end() - 1U), result); - - meta[META_KEY] = utils::path::create_api_path( - utils::path::combine(utils::path::create_api_path(encrypted_file_path), - {utils::collection::to_hex_string(result)})); + auto res{set_meta_key(api_path, meta)}; + if (res != api_error::success) { + return res; } - return api_error::success; + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; + + return create_directory_object( + api_path, + utils::path::create_api_path(is_encrypted ? meta[META_KEY] : api_path)); } -auto s3_provider::create_path_directories( +auto s3_provider::create_directory_paths( const std::string &api_path, const std::string &key) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); @@ -170,12 +165,12 @@ auto s3_provider::create_path_directories( return api_error::success; } - const auto &cfg = get_s3_config(); - auto encryption_token = cfg.encryption_token; - auto is_encrypted = not encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto encryption_token{cfg.encryption_token}; + auto is_encrypted{not encryption_token.empty()}; - auto path_parts = utils::string::split(api_path, '/', false); - auto key_parts = utils::string::split(key, '/', false); + auto path_parts{utils::string::split(api_path, '/', false)}; + auto key_parts{utils::string::split(key, '/', false)}; if (is_encrypted && key_parts.size() != path_parts.size()) { return api_error::error; @@ -191,46 +186,38 @@ auto s3_provider::create_path_directories( cur_path = utils::path::create_api_path( utils::path::combine(cur_path, {path_parts.at(idx)})); - auto exists{false}; - auto res = is_directory(cur_path, exists); - if (res != api_error::success) { - return res; - } - - if (not exists) { - curl::requests::http_put_file put_file{}; - put_file.allow_timeout = true; - put_file.aws_service = "aws:amz:" + cfg.region + ":s3"; - put_file.path = (is_encrypted ? cur_key : cur_path) + '/'; - - stop_type stop_requested{false}; - long response_code{}; - if (not get_comm().make_request(put_file, response_code, - stop_requested)) { - utils::error::raise_api_path_error(function_name, cur_path, - api_error::comm_error, - "failed to create directory object"); - return api_error::comm_error; + std::string value; + auto res{get_item_meta(cur_path, META_DIRECTORY, value)}; + if (res == api_error::success) { + if (not utils::string::to_bool(value)) { + return api_error::item_exists; } - - if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, cur_path, - response_code, - "failed to create directory object"); - return api_error::comm_error; - } - } - - api_meta_map meta{}; - res = get_item_meta(cur_path, meta); - if (res == api_error::item_not_found) { - auto dir = create_api_file(cur_path, cur_key, 0U, - get_last_modified(true, cur_path)); - get_api_item_added()(true, dir); - continue; } + if (res == api_error::item_not_found) { + auto exists{false}; + res = is_directory(cur_path, exists); + if (res != api_error::success) { + return res; + } + + if (not exists) { + res = create_directory_object(api_path, + (is_encrypted ? cur_key : cur_path)); + if (res != api_error::success) { + return res; + } + } + + auto dir{ + create_api_file(cur_path, cur_key, 0U, + exists ? get_last_modified(true, cur_path) + : utils::time::get_time_now()), + }; + get_api_item_added()(true, dir); + } + if (res != api_error::success) { return res; } @@ -239,18 +226,19 @@ auto s3_provider::create_path_directories( return api_error::success; } +auto s3_provider::create_file_extra(const std::string &api_path, + api_meta_map &meta) -> api_error { + return set_meta_key(api_path, meta); +} + auto s3_provider::decrypt_object_name(std::string &object_name) const -> api_error { - auto parts = utils::string::split(object_name, '/', false); - for (auto &part : parts) { - if (not utils::encryption::decrypt_file_name( - get_s3_config().encryption_token, part)) { - return api_error::decryption_error; - } + if (utils::encryption::decrypt_file_path(get_s3_config().encryption_token, + object_name)) { + return api_error::success; } - object_name = utils::string::join(parts, '/'); - return api_error::success; + return api_error::decryption_error; } auto s3_provider::get_directory_item_count(const std::string &api_path) const @@ -258,24 +246,26 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const REPERTORY_USES_FUNCTION_NAME(); try { - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; + std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return 0U; } } - auto object_name = + auto object_name{ api_path == "/" ? "" - : utils::path::create_api_path(is_encrypted ? key : api_path); + : utils::path::create_api_path(is_encrypted ? key : api_path), + }; std::string response_data{}; long response_code{}; - auto prefix = object_name.empty() ? object_name : object_name + "/"; + auto prefix{object_name.empty() ? object_name : object_name + "/"}; auto grab_more{true}; std::string token{}; @@ -295,7 +285,7 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const } pugi::xml_document doc; - auto res = doc.load_string(response_data.c_str()); + auto res{doc.load_string(response_data.c_str())}; if (res.status != pugi::xml_parse_status::status_ok) { return total_count; } @@ -311,8 +301,9 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const .as_string(); } - auto node_list = - doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"); + auto node_list{ + doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"), + }; total_count += node_list.size(); node_list = doc.select_nodes("/ListBucketResult/Contents"); @@ -334,30 +325,96 @@ auto s3_provider::get_directory_items_impl( const std::string &api_path, directory_item_list &list) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; + + const auto add_diretory_item = + [this, &is_encrypted, &list](const std::string &child_object_name, + bool directory, auto node) -> api_error { + auto res{api_error::success}; + + directory_item dir_item{}; + dir_item.api_path = child_object_name; + dir_item.directory = directory; + if (is_encrypted) { + res = decrypt_object_name(dir_item.api_path); + if (res != api_error::success) { + return res; + } + } + dir_item.api_path = utils::path::create_api_path(dir_item.api_path); + dir_item.api_parent = utils::path::get_parent_api_path(dir_item.api_path); + + if (directory) { + res = get_item_meta(dir_item.api_path, dir_item.meta); + if (res == api_error::item_not_found) { + res = create_directory_paths(dir_item.api_path, child_object_name); + } + } else { + std::string size_str; + if (get_item_meta(dir_item.api_path, META_SIZE, size_str) == + api_error::success) { + dir_item.size = utils::string::to_uint64(size_str); + } else { + auto size{node.select_node("Size").node().text().as_ullong()}; + + dir_item.size = is_encrypted ? utils::encryption::encrypting_reader:: + calculate_decrypted_size(size) + : size; + } + + res = get_item_meta(dir_item.api_path, dir_item.meta); + if (res == api_error::item_not_found) { + auto last_modified{ + convert_api_date( + node.select_node("LastModified").node().text().as_string()), + }; + + api_file file{}; + file.api_path = dir_item.api_path; + file.api_parent = dir_item.api_parent; + file.accessed_date = file.changed_date = file.creation_date = + file.modified_date = last_modified; + file.file_size = dir_item.size; + if (is_encrypted) { + file.key = child_object_name; + } + + res = add_if_not_found(file, child_object_name); + } + } + + if (res != api_error::success) { + return res; + } + + list.push_back(std::move(dir_item)); + return api_error::success; + }; - auto ret = api_error::success; std::string key; if (is_encrypted) { - ret = get_item_meta(api_path, META_KEY, key); - if (ret != api_error::success) { - return ret; + auto res{get_item_meta(api_path, META_KEY, key)}; + if (res != api_error::success) { + return res; } } - auto object_name = + auto object_name{ api_path == "/" ? "" - : utils::path::create_api_path(is_encrypted ? key : api_path); + : utils::path::create_api_path(is_encrypted ? key : api_path), + }; - std::string response_data{}; - long response_code{}; - auto prefix = object_name.empty() ? object_name : object_name + "/"; + auto prefix{ + object_name.empty() ? object_name : object_name + "/", + }; auto grab_more{true}; std::string token{}; while (grab_more) { + std::string response_data{}; + long response_code{}; if (not get_object_list(response_data, response_code, "/", prefix, token)) { return api_error::comm_error; } @@ -373,7 +430,7 @@ auto s3_provider::get_directory_items_impl( } pugi::xml_document doc; - auto parse_res = doc.load_string(response_data.c_str()); + auto parse_res{doc.load_string(response_data.c_str())}; if (parse_res.status != pugi::xml_parse_status::status_ok) { return api_error::error; } @@ -389,91 +446,38 @@ auto s3_provider::get_directory_items_impl( .as_string(); } - const auto add_directory_item = - [&](bool directory, const std::string &name, - std::uint64_t last_modified, - std::function get_size) - -> api_error { - auto child_api_path = - utils::path::create_api_path(utils::path::combine("/", {name})); - std::string child_object_name; - if (is_encrypted) { - child_object_name = child_api_path; - if (not utils::encryption::decrypt_file_path(cfg.encryption_token, - child_api_path)) { - return api_error::decryption_error; - } - } - - directory_item dir_item{}; - dir_item.api_path = child_api_path; - dir_item.api_parent = utils::path::get_parent_api_path(dir_item.api_path); - dir_item.directory = directory; - dir_item.size = get_size(dir_item); - ret = get_item_meta(child_api_path, dir_item.meta); - if (ret == api_error::item_not_found) { - if (directory) { - ret = create_path_directories(child_api_path, child_object_name); - if (ret != api_error::success) { - return ret; - } - } else { - auto file = create_api_file(child_api_path, child_object_name, - dir_item.size, last_modified); - ret = add_if_not_found(file, child_object_name); - if (ret != api_error::success) { - return ret; - } - } - - ret = get_item_meta(child_api_path, dir_item.meta); - } - - if (ret != api_error::success) { - return ret; - } - - list.push_back(std::move(dir_item)); - return api_error::success; + auto node_list{ + doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"), }; - - auto node_list = - doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"); for (const auto &node : node_list) { - add_directory_item( - true, node.node().text().as_string(), 0U, - [](const directory_item &) -> std::uint64_t { return 0U; }); + auto child_object_name{ + utils::path::create_api_path( + utils::path::combine("/", {node.node().text().as_string()})), + }; + auto res{add_diretory_item(child_object_name, true, node.node())}; + if (res != api_error::success) { + return res; + } } node_list = doc.select_nodes("/ListBucketResult/Contents"); for (const auto &node : node_list) { - auto child_object_name = utils::path::create_api_path( - node.node().select_node("Key").node().text().as_string()); + auto child_object_name{ + utils::path::create_api_path( + node.node().select_node("Key").node().text().as_string()), + }; if (child_object_name == utils::path::create_api_path(prefix)) { continue; } - auto size = node.node().select_node("Size").node().text().as_ullong(); - auto last_modified = convert_api_date( - node.node().select_node("LastModified").node().text().as_string()); - add_directory_item(false, child_object_name, last_modified, - [this, &is_encrypted, &size]( - const directory_item &dir_item) -> std::uint64_t { - std::string size_str; - if (get_item_meta(dir_item.api_path, META_SIZE, - size_str) == api_error::success) { - return utils::string::to_uint64(size_str); - } - - return is_encrypted - ? utils::encryption::encrypting_reader:: - calculate_decrypted_size(size) - : size; - }); + auto res{add_diretory_item(child_object_name, false, node.node())}; + if (res != api_error::success) { + return res; + } } } - return ret; + return api_error::success; } auto s3_provider::get_file(const std::string &api_path, @@ -484,8 +488,9 @@ auto s3_provider::get_file(const std::string &api_path, bool is_encrypted{}; std::string object_name; head_object_result result{}; - auto res = - get_object_info(false, api_path, is_encrypted, object_name, result); + auto res{ + get_object_info(false, api_path, is_encrypted, object_name, result), + }; if (res != api_error::success) { return res; } @@ -520,76 +525,91 @@ auto s3_provider::get_file_list(api_file_list &list, std::string &marker) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - std::string response_data; - long response_code{}; - if (not get_object_list(response_data, response_code, std::nullopt, - std::nullopt, marker)) { - return api_error::comm_error; - } - - if (response_code != http_error_codes::ok) { - utils::error::raise_error(function_name, response_code, - "failed to get file list"); - return api_error::comm_error; - } - - pugi::xml_document doc; - auto res = doc.load_string(response_data.c_str()); - if (res.status != pugi::xml_parse_status::status_ok) { - utils::error::raise_error(function_name, res.status, - "failed to parse xml document"); - return api_error::comm_error; - } - - auto grab_more = - doc.select_node("/ListBucketResult/IsTruncated").node().text().as_bool(); - if (grab_more) { - marker = doc.select_node("/ListBucketResult/NextContinuationToken") - .node() - .text() - .as_string(); - } - - auto node_list = doc.select_nodes("/ListBucketResult/Contents"); - for (const auto &node : node_list) { - auto object_name = - std::string{node.node().select_node("Key").node().text().as_string()}; - auto api_path{object_name}; - if (utils::string::ends_with(api_path, "/")) { - continue; + try { + std::string response_data; + long response_code{}; + if (not get_object_list(response_data, response_code, std::nullopt, + std::nullopt, marker)) { + return api_error::comm_error; } - auto is_encrypted = not get_s3_config().encryption_token.empty(); - if (is_encrypted) { - auto err = decrypt_object_name(api_path); - if (err != api_error::success) { - return err; + if (response_code != http_error_codes::ok) { + utils::error::raise_error(function_name, response_code, + "failed to get file list"); + return api_error::comm_error; + } + + pugi::xml_document doc; + auto result{doc.load_string(response_data.c_str())}; + if (result.status != pugi::xml_parse_status::status_ok) { + utils::error::raise_error(function_name, result.status, + "failed to parse xml document"); + return api_error::comm_error; + } + + auto grab_more{ + doc.select_node("/ListBucketResult/IsTruncated") + .node() + .text() + .as_bool(), + }; + if (grab_more) { + marker = doc.select_node("/ListBucketResult/NextContinuationToken") + .node() + .text() + .as_string(); + } + + auto node_list{doc.select_nodes("/ListBucketResult/Contents")}; + for (const auto &node : node_list) { + auto object_name{ + std::string(node.node().select_node("Key").node().text().as_string()), + }; + if (utils::string::ends_with(object_name, "/")) { + continue; } + + auto api_path{object_name}; + auto is_encrypted{not get_s3_config().encryption_token.empty()}; + + if (is_encrypted) { + auto res{decrypt_object_name(api_path)}; + if (res != api_error::success) { + return res; + } + } + + auto size{node.node().select_node("Size").node().text().as_ullong()}; + + api_file file{}; + file.api_path = utils::path::create_api_path(api_path); + file.api_parent = utils::path::get_parent_api_path(file.api_path); + file.accessed_date = file.changed_date = file.creation_date = + file.modified_date = convert_api_date(node.node() + .select_node("LastModified") + .node() + .text() + .as_string()); + file.file_size = + is_encrypted + ? utils::encryption::encrypting_reader::calculate_decrypted_size( + size) + : size; + file.key = is_encrypted ? utils::path::create_api_path(object_name) : ""; + auto res{add_if_not_found(file, file.key)}; + if (res != api_error::success) { + return res; + } + + list.push_back(std::move(file)); } - auto size = node.node().select_node("Size").node().text().as_ullong(); - - api_file file{}; - file.api_path = utils::path::create_api_path(api_path); - file.api_parent = utils::path::get_parent_api_path(file.api_path); - file.accessed_date = file.changed_date = file.creation_date = - file.modified_date = convert_api_date( - node.node().select_node("LastModified").node().text().as_string()); - file.file_size = - is_encrypted - ? utils::encryption::encrypting_reader::calculate_decrypted_size( - size) - : size; - file.key = is_encrypted ? utils::path::create_api_path(object_name) : ""; - auto err = add_if_not_found(file, file.key); - if (err != api_error::success) { - return err; - } - - list.push_back(std::move(file)); + return grab_more ? api_error::more_data : api_error::success; + } catch (const std::exception &e) { + utils::error::raise_error(function_name, e, "exception occurred"); } - return grab_more ? api_error::more_data : api_error::success; + return api_error::error; } auto s3_provider::get_last_modified( @@ -609,12 +629,12 @@ auto s3_provider::get_object_info( REPERTORY_USES_FUNCTION_NAME(); try { - const auto &cfg = get_s3_config(); + const auto &cfg{get_s3_config()}; is_encrypted = not cfg.encryption_token.empty(); std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return res; } @@ -622,11 +642,21 @@ auto s3_provider::get_object_info( object_name = utils::path::create_api_path(is_encrypted ? key : api_path); + std::string response_data; curl::requests::http_head head{}; head.allow_timeout = true; head.aws_service = "aws:amz:" + cfg.region + ":s3"; - head.path = directory ? object_name + '/' : object_name; head.response_headers = http_headers{}; + head.response_handler = [&response_data](auto &&data, + long /*response_code*/) { + response_data = std::string(data.begin(), data.end()); + }; + auto res{ + set_request_path(head, directory ? object_name + '/' : object_name), + }; + if (res != api_error::success) { + return res; + } stop_type stop_requested{false}; long response_code{}; @@ -639,8 +669,9 @@ auto s3_provider::get_object_info( } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to get object info"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to get object info|response|{}", response_data)); return api_error::comm_error; } @@ -673,8 +704,7 @@ auto s3_provider::get_object_list( if (token.has_value() && not token.value().empty()) { get.query["continuation-token"] = token.value(); } - get.response_handler = [&response_data](const data_buffer &data, - long /*response_code*/) { + get.response_handler = [&response_data](auto &&data, long /*response_code*/) { response_data = std::string(data.begin(), data.end()); }; @@ -690,18 +720,19 @@ auto s3_provider::is_directory(const std::string &api_path, bool &exists) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - exists = false; - if (api_path == "/") { - exists = true; - return api_error::success; - } - try { + exists = false; + if (api_path == "/") { + exists = true; + return api_error::success; + } + bool is_encrypted{}; std::string object_name; head_object_result result{}; - auto res = - get_object_info(true, api_path, is_encrypted, object_name, result); + auto res{ + get_object_info(true, api_path, is_encrypted, object_name, result), + }; if (res != api_error::item_not_found && res != api_error::success) { return res; } @@ -718,17 +749,18 @@ auto s3_provider::is_file(const std::string &api_path, bool &exists) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - exists = false; - if (api_path == "/") { - return api_error::success; - } - try { + exists = false; + if (api_path == "/") { + return api_error::success; + } + bool is_encrypted{}; std::string object_name; head_object_result result{}; - auto res = - get_object_info(false, api_path, is_encrypted, object_name, result); + auto res{ + get_object_info(false, api_path, is_encrypted, object_name, result), + }; if (res != api_error::item_not_found && res != api_error::success) { return res; } @@ -752,40 +784,46 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size, REPERTORY_USES_FUNCTION_NAME(); try { - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; + std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return res; } } - auto object_name = - utils::path::create_api_path(is_encrypted ? key : api_path); + auto object_name{ + utils::path::create_api_path(is_encrypted ? key : api_path), + }; const auto read_bytes = [this, &api_path, &cfg, &object_name, &stop_requested](std::size_t read_size, std::size_t read_offset, data_buffer &read_buffer) -> api_error { - auto res = api_error::error; + auto res{api_error::error}; for (std::uint32_t idx = 0U; - not stop_requested && res != api_error::success && + not(stop_requested || app_config::get_stop_requested()) && + res != api_error::success && idx < get_config().get_retry_read_count() + 1U; ++idx) { curl::requests::http_get get{}; get.aws_service = "aws:amz:" + cfg.region + ":s3"; get.headers["response-content-type"] = "binary/octet-stream"; - get.path = object_name; get.range = {{ read_offset, read_offset + read_size - 1U, }}; - get.response_handler = [&read_buffer](const data_buffer &response_data, + get.response_handler = [&read_buffer](auto &&response_data, long /*response_code*/) { read_buffer = response_data; }; + res = set_request_path(get, object_name); + if (res != api_error::success) { + return res; + } long response_code{}; const auto notify_retry = [&]() { @@ -827,12 +865,12 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size, } std::string temp; - auto res = get_item_meta(api_path, META_SIZE, temp); + auto res{get_item_meta(api_path, META_SIZE, temp)}; if (res != api_error::success) { return res; } - auto total_size = utils::string::to_uint64(temp); + auto total_size{utils::string::to_uint64(temp)}; return utils::encryption::read_encrypted_range( {offset, offset + size - 1U}, utils::encryption::generate_key( @@ -858,28 +896,38 @@ auto s3_provider::remove_directory_impl(const std::string &api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return res; } } - auto object_name = - utils::path::create_api_path(is_encrypted ? key : api_path); + auto object_name{ + utils::path::create_api_path(is_encrypted ? key : api_path), + }; - curl::requests::http_delete del{}; - del.allow_timeout = true; - del.aws_service = "aws:amz:" + cfg.region + ":s3"; - del.path = object_name + '/'; + std::string response_data; + curl::requests::http_delete del_dir{}; + del_dir.allow_timeout = true; + del_dir.aws_service = "aws:amz:" + cfg.region + ":s3"; + del_dir.response_handler = [&response_data](auto &&data, + long /*response_code*/) { + response_data = std::string(data.begin(), data.end()); + }; + + auto res{set_request_path(del_dir, object_name + '/')}; + if (res != api_error::success) { + return res; + } long response_code{}; stop_type stop_requested{}; - if (not get_comm().make_request(del, response_code, stop_requested)) { + if (not get_comm().make_request(del_dir, response_code, stop_requested)) { utils::error::raise_api_path_error(function_name, api_path, api_error::comm_error, "failed to remove directory"); @@ -889,8 +937,9 @@ auto s3_provider::remove_directory_impl(const std::string &api_path) if ((response_code < http_error_codes::ok || response_code >= http_error_codes::multiple_choices) && response_code != http_error_codes::not_found) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to remove directory"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to remove directory|response|{}", response_data)); return api_error::comm_error; } @@ -900,28 +949,37 @@ auto s3_provider::remove_directory_impl(const std::string &api_path) auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return res; } } - auto object_name = - utils::path::create_api_path(is_encrypted ? key : api_path); + auto object_name{ + utils::path::create_api_path(is_encrypted ? key : api_path), + }; - curl::requests::http_delete del{}; - del.allow_timeout = true; - del.aws_service = "aws:amz:" + cfg.region + ":s3"; - del.path = object_name; + std::string response_data; + curl::requests::http_delete del_file{}; + del_file.allow_timeout = true; + del_file.aws_service = "aws:amz:" + cfg.region + ":s3"; + del_file.response_handler = [&response_data](auto &&data, + long /*response_code*/) { + response_data = std::string(data.begin(), data.end()); + }; + auto res{set_request_path(del_file, object_name)}; + if (res != api_error::success) { + return res; + } long response_code{}; stop_type stop_requested{}; - if (not get_comm().make_request(del, response_code, stop_requested)) { + if (not get_comm().make_request(del_file, response_code, stop_requested)) { utils::error::raise_api_path_error(function_name, api_path, api_error::comm_error, "failed to remove file"); @@ -931,8 +989,9 @@ auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error { if ((response_code < http_error_codes::ok || response_code >= http_error_codes::multiple_choices) && response_code != http_error_codes::not_found) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to remove file"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to remove file|response|{}", response_data)); return api_error::comm_error; } @@ -945,18 +1004,62 @@ auto s3_provider::rename_file(const std::string & /* from_api_path */, return api_error::not_implemented; } +auto s3_provider::set_meta_key(const std::string &api_path, + api_meta_map &meta) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; + if (not is_encrypted) { + return api_error::success; + } + + std::string encrypted_parent_path; + auto res{ + get_item_meta(utils::path::get_parent_api_path(api_path), META_KEY, + encrypted_parent_path), + }; + if (res != api_error::success) { + utils::error::raise_api_path_error(function_name, api_path, res, + "failed to create file"); + return res; + } + + data_buffer result; + utils::encryption::encrypt_data( + cfg.encryption_token, + *(utils::string::split(api_path, '/', false).end() - 1U), result); + + meta[META_KEY] = utils::path::create_api_path( + utils::path::combine(utils::path::create_api_path(encrypted_parent_path), + { + utils::collection::to_hex_string(result), + })); + return api_error::success; +} + auto s3_provider::start(api_item_added_callback api_item_added, i_file_manager *mgr) -> bool { - event_system::instance().raise("s3_provider"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "s3_provider"); s3_config_ = get_config().get_s3_config(); get_comm().enable_s3_path_style(s3_config_.use_path_style); - return base_provider::start(api_item_added, mgr); + auto ret = base_provider::start(api_item_added, mgr); + event_system::instance().raise(function_name, + "s3_provider"); + return ret; } void s3_provider::stop() { - event_system::instance().raise("s3_provider"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "s3_provider"); base_provider::stop(); - event_system::instance().raise("s3_provider"); + event_system::instance().raise(function_name, + "s3_provider"); } auto s3_provider::upload_file_impl(const std::string &api_path, @@ -966,37 +1069,47 @@ auto s3_provider::upload_file_impl(const std::string &api_path, std::uint64_t file_size{}; if (utils::file::file{source_path}.exists()) { - auto opt_size = utils::file::file{source_path}.size(); + auto opt_size{utils::file::file{source_path}.size()}; if (not opt_size.has_value()) { return api_error::comm_error; } file_size = opt_size.value(); } - const auto &cfg = get_s3_config(); - auto is_encrypted = not cfg.encryption_token.empty(); + const auto &cfg{get_s3_config()}; + auto is_encrypted{not cfg.encryption_token.empty()}; std::string key; if (is_encrypted) { - auto res = get_item_meta(api_path, META_KEY, key); + auto res{get_item_meta(api_path, META_KEY, key)}; if (res != api_error::success) { return res; } } - auto object_name = - utils::path::create_api_path(is_encrypted ? key : api_path); + auto object_name{ + utils::path::create_api_path(is_encrypted ? key : api_path), + }; + std::string response_data; curl::requests::http_put_file put_file{}; put_file.aws_service = "aws:amz:" + cfg.region + ":s3"; - put_file.path = object_name; + put_file.response_handler = [&response_data](auto &&data, + long /*response_code*/) { + response_data = std::string(data.begin(), data.end()); + }; put_file.source_path = source_path; - if (is_encrypted && file_size > 0U) { - static stop_type no_stop{false}; + auto res{set_request_path(put_file, object_name)}; + if (res != api_error::success) { + return res; + } + if (is_encrypted && file_size > 0U) { put_file.reader = std::make_shared( - object_name, source_path, no_stop, cfg.encryption_token, -1); + object_name, source_path, + []() -> bool { return app_config::get_stop_requested(); }, + cfg.encryption_token, -1); } long response_code{}; @@ -1005,8 +1118,9 @@ auto s3_provider::upload_file_impl(const std::string &api_path, } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to get upload file"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to upload file|response|{}", response_data)); return api_error::comm_error; } diff --git a/repertory/librepertory/src/providers/sia/sia_provider.cpp b/repertory/librepertory/src/providers/sia/sia_provider.cpp index c0863800..ceced3b7 100644 --- a/repertory/librepertory/src/providers/sia/sia_provider.cpp +++ b/repertory/librepertory/src/providers/sia/sia_provider.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,11 @@ #include "app_config.hpp" #include "comm/i_http_comm.hpp" -#include "events/events.hpp" +#include "events/event_system.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "file_manager/i_file_manager.hpp" #include "providers/base_provider.hpp" #include "providers/s3/s3_provider.hpp" @@ -69,6 +73,15 @@ auto sia_provider::create_directory_impl(const std::string &api_path, put_file.path = "/api/worker/objects" + api_path + "/"; put_file.query["bucket"] = get_bucket(get_sia_config()); + std::string error_data; + put_file.response_handler = [&error_data](auto &&data, long response_code) { + if (response_code == http_error_codes::ok) { + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + long response_code{}; stop_type stop_requested{}; if (not get_comm().make_request(put_file, response_code, stop_requested)) { @@ -79,8 +92,9 @@ auto sia_provider::create_directory_impl(const std::string &api_path, } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to create directory"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to create directory|response|{}", error_data)); return api_error::comm_error; } @@ -101,8 +115,8 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const if (object_list.contains("entries")) { for (const auto &entry : object_list.at("entries")) { try { - auto name = entry.at("name").get(); - auto entry_api_path = utils::path::create_api_path(name); + auto name{entry.at("name").get()}; + auto entry_api_path{utils::path::create_api_path(name)}; if (utils::string::ends_with(name, "/") && (entry_api_path == api_path)) { continue; @@ -138,10 +152,10 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path, if (object_list.contains("entries")) { for (const auto &entry : object_list.at("entries")) { try { - auto name = entry.at("name").get(); - auto entry_api_path = utils::path::create_api_path(name); + auto name{entry.at("name").get()}; + auto entry_api_path{utils::path::create_api_path(name)}; - auto directory = utils::string::ends_with(name, "/"); + auto directory{utils::string::ends_with(name, "/")}; if (directory && (entry_api_path == api_path)) { continue; } @@ -154,10 +168,10 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path, : entry["size"].get(), get_last_modified(entry)); get_api_item_added()(directory, file); - auto res = get_item_meta(entry_api_path, meta); + auto res{get_item_meta(entry_api_path, meta)}; if (res != api_error::success) { - utils::error::raise_error(function_name, res, - "failed to get item meta"); + utils::error::raise_api_path_error(function_name, entry_api_path, + res, "failed to get item meta"); continue; } } else { @@ -187,30 +201,40 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path, auto sia_provider::get_file(const std::string &api_path, api_file &file) const -> api_error { - json file_data{}; - auto res = get_object_info(api_path, file_data); - if (res != api_error::success) { - return res; + REPERTORY_USES_FUNCTION_NAME(); + + try { + json file_data{}; + auto res{get_object_info(api_path, file_data)}; + if (res != api_error::success) { + return res; + } + + auto slabs{file_data["object"]["Slabs"]}; + auto size{ + std::accumulate( + slabs.begin(), slabs.end(), std::uint64_t(0U), + [](auto &&total_size, const json &slab) -> std::uint64_t { + return total_size + slab["Length"].get(); + }), + }; + + api_meta_map meta{}; + if (get_item_meta(api_path, meta) == api_error::item_not_found) { + file = create_api_file(api_path, "", size, + get_last_modified(file_data["object"])); + get_api_item_added()(false, file); + } else { + file = create_api_file(api_path, size, meta); + } + + return api_error::success; + } catch (const std::exception &e) { + utils::error::raise_api_path_error(function_name, api_path, e, + "failed to get file"); } - auto slabs = file_data["object"]["Slabs"]; - auto size = - std::accumulate(slabs.begin(), slabs.end(), std::uint64_t(0U), - [](std::uint64_t total_size, - const nlohmann::json &slab) -> std::uint64_t { - return total_size + slab["Length"].get(); - }); - - api_meta_map meta{}; - if (get_item_meta(api_path, meta) == api_error::item_not_found) { - file = create_api_file(api_path, "", size, - get_last_modified(file_data["object"])); - get_api_item_added()(false, file); - } else { - file = create_api_file(api_path, size, meta); - } - - return api_error::success; + return api_error::error; } auto sia_provider::get_file_list(api_file_list &list, @@ -228,8 +252,8 @@ auto sia_provider::get_file_list(api_file_list &list, if (object_list.contains("entries")) { for (const auto &entry : object_list.at("entries")) { - auto name = entry.at("name").get(); - auto entry_api_path = utils::path::create_api_path(name); + auto name{entry.at("name").get()}; + auto entry_api_path{utils::path::create_api_path(name)}; if (utils::string::ends_with(name, "/")) { if (entry_api_path == utils::path::create_api_path(api_path)) { @@ -239,12 +263,14 @@ auto sia_provider::get_file_list(api_file_list &list, api_meta_map meta{}; if (get_item_meta(entry_api_path, meta) == api_error::item_not_found) { - auto dir = create_api_file(entry_api_path, "", 0U, - get_last_modified(entry)); + auto dir{ + create_api_file(entry_api_path, "", 0U, + get_last_modified(entry)), + }; get_api_item_added()(true, dir); } - auto res = get_files_in_dir(entry_api_path); + auto res{get_files_in_dir(entry_api_path)}; if (res != api_error::success) { return res; } @@ -270,8 +296,8 @@ auto sia_provider::get_file_list(api_file_list &list, return api_error::success; } catch (const std::exception &e) { - utils::error::raise_error(function_name, e, - "failed to process directory|" + api_path); + utils::error::raise_api_path_error(function_name, api_path, e, + "failed to process directory"); } return api_error::error; @@ -290,11 +316,15 @@ auto sia_provider::get_object_info(const std::string &api_path, get.path = "/api/bus/objects" + api_path; get.query["bucket"] = get_bucket(get_sia_config()); - get.response_handler = [&object_info](const data_buffer &data, - long response_code) { + std::string error_data; + get.response_handler = [&error_data, &object_info](auto &&data, + long response_code) { if (response_code == http_error_codes::ok) { object_info = nlohmann::json::parse(data.begin(), data.end()); + return; } + + error_data = std::string(data.begin(), data.end()); }; long response_code{}; @@ -308,8 +338,9 @@ auto sia_provider::get_object_info(const std::string &api_path, } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to get object info"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to get object info|response|{}", error_data)); return api_error::comm_error; } @@ -326,34 +357,46 @@ auto sia_provider::get_object_list(const std::string &api_path, nlohmann::json &object_list) const -> bool { REPERTORY_USES_FUNCTION_NAME(); - curl::requests::http_get get{}; - get.allow_timeout = true; - get.path = "/api/bus/objects" + api_path + "/"; - get.query["bucket"] = get_bucket(get_sia_config()); + try { + curl::requests::http_get get{}; + get.allow_timeout = true; + get.path = "/api/bus/objects" + api_path + "/"; + get.query["bucket"] = get_bucket(get_sia_config()); - get.response_handler = [&object_list](const data_buffer &data, - long response_code) { - if (response_code == http_error_codes::ok) { - object_list = nlohmann::json::parse(data.begin(), data.end()); + std::string error_data; + get.response_handler = [&error_data, &object_list](auto &&data, + long response_code) { + if (response_code == http_error_codes::ok) { + object_list = nlohmann::json::parse(data.begin(), data.end()); + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + + long response_code{}; + stop_type stop_requested{}; + if (not get_comm().make_request(get, response_code, stop_requested)) { + utils::error::raise_api_path_error(function_name, api_path, + api_error::comm_error, + "failed to get object list"); + return false; } - }; - long response_code{}; - stop_type stop_requested{}; - if (not get_comm().make_request(get, response_code, stop_requested)) { - utils::error::raise_api_path_error(function_name, api_path, - api_error::comm_error, + if (response_code != http_error_codes::ok) { + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to get object list|response|{}", error_data)); + return false; + } + + return true; + } catch (const std::exception &e) { + utils::error::raise_api_path_error(function_name, api_path, e, "failed to get object list"); - return false; } - if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to get object list"); - return false; - } - - return true; + return false; } auto sia_provider::get_total_drive_space() const -> std::uint64_t { @@ -365,12 +408,16 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t { get.path = "/api/autopilot/config"; get.query["bucket"] = get_bucket(get_sia_config()); - json config_data{}; - get.response_handler = [&config_data](const data_buffer &data, - long response_code) { + json config_data; + std::string error_data; + get.response_handler = [&error_data, &config_data](auto &&data, + long response_code) { if (response_code == http_error_codes::ok) { config_data = nlohmann::json::parse(data.begin(), data.end()); + return; } + + error_data = std::string(data.begin(), data.end()); }; long response_code{}; @@ -380,8 +427,10 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t { } if (response_code != http_error_codes::ok) { - utils::error::raise_error(function_name, response_code, - "failed to get total drive space"); + utils::error::raise_error( + function_name, response_code, + fmt::format("failed to get total drive space|response|{}", + error_data)); return 0U; } @@ -398,14 +447,14 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - if (api_path == "/") { - exists = true; - return api_error::success; - } - - exists = false; - try { + if (api_path == "/") { + exists = true; + return api_error::success; + } + + exists = false; + json object_list{}; if (not get_object_list(utils::path::get_parent_api_path(api_path), object_list)) { @@ -413,15 +462,14 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const } exists = object_list.contains("entries") && - std::find_if(object_list.at("entries").begin(), - object_list.at("entries").end(), - [&api_path](const auto &entry) -> bool { - return entry.at("name") == (api_path + "/"); - }) != object_list.at("entries").end(); + std::ranges::find_if(object_list.at("entries"), + [&api_path](auto &&entry) -> bool { + return entry.at("name") == (api_path + "/"); + }) != object_list.at("entries").end(); return api_error::success; } catch (const std::exception &e) { - utils::error::raise_api_path_error(function_name, api_path, e, - "failed to determine path is directory"); + utils::error::raise_api_path_error( + function_name, api_path, e, "failed to determine if path is directory"); } return api_error::error; @@ -431,14 +479,14 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); - exists = false; - if (api_path == "/") { - return api_error::success; - } - try { + exists = false; + if (api_path == "/") { + return api_error::success; + } + json file_data{}; - auto res = get_object_info(api_path, file_data); + auto res{get_object_info(api_path, file_data)}; if (res == api_error::item_not_found) { return api_error::success; } @@ -451,7 +499,7 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const return api_error::success; } catch (const std::exception &e) { utils::error::raise_api_path_error(function_name, api_path, e, - "failed to determine path is directory"); + "failed to determine if path is file"); } return api_error::error; @@ -466,12 +514,16 @@ auto sia_provider::is_online() const -> bool { get.path = "/api/bus/consensus/state"; get.query["bucket"] = get_bucket(get_sia_config()); - json state_data{}; - get.response_handler = [&state_data](const data_buffer &data, - long response_code) { + std::string error_data; + json state_data; + get.response_handler = [&error_data, &state_data](auto &&data, + long response_code) { if (response_code == http_error_codes::ok) { state_data = nlohmann::json::parse(data.begin(), data.end()); + return; } + + error_data = std::string(data.begin(), data.end()); }; long response_code{}; @@ -483,8 +535,10 @@ auto sia_provider::is_online() const -> bool { } if (response_code != http_error_codes::ok) { - utils::error::raise_error(function_name, response_code, - "failed to determine if provider is online"); + utils::error::raise_error( + function_name, response_code, + fmt::format("failed to determine if provider is online|response|{}", + error_data)); return false; } @@ -503,54 +557,63 @@ auto sia_provider::read_file_bytes(const std::string &api_path, stop_type &stop_requested) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - curl::requests::http_get get{}; - get.path = "/api/worker/objects" + api_path; - get.query["bucket"] = get_bucket(get_sia_config()); - get.range = {{ - offset, - offset + size - 1U, - }}; - get.response_handler = [&buffer](const data_buffer &data, - long /*response_code*/) { buffer = data; }; - - auto res = api_error::comm_error; - for (std::uint32_t idx = 0U; - not stop_requested && res != api_error::success && - idx < get_config().get_retry_read_count() + 1U; - ++idx) { - long response_code{}; - const auto notify_retry = [&]() { - if (response_code == 0) { - utils::error::raise_api_path_error( - function_name, api_path, api_error::comm_error, - "read file bytes failed|offset|" + std::to_string(offset) + - "|size|" + std::to_string(size) + "|retry|" + - std::to_string(idx + 1U)); - } else { - utils::error::raise_api_path_error( - function_name, api_path, response_code, - "read file bytes failed|offset|" + std::to_string(offset) + - "|size|" + std::to_string(size) + "|retry|" + - std::to_string(idx + 1U)); - } - std::this_thread::sleep_for(1s); + try { + curl::requests::http_get get{}; + get.path = "/api/worker/objects" + api_path; + get.query["bucket"] = get_bucket(get_sia_config()); + get.range = {{ + offset, + offset + size - 1U, + }}; + get.response_handler = [&buffer](auto &&data, long /* response_code */) { + buffer = data; }; - if (not get_comm().make_request(get, response_code, stop_requested)) { - notify_retry(); - continue; + auto res{api_error::comm_error}; + for (std::uint32_t idx = 0U; + not(stop_requested || app_config::get_stop_requested()) && + res != api_error::success && + idx < get_config().get_retry_read_count() + 1U; + ++idx) { + long response_code{}; + const auto notify_retry = [&]() { + if (response_code == 0) { + utils::error::raise_api_path_error( + function_name, api_path, api_error::comm_error, + "read file bytes failed|offset|" + std::to_string(offset) + + "|size|" + std::to_string(size) + "|retry|" + + std::to_string(idx + 1U)); + } else { + utils::error::raise_api_path_error( + function_name, api_path, response_code, + "read file bytes failed|offset|" + std::to_string(offset) + + "|size|" + std::to_string(size) + "|retry|" + + std::to_string(idx + 1U)); + } + std::this_thread::sleep_for(1s); + }; + + if (not get_comm().make_request(get, response_code, stop_requested)) { + notify_retry(); + continue; + } + + if (response_code < http_error_codes::ok || + response_code >= http_error_codes::multiple_choices) { + notify_retry(); + continue; + } + + res = api_error::success; } - if (response_code < http_error_codes::ok || - response_code >= http_error_codes::multiple_choices) { - notify_retry(); - continue; - } - - res = api_error::success; + return res; + } catch (const std::exception &e) { + utils::error::raise_api_path_error(function_name, api_path, e, + "failed to read file bytes"); } - return res; + return api_error::error; } auto sia_provider::remove_directory_impl(const std::string &api_path) @@ -562,6 +625,15 @@ auto sia_provider::remove_directory_impl(const std::string &api_path) del.path = "/api/bus/objects" + api_path + "/"; del.query["bucket"] = get_bucket(get_sia_config()); + std::string error_data; + del.response_handler = [&error_data](auto &&data, long response_code) { + if (response_code == http_error_codes::ok) { + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + long response_code{}; stop_type stop_requested{}; if (not get_comm().make_request(del, response_code, stop_requested)) { @@ -572,8 +644,9 @@ auto sia_provider::remove_directory_impl(const std::string &api_path) } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to remove directory"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to remove directory|response|{}", error_data)); return api_error::comm_error; } @@ -588,6 +661,15 @@ auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error { del.path = "/api/bus/objects" + api_path; del.query["bucket"] = get_bucket(get_sia_config()); + std::string error_data; + del.response_handler = [&error_data](auto &&data, long response_code) { + if (response_code == http_error_codes::ok) { + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + long response_code{}; stop_type stop_requested{}; if (not get_comm().make_request(del, response_code, stop_requested)) { @@ -599,8 +681,9 @@ auto sia_provider::remove_file_impl(const std::string &api_path) -> api_error { if (response_code != http_error_codes::ok && response_code != http_error_codes::not_found) { - utils::error::raise_api_path_error(function_name, api_path, response_code, - "failed to remove file"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to remove file|response|{}", error_data)); return api_error::comm_error; } @@ -611,46 +694,74 @@ auto sia_provider::rename_file(const std::string &from_api_path, const std::string &to_api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); - curl::requests::http_post post{}; - post.json = nlohmann::json({ - {"from", from_api_path}, - {"to", to_api_path}, - {"mode", "single"}, - }); - post.path = "/api/bus/objects/rename"; - post.query["bucket"] = get_bucket(get_sia_config()); + try { + curl::requests::http_post post{}; + post.json = nlohmann::json({ + {"from", from_api_path}, + {"to", to_api_path}, + {"mode", "single"}, + }); + post.path = "/api/bus/objects/rename"; + post.query["bucket"] = get_bucket(get_sia_config()); - long response_code{}; - stop_type stop_requested{}; - if (not get_comm().make_request(post, response_code, stop_requested)) { + std::string error_data; + post.response_handler = [&error_data](auto &&data, long response_code) { + if (response_code == http_error_codes::ok) { + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + + long response_code{}; + stop_type stop_requested{}; + if (not get_comm().make_request(post, response_code, stop_requested)) { + utils::error::raise_api_path_error( + function_name, fmt::format("{}|{}", from_api_path, to_api_path), + api_error::comm_error, "failed to rename file"); + return api_error::comm_error; + } + + if (response_code < http_error_codes::ok || + response_code >= http_error_codes::multiple_choices) { + utils::error::raise_api_path_error( + function_name, fmt::format("{}|{}", from_api_path, to_api_path), + response_code, + fmt::format("failed to rename file file|response|{}", error_data)); + return api_error::comm_error; + } + + return get_db().rename_item_meta(from_api_path, to_api_path); + } catch (const std::exception &e) { utils::error::raise_api_path_error( - function_name, from_api_path + '|' + to_api_path, api_error::comm_error, - "failed to rename file"); - return api_error::comm_error; + function_name, fmt::format("{}|{}", from_api_path, to_api_path), e, + "failed to rename file file|response"); } - if (response_code < http_error_codes::ok || - response_code >= http_error_codes::multiple_choices) { - utils::error::raise_api_path_error( - function_name, from_api_path + '|' + to_api_path, response_code, - "failed to rename file file"); - return api_error::comm_error; - } - - return get_db().rename_item_meta(from_api_path, to_api_path); + return api_error::error; } auto sia_provider::start(api_item_added_callback api_item_added, i_file_manager *mgr) -> bool { - event_system::instance().raise("sia_provider"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "sia_provider"); sia_config_ = get_config().get_sia_config(); - return base_provider::start(api_item_added, mgr); + auto ret = base_provider::start(api_item_added, mgr); + event_system::instance().raise(function_name, + "sia_provider"); + return ret; } void sia_provider::stop() { - event_system::instance().raise("sia_provider"); + REPERTORY_USES_FUNCTION_NAME(); + + event_system::instance().raise(function_name, + "sia_provider"); base_provider::stop(); - event_system::instance().raise("sia_provider"); + event_system::instance().raise(function_name, + "sia_provider"); } auto sia_provider::upload_file_impl(const std::string &api_path, @@ -663,6 +774,15 @@ auto sia_provider::upload_file_impl(const std::string &api_path, put_file.query["bucket"] = get_bucket(get_sia_config()); put_file.source_path = source_path; + std::string error_data; + put_file.response_handler = [&error_data](auto &&data, long response_code) { + if (response_code == http_error_codes::ok) { + return; + } + + error_data = std::string(data.begin(), data.end()); + }; + long response_code{}; if (not get_comm().make_request(put_file, response_code, stop_requested)) { utils::error::raise_api_path_error(function_name, api_path, source_path, @@ -672,8 +792,9 @@ auto sia_provider::upload_file_impl(const std::string &api_path, } if (response_code != http_error_codes::ok) { - utils::error::raise_api_path_error(function_name, api_path, source_path, - response_code, "failed to upload file"); + utils::error::raise_api_path_error( + function_name, api_path, response_code, + fmt::format("failed to upload file|response|{}", error_data)); return api_error::comm_error; } diff --git a/repertory/librepertory/src/rpc/client/client.cpp b/repertory/librepertory/src/rpc/client/client.cpp index dbde43d1..0210f24b 100644 --- a/repertory/librepertory/src/rpc/client/client.cpp +++ b/repertory/librepertory/src/rpc/client/client.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -26,12 +26,10 @@ #include "utils/utils.hpp" namespace repertory { -client::client(rpc_host_info host_info) : host_info_(std::move(host_info)) { - request_id_ = 0u; -} +client::client(rpc_host_info host_info) : host_info_(std::move(host_info)) {} auto client::get_drive_information() -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Client cli{base_url}; @@ -39,19 +37,26 @@ auto client::get_drive_information() -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_drive_information); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::get_config() -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Client cli{base_url}; @@ -59,19 +64,26 @@ auto client::get_config() -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_config); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::get_config_value_by_name(const std::string &name) -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{{"name", name}}; @@ -81,19 +93,26 @@ auto client::get_config_value_by_name(const std::string &name) -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_config_value_by_name, params, {}); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::get_directory_items(const std::string &api_path) -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{{"api_path", api_path}}; @@ -102,19 +121,26 @@ auto client::get_directory_items(const std::string &api_path) -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_directory_items, params, {}); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::get_open_files() -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Client cli{base_url}; @@ -122,19 +148,26 @@ auto client::get_open_files() -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_open_files); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::get_pinned_files() -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Client cli{base_url}; @@ -142,19 +175,26 @@ auto client::get_pinned_files() -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::get_pinned_files); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } auto client::pin_file(const std::string &api_path) -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{{"api_path", api_path}}; @@ -163,19 +203,26 @@ auto client::pin_file(const std::string &api_path) -> rpc_response { auto resp = cli.Post("/api/v1/" + rpc_method::pin_file, params); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, {}}; + return rpc_response{ + rpc_response_type::success, + {}, + }; } auto client::pinned_status(const std::string &api_path) -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{{"api_path", api_path}}; @@ -184,20 +231,28 @@ auto client::pinned_status(const std::string &api_path) -> rpc_response { auto resp = cli.Get("/api/v1/" + rpc_method::pinned_status, params, {}); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + json::parse(resp->body), + }; } -auto client::set_config_value_by_name( - const std::string &name, const std::string &value) -> rpc_response { - const auto base_url = +auto client::set_config_value_by_name(const std::string &name, + const std::string &value) + -> rpc_response { + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{ @@ -211,20 +266,26 @@ auto client::set_config_value_by_name( auto resp = cli.Post("/api/v1/" + rpc_method::set_config_value_by_name, params); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; }; - return rpc_response{rpc_response_type::success, - nlohmann::json::parse(resp->body)}; + return rpc_response{ + rpc_response_type::success, + nlohmann::json::parse(resp->body), + }; } auto client::unmount() -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Client cli{base_url}; @@ -232,19 +293,26 @@ auto client::unmount() -> rpc_response { auto resp = cli.Post("/api/v1/" + rpc_method::unmount); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, {}}; + return rpc_response{ + rpc_response_type::success, + {}, + }; } auto client::unpin_file(const std::string &api_path) -> rpc_response { - const auto base_url = + auto base_url = "http://" + host_info_.host + ":" + std::to_string(host_info_.port); httplib::Params params{{"api_path", api_path}}; @@ -253,14 +321,21 @@ auto client::unpin_file(const std::string &api_path) -> rpc_response { auto resp = cli.Post("/api/v1/" + rpc_method::unpin_file, params); if (resp.error() != httplib::Error::Success) { - return rpc_response{rpc_response_type::http_error, - {{"error", httplib::to_string(resp.error())}}}; + return rpc_response{ + rpc_response_type::http_error, + {{"error", httplib::to_string(resp.error())}}, + }; } - if (resp->status != 200) { - return rpc_response{rpc_response_type::http_error, - {{"error", std::to_string(resp->status)}}}; + if (resp->status != http_error_codes::ok) { + return rpc_response{ + rpc_response_type::http_error, + {{"error", std::to_string(resp->status)}}, + }; } - return rpc_response{rpc_response_type::success, {}}; + return rpc_response{ + rpc_response_type::success, + {}, + }; } } // namespace repertory diff --git a/repertory/librepertory/src/rpc/server/full_server.cpp b/repertory/librepertory/src/rpc/server/full_server.cpp index 4d903ded..a58b3c30 100644 --- a/repertory/librepertory/src/rpc/server/full_server.cpp +++ b/repertory/librepertory/src/rpc/server/full_server.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,8 @@ #include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/file_pinned.hpp" +#include "events/types/file_unpinned.hpp" #include "file_manager/cache_size_mgr.hpp" #include "file_manager/i_file_manager.hpp" #include "providers/i_provider.hpp" @@ -46,7 +47,7 @@ void full_server::handle_get_directory_items(const httplib::Request &req, }) .dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void full_server::handle_get_drive_information(const httplib::Request & /*req*/, @@ -60,7 +61,7 @@ void full_server::handle_get_drive_information(const httplib::Request & /*req*/, }) .dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void full_server::handle_get_open_files(const httplib::Request & /*req*/, @@ -75,7 +76,7 @@ void full_server::handle_get_open_files(const httplib::Request & /*req*/, })); } res.set_content(open_files.dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void full_server::handle_get_pinned_files(const httplib::Request & /*req*/, @@ -85,7 +86,7 @@ void full_server::handle_get_pinned_files(const httplib::Request & /*req*/, }) .dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void full_server::handle_get_pinned_status(const httplib::Request &req, @@ -99,7 +100,7 @@ void full_server::handle_get_pinned_status(const httplib::Request &req, if (result != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, result, "failed to get pinned status"); - res.status = 500; + res.status = http_error_codes::internal_error; return; } @@ -110,7 +111,7 @@ void full_server::handle_get_pinned_status(const httplib::Request &req, }) .dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void full_server::handle_pin_file(const httplib::Request &req, @@ -124,7 +125,7 @@ void full_server::handle_pin_file(const httplib::Request &req, if (result != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, result, "failed to pin file"); - res.status = 500; + res.status = http_error_codes::internal_error; return; } @@ -135,10 +136,10 @@ void full_server::handle_pin_file(const httplib::Request &req, } if (exists) { - event_system::instance().raise(api_path); + event_system::instance().raise(api_path, function_name); } - res.status = exists ? 200 : 404; + res.status = exists ? http_error_codes::ok : http_error_codes::not_found; } void full_server::handle_unpin_file(const httplib::Request &req, @@ -152,7 +153,7 @@ void full_server::handle_unpin_file(const httplib::Request &req, if (result != api_error::success) { utils::error::raise_api_path_error(function_name, api_path, result, "failed to unpin file"); - res.status = 500; + res.status = http_error_codes::internal_error; return; } @@ -163,10 +164,10 @@ void full_server::handle_unpin_file(const httplib::Request &req, } if (exists) { - event_system::instance().raise(api_path); + event_system::instance().raise(api_path, function_name); } - res.status = exists ? 200 : 404; + res.status = exists ? http_error_codes::ok : http_error_codes::not_found; } void full_server::initialize(httplib::Server &inst) { diff --git a/repertory/librepertory/src/rpc/server/server.cpp b/repertory/librepertory/src/rpc/server/server.cpp index c68f9f39..a98d7428 100644 --- a/repertory/librepertory/src/rpc/server/server.cpp +++ b/repertory/librepertory/src/rpc/server/server.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,14 @@ #include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" +#include "events/types/unmount_requested.hpp" #include "utils/base64.hpp" #include "utils/error_utils.hpp" +#include "utils/string.hpp" namespace repertory { server::server(app_config &config) : config_(config) {} @@ -82,7 +87,7 @@ void server::handle_get_config(const httplib::Request & /*req*/, httplib::Response &res) { auto data = config_.get_json(); res.set_content(data.dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void server::handle_get_config_value_by_name(const httplib::Request &req, @@ -90,7 +95,7 @@ void server::handle_get_config_value_by_name(const httplib::Request &req, auto name = req.get_param_value("name"); auto data = json({{"value", config_.get_value_by_name(name)}}); res.set_content(data.dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void server::handle_set_config_value_by_name(const httplib::Request &req, @@ -100,13 +105,13 @@ void server::handle_set_config_value_by_name(const httplib::Request &req, json data = {{"value", config_.set_value_by_name(name, value)}}; res.set_content(data.dump(), "application/json"); - res.status = 200; + res.status = http_error_codes::ok; } void server::handle_unmount(const httplib::Request & /*req*/, httplib::Response &res) { event_system::instance().raise(); - res.status = 200; + res.status = http_error_codes::ok; } void server::initialize(httplib::Server &inst) { @@ -137,63 +142,75 @@ void server::start() { REPERTORY_USES_FUNCTION_NAME(); mutex_lock lock(start_stop_mutex_); - if (not started_) { - event_system::instance().raise("server"); - server_ = std::make_unique(); - - server_->set_exception_handler([](const httplib::Request &req, - httplib::Response &res, - std::exception_ptr ep) { - json data = {{"path", req.path}}; - - try { - std::rethrow_exception(ep); - } catch (std::exception &e) { - data["error"] = e.what() ? e.what() : "unknown error"; - utils::error::raise_error(function_name, e, - "failed request: " + req.path); - } catch (...) { - data["error"] = "unknown error"; - utils::error::raise_error(function_name, "unknown error", - "failed request: " + req.path); - } - - res.set_content(data.dump(), "application/json"); - res.status = 500; - }); - - server_->set_pre_routing_handler( - [this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse { - if (check_authorization(req)) { - return httplib::Server::HandlerResponse::Unhandled; - } - - res.status = 401; - return httplib::Server::HandlerResponse::Handled; - }); - - initialize(*server_); - - server_thread_ = std::make_unique( - [this]() { server_->listen("127.0.0.1", config_.get_api_port()); }); - - started_ = true; + if (server_thread_) { + return; } + + event_system::instance().raise(function_name, "server"); + + server_ = std::make_unique(); + + server_->set_exception_handler([](const httplib::Request &req, + httplib::Response &res, + std::exception_ptr ptr) { + json data = {{"path", req.path}}; + + try { + std::rethrow_exception(ptr); + } catch (std::exception &e) { + data["error"] = (e.what() == nullptr) ? "unknown error" : e.what(); + utils::error::raise_error(function_name, e, + "failed request: " + req.path); + } catch (...) { + data["error"] = "unknown error"; + utils::error::raise_error(function_name, "unknown error", + "failed request: " + req.path); + } + + res.set_content(data.dump(), "application/json"); + res.status = http_error_codes::internal_error; + }); + + server_->set_pre_routing_handler( + [this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse { + if (check_authorization(req)) { + return httplib::Server::HandlerResponse::Unhandled; + } + + res.status = http_error_codes::unauthorized; + return httplib::Server::HandlerResponse::Handled; + }); + + initialize(*server_); + + server_thread_ = std::make_unique( + [this]() { server_->listen("127.0.0.1", config_.get_api_port()); }); + event_system::instance().raise(function_name, "server"); } void server::stop() { - if (started_) { - mutex_lock l(start_stop_mutex_); - if (started_) { - event_system::instance().raise("server"); + REPERTORY_USES_FUNCTION_NAME(); - server_->stop(); - server_thread_->join(); - server_thread_.reset(); - - started_ = false; - event_system::instance().raise("server"); - } + unique_mutex_lock lock(start_stop_mutex_); + if (not server_thread_) { + return; } + + event_system::instance().raise(function_name, "server"); + + server_->stop(); + + std::unique_ptr thread{nullptr}; + std::swap(thread, server_thread_); + lock.unlock(); + + thread->join(); + thread.reset(); + + lock.lock(); + server_.reset(); + lock.unlock(); + + event_system::instance().raise(function_name, "server"); } } // namespace repertory diff --git a/repertory/librepertory/src/types/remote.cpp b/repertory/librepertory/src/types/remote.cpp index 57e24bf2..71809886 100644 --- a/repertory/librepertory/src/types/remote.cpp +++ b/repertory/librepertory/src/types/remote.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/types/repertory.cpp b/repertory/librepertory/src/types/repertory.cpp index 9bfcee23..ce662556 100644 --- a/repertory/librepertory/src/types/repertory.cpp +++ b/repertory/librepertory/src/types/repertory.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,8 +25,8 @@ #include "utils/string.hpp" namespace repertory { -auto database_type_from_string(std::string type, - database_type default_type) -> database_type { +auto database_type_from_string(std::string type, database_type default_type) + -> database_type { type = utils::string::to_lower(utils::string::trim(type)); if (type == "rocksdb") { return database_type::rocksdb; @@ -50,8 +50,8 @@ auto database_type_to_string(const database_type &type) -> std::string { } } -auto download_type_from_string(std::string type, - download_type default_type) -> download_type { +auto download_type_from_string(std::string type, download_type default_type) + -> download_type { type = utils::string::to_lower(utils::string::trim(type)); if (type == "default") { return download_type::default_; @@ -81,6 +81,54 @@ auto download_type_to_string(const download_type &type) -> std::string { } } +auto event_level_from_string(std::string level, event_level default_level) + -> event_level { + level = utils::string::to_lower(level); + if (level == "critical" || level == "event_level::critical") { + return event_level::critical; + } + + if (level == "debug" || level == "event_level::debug") { + return event_level::debug; + } + + if (level == "warn" || level == "event_level::warn") { + return event_level::warn; + } + + if (level == "info" || level == "event_level::info") { + return event_level::info; + } + + if (level == "error" || level == "event_level::error") { + return event_level::error; + } + + if (level == "trace" || level == "event_level::trace") { + return event_level::trace; + } + + return default_level; +} + +auto event_level_to_string(event_level level) -> std::string { + switch (level) { + case event_level::critical: + return "critical"; + case event_level::debug: + return "debug"; + case event_level::error: + return "error"; + case event_level::info: + return "info"; + case event_level::warn: + return "warn"; + case event_level::trace: + return "trace"; + default: + return "info"; + } +} static const std::unordered_map LOOKUP = { {api_error::success, "success"}, {api_error::access_denied, "access_denied"}, @@ -112,6 +160,7 @@ static const std::unordered_map LOOKUP = { {api_error::item_exists, "item_exists"}, {api_error::item_not_found, "item_not_found"}, {api_error::more_data, "more_data"}, + {api_error::name_too_long, "name_too_long"}, {api_error::no_disk_space, "no_disk_space"}, {api_error::not_implemented, "not_implemented"}, {api_error::not_supported, "not_supported"}, @@ -130,11 +179,8 @@ auto api_error_from_string(std::string_view str) -> api_error { throw startup_exception("undefined api_error strings"); } - const auto iter = std::find_if( - LOOKUP.begin(), LOOKUP.end(), - [&str](const std::pair &item) -> bool { - return item.second == str; - }); + const auto iter = std::ranges::find_if( + LOOKUP, [&str](auto &&item) -> bool { return item.second == str; }); return iter == LOOKUP.end() ? api_error::error : iter->first; } diff --git a/repertory/librepertory/src/utils/cli_utils.cpp b/repertory/librepertory/src/utils/cli_utils.cpp index e3e3bc00..ecd46f85 100644 --- a/repertory/librepertory/src/utils/cli_utils.cpp +++ b/repertory/librepertory/src/utils/cli_utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -69,10 +69,9 @@ void get_api_authentication_data(std::string &user, std::string &password, auto has_option(std::vector args, const std::string &option_name) -> bool { - return std::find_if(args.begin(), args.end(), - [&option_name](const auto &value) -> bool { - return option_name == value; - }) != args.end(); + return std::ranges::find_if(args, [&option_name](auto &&value) -> bool { + return option_name == value; + }) != args.end(); } auto has_option(std::vector args, const option &opt) -> bool { @@ -128,10 +127,9 @@ auto parse_drive_options(std::vector args, std::vector drive_args; for (std::size_t i = 0U; i < args.size(); i++) { const auto &arg = args.at(i); - if (std::find_if(option_list.begin(), option_list.end(), - [&arg](const auto &pair) -> bool { - return ((pair.at(0U) == arg) || (pair.at(1U) == arg)); - }) == option_list.end()) { + if (std::ranges::find_if(option_list, [&arg](auto &&pair) -> bool { + return ((pair.at(0U) == arg) || (pair.at(1U) == arg)); + }) == option_list.end()) { drive_args.emplace_back(args.at(i)); continue; } diff --git a/repertory/librepertory/src/utils/error_utils.cpp b/repertory/librepertory/src/utils/error_utils.cpp index 80acbdcf..b4401e82 100644 --- a/repertory/librepertory/src/utils/error_utils.cpp +++ b/repertory/librepertory/src/utils/error_utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,7 +22,7 @@ #include "utils/error_utils.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/repertory_exception.hpp" #include "types/repertory.hpp" #include "utils/error.hpp" @@ -54,19 +54,19 @@ std::unique_ptr handler{([]() -> auto * { namespace repertory::utils::error { void raise_error(std::string_view function, std::string_view msg) { event_system::instance().raise( - static_cast(function), static_cast(msg)); + function, static_cast(msg)); } void raise_error(std::string_view function, const api_error &err, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|err|" + api_error_to_string(err)); } void raise_error(std::string_view function, const std::exception &exception) { event_system::instance().raise( - static_cast(function), + function, "err|" + std::string(exception.what() == nullptr ? "unknown error" : exception.what())); } @@ -74,7 +74,7 @@ void raise_error(std::string_view function, const std::exception &exception) { void raise_error(std::string_view function, const std::exception &exception, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); } @@ -82,38 +82,35 @@ void raise_error(std::string_view function, const std::exception &exception, void raise_error(std::string_view function, const json &err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|err|" + err.dump(2)); + function, static_cast(msg) + "|err|" + err.dump(2)); } void raise_error(std::string_view function, std::int64_t err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|err|" + std::to_string(err)); + function, static_cast(msg) + "|err|" + std::to_string(err)); } void raise_error(std::string_view function, const api_error &err, std::string_view file_path, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|sp|" + - static_cast(file_path) + "|err|" + - api_error_to_string(err)); + function, static_cast(msg) + "|sp|" + + static_cast(file_path) + "|err|" + + api_error_to_string(err)); } void raise_error(std::string_view function, std::int64_t err, std::string_view file_path, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|sp|" + - static_cast(file_path) + "|err|" + std::to_string(err)); + function, static_cast(msg) + "|sp|" + + static_cast(file_path) + "|err|" + + std::to_string(err)); } void raise_error(std::string_view function, const std::exception &exception, std::string_view file_path, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|sp|" + static_cast(file_path) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); @@ -122,24 +119,23 @@ void raise_error(std::string_view function, const std::exception &exception, void raise_api_path_error(std::string_view function, std::string_view api_path, const api_error &err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|ap|" + - static_cast(api_path) + "|err|" + - api_error_to_string(err)); + function, static_cast(msg) + "|ap|" + + static_cast(api_path) + "|err|" + + api_error_to_string(err)); } void raise_api_path_error(std::string_view function, std::string_view api_path, std::int64_t err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|ap|" + - static_cast(api_path) + "|err|" + std::to_string(err)); + function, static_cast(msg) + "|ap|" + + static_cast(api_path) + "|err|" + + std::to_string(err)); } void raise_api_path_error(std::string_view function, std::string_view api_path, const std::exception &exception) { event_system::instance().raise( - static_cast(function), + function, "ap|" + static_cast(api_path) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); } @@ -148,7 +144,7 @@ void raise_api_path_error(std::string_view function, std::string_view api_path, const std::exception &exception, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|ap|" + static_cast(api_path) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); @@ -158,30 +154,27 @@ void raise_api_path_error(std::string_view function, std::string_view api_path, std::string_view source_path, const api_error &err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|ap|" + - static_cast(api_path) + "|sp|" + - static_cast(source_path) + "|err|" + - api_error_to_string(err)); + function, static_cast(msg) + "|ap|" + + static_cast(api_path) + "|sp|" + + static_cast(source_path) + "|err|" + + api_error_to_string(err)); } void raise_api_path_error(std::string_view function, std::string_view api_path, std::string_view source_path, std::int64_t err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|ap|" + - static_cast(api_path) + "|sp|" + - static_cast(source_path) + "|err|" + - std::to_string(err)); + function, static_cast(msg) + "|ap|" + + static_cast(api_path) + "|sp|" + + static_cast(source_path) + "|err|" + + std::to_string(err)); } void raise_api_path_error(std::string_view function, std::string_view api_path, const json &err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|ap|" + - static_cast(api_path) + "|err|" + err.dump(2)); + function, static_cast(msg) + "|ap|" + + static_cast(api_path) + "|err|" + err.dump(2)); } void raise_api_path_error(std::string_view function, std::string_view api_path, @@ -189,7 +182,7 @@ void raise_api_path_error(std::string_view function, std::string_view api_path, const std::exception &exception, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|ap|" + static_cast(api_path) + "|sp|" + static_cast(source_path) + "|err|" + @@ -199,16 +192,16 @@ void raise_api_path_error(std::string_view function, std::string_view api_path, void raise_url_error(std::string_view function, std::string_view url, CURLcode err, std::string_view msg) { event_system::instance().raise( - static_cast(function), - static_cast(msg) + "|url|" + static_cast(url) + - "|err|" + curl_easy_strerror(err)); + function, static_cast(msg) + "|url|" + + static_cast(url) + "|err|" + + curl_easy_strerror(err)); } void raise_url_error(std::string_view function, std::string_view url, std::string_view source_path, const std::exception &exception) { event_system::instance().raise( - static_cast(function), + function, "url|" + static_cast(url) + "|sp|" + static_cast(source_path) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); @@ -218,7 +211,7 @@ void raise_url_error(std::string_view function, std::string_view url, std::string_view source_path, const std::exception &exception, std::string_view msg) { event_system::instance().raise( - static_cast(function), + function, static_cast(msg) + "|url|" + static_cast(url) + "|sp|" + static_cast(source_path) + "|err|" + (exception.what() == nullptr ? "unknown error" : exception.what())); diff --git a/repertory/librepertory/src/utils/file_utils.cpp b/repertory/librepertory/src/utils/file_utils.cpp index 9a4d891f..74d387f5 100644 --- a/repertory/librepertory/src/utils/file_utils.cpp +++ b/repertory/librepertory/src/utils/file_utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/librepertory/src/utils/polling.cpp b/repertory/librepertory/src/utils/polling.cpp index 0dfdb4a5..127f109e 100644 --- a/repertory/librepertory/src/utils/polling.cpp +++ b/repertory/librepertory/src/utils/polling.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,12 @@ #include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/polling_item_begin.hpp" +#include "events/types/polling_item_end.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "utils/tasks.hpp" namespace repertory { @@ -31,11 +36,13 @@ polling polling::instance_; void polling::frequency_thread( std::function get_frequency_seconds, frequency freq) { - while (not stop_requested_) { + REPERTORY_USES_FUNCTION_NAME(); + + while (not get_stop_requested()) { unique_mutex_lock lock(mutex_); auto futures = std::accumulate( items_.begin(), items_.end(), std::deque{}, - [this, &freq](auto &&list, auto &&item) { + [this, &freq](auto &&list, auto &&item) -> auto { if (item.second.freq != freq) { return list; } @@ -45,12 +52,13 @@ void polling::frequency_thread( if (config_->get_event_level() == event_level::trace || freq != frequency::second) { event_system::instance().raise( - item.first); + function_name, item.first); } item.second.action(task_stopped); if (config_->get_event_level() == event_level::trace || freq != frequency::second) { - event_system::instance().raise(item.first); + event_system::instance().raise( + function_name, item.first); } }, }); @@ -65,7 +73,7 @@ void polling::frequency_thread( futures.pop_front(); } - if (stop_requested_) { + if (get_stop_requested()) { return; } @@ -74,6 +82,10 @@ void polling::frequency_thread( } } +auto polling::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + void polling::remove_callback(const std::string &name) { mutex_lock lock(mutex_); items_.erase(name); @@ -85,12 +97,14 @@ void polling::set_callback(const polling_item &item) { } void polling::start(app_config *config) { + REPERTORY_USES_FUNCTION_NAME(); + mutex_lock lock(start_stop_mutex_); if (frequency_threads_.at(0U)) { return; } - event_system::instance().raise("polling"); + event_system::instance().raise(function_name, "polling"); config_ = config; stop_requested_ = false; @@ -129,28 +143,36 @@ void polling::start(app_config *config) { this->frequency_thread([]() -> std::uint32_t { return 1U; }, frequency::second); }); + event_system::instance().raise(function_name, "polling"); } void polling::stop() { + REPERTORY_USES_FUNCTION_NAME(); + mutex_lock lock(start_stop_mutex_); if (not frequency_threads_.at(0U)) { return; } - event_system::instance().raise("polling"); + event_system::instance().raise(function_name, "polling"); + stop_requested_ = true; tasks::instance().stop(); unique_mutex_lock thread_lock(mutex_); + std::array, + static_cast(frequency::size)> + threads; + std::swap(threads, frequency_threads_); notify_.notify_all(); thread_lock.unlock(); - for (auto &&thread : frequency_threads_) { + for (auto &thread : threads) { thread->join(); thread.reset(); } - event_system::instance().raise("polling"); + event_system::instance().raise(function_name, "polling"); } } // namespace repertory diff --git a/repertory/librepertory/src/utils/single_thread_service_base.cpp b/repertory/librepertory/src/utils/single_thread_service_base.cpp index 7eab1931..47da2fd6 100644 --- a/repertory/librepertory/src/utils/single_thread_service_base.cpp +++ b/repertory/librepertory/src/utils/single_thread_service_base.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,45 +21,70 @@ */ #include "utils/single_thread_service_base.hpp" +#include "app_config.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "types/repertory.hpp" namespace repertory { +auto single_thread_service_base::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + void single_thread_service_base::notify_all() const { mutex_lock lock(get_mutex()); notify_.notify_all(); } void single_thread_service_base::start() { + REPERTORY_USES_FUNCTION_NAME(); + mutex_lock lock(mtx_); - if (not thread_) { - stop_requested_ = false; - on_start(); - thread_ = std::make_unique([this]() { - event_system::instance().raise(service_name_); - while (not stop_requested_) { - service_function(); - } - }); + if (thread_) { + return; } + + stop_requested_ = false; + on_start(); + thread_ = std::make_unique([this]() { + event_system::instance().raise(function_name, + service_name_); + event_system::instance().raise(function_name, + service_name_); + while (not get_stop_requested()) { + service_function(); + } + }); } void single_thread_service_base::stop() { - if (thread_) { - event_system::instance().raise(service_name_); - unique_mutex_lock lock(mtx_); - if (thread_) { - stop_requested_ = true; - notify_.notify_all(); - lock.unlock(); + REPERTORY_USES_FUNCTION_NAME(); - thread_->join(); - thread_.reset(); - - on_stop(); - } - event_system::instance().raise(service_name_); + unique_mutex_lock lock(mtx_); + if (not thread_) { + return; } + + event_system::instance().raise(function_name, + service_name_); + + stop_requested_ = true; + + std::unique_ptr thread{nullptr}; + std::swap(thread, thread_); + + notify_.notify_all(); + lock.unlock(); + + thread->join(); + thread.reset(); + + on_stop(); + + event_system::instance().raise(function_name, + service_name_); } } // namespace repertory diff --git a/repertory/librepertory/src/utils/tasks.cpp b/repertory/librepertory/src/utils/tasks.cpp index d218a08a..f2184bc6 100644 --- a/repertory/librepertory/src/utils/tasks.cpp +++ b/repertory/librepertory/src/utils/tasks.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,10 @@ namespace repertory { tasks tasks::instance_; +auto tasks::get_stop_requested() const -> bool { + return stop_requested_ || app_config::get_stop_requested(); +} + void tasks::task_wait::set_result(bool result) { unique_mutex_lock lock(mtx); if (complete) { @@ -50,7 +54,7 @@ auto tasks::task_wait::wait() const -> bool { auto tasks::schedule(task item) -> task_ptr { ++count_; - while (not stop_requested_ && (count_ >= task_threads_.size())) { + while (not get_stop_requested() && (count_ >= task_threads_.size())) { std::this_thread::sleep_for( std::chrono::milliseconds(config_->get_task_wait_ms())); } @@ -58,7 +62,7 @@ auto tasks::schedule(task item) -> task_ptr { scheduled_task runnable{item}; unique_mutex_lock lock(mutex_); - if (stop_requested_) { + if (get_stop_requested()) { runnable.wait->set_result(false); notify_.notify_all(); return runnable.wait; @@ -80,7 +84,7 @@ void tasks::start(app_config *config) { stop_requested_ = false; tasks_.clear(); - for (std::uint32_t idx = 0U; idx < std::thread::hardware_concurrency(); + for (std::uint32_t idx = 0U; idx < std::thread::hardware_concurrency() * 2U; ++idx) { task_threads_.emplace_back( std::make_unique([this]() { task_thread(); })); @@ -96,15 +100,17 @@ void tasks::stop() { stop_requested_ = true; unique_mutex_lock lock(mutex_); + std::vector> threads; + std::swap(threads, task_threads_); + + std::deque task_list; + std::swap(task_list, tasks_); + notify_.notify_all(); lock.unlock(); - task_threads_.clear(); - - lock.lock(); - tasks_.clear(); - notify_.notify_all(); - lock.unlock(); + threads.clear(); + task_list.clear(); } void tasks::task_thread() { @@ -119,14 +125,14 @@ void tasks::task_thread() { release(); - while (not stop_requested_) { + while (not get_stop_requested()) { lock.lock(); - while (not stop_requested_ && tasks_.empty()) { + while (not get_stop_requested() && tasks_.empty()) { notify_.wait(lock); } - if (stop_requested_) { + if (get_stop_requested()) { release(); return; } diff --git a/repertory/librepertory/src/utils/throttle.cpp b/repertory/librepertory/src/utils/throttle.cpp deleted file mode 100644 index 39078fe8..00000000 --- a/repertory/librepertory/src/utils/throttle.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright <2018-2024> - - 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 "utils/throttle.hpp" - -#include "types/repertory.hpp" - -namespace repertory { -void throttle::decrement() { - mutex_lock l(mutex_); - if (not shutdown_) { - if (count_ > 0) { - count_--; - } - notify_.notify_one(); - } -} - -void throttle::increment_or_wait() { - unique_mutex_lock l(mutex_); - if (not shutdown_) { - if (count_ >= max_size_) { - notify_.wait(l); - } - if (not shutdown_) { - count_++; - } - } -} - -void throttle::reset() { - unique_mutex_lock l(mutex_); - if (shutdown_) { - count_ = 0; - shutdown_ = false; - } -} - -void throttle::shutdown() { - if (not shutdown_) { - unique_mutex_lock l(mutex_); - shutdown_ = true; - notify_.notify_all(); - } -} -} // namespace repertory diff --git a/repertory/librepertory/src/utils/timeout.cpp b/repertory/librepertory/src/utils/timeout.cpp index 72221b19..60d19257 100644 --- a/repertory/librepertory/src/utils/timeout.cpp +++ b/repertory/librepertory/src/utils/timeout.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,34 +21,37 @@ */ #include "utils/timeout.hpp" -#include "types/repertory.hpp" - namespace repertory { timeout::timeout(std::function timeout_callback, - const std::chrono::system_clock::duration &duration) + std::chrono::system_clock::duration duration) : timeout_killed_(duration == 0s) { - if (not timeout_killed_) { - timeout_thread_ = - std::make_unique([this, duration, timeout_callback]() { - unique_mutex_lock lock(timeout_mutex_); - if (not timeout_killed_) { - timeout_notify_.wait_for(lock, duration); - if (not timeout_killed_) { - timeout_callback(); - } - } - }); + if (timeout_killed_) { + return; } + + timeout_thread_ = + std::make_unique([this, duration, timeout_callback]() { + unique_mutex_lock lock(timeout_mutex_); + if (not timeout_killed_) { + timeout_notify_.wait_for(lock, duration); + if (not timeout_killed_) { + timeout_callback(); + } + } + }); } void timeout::disable() { - if (not timeout_killed_) { - timeout_killed_ = true; - unique_mutex_lock lock(timeout_mutex_); - timeout_notify_.notify_all(); - lock.unlock(); - timeout_thread_->join(); - timeout_thread_.reset(); + if (timeout_killed_) { + return; } + + timeout_killed_ = true; + unique_mutex_lock lock(timeout_mutex_); + timeout_notify_.notify_all(); + lock.unlock(); + + timeout_thread_->join(); + timeout_thread_.reset(); } } // namespace repertory diff --git a/repertory/librepertory/src/utils/unix/unix_utils.cpp b/repertory/librepertory/src/utils/unix/unix_utils.cpp index d91e4834..4e204fc9 100644 --- a/repertory/librepertory/src/utils/unix/unix_utils.cpp +++ b/repertory/librepertory/src/utils/unix/unix_utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -58,6 +58,8 @@ auto from_api_error(const api_error &err) -> int { return -EINVAL; case api_error::item_not_found: return -ENOENT; + case api_error::name_too_long: + return -ENAMETOOLONG; case api_error::out_of_memory: return -ENOMEM; case api_error::no_disk_space: @@ -128,6 +130,8 @@ auto to_api_error(int err) -> api_error { return api_error::file_in_use; case EINVAL: return api_error::invalid_operation; + case ENAMETOOLONG: + return api_error::name_too_long; case ENOENT: return api_error::item_not_found; case ENOMEM: diff --git a/repertory/librepertory/src/utils/utils.cpp b/repertory/librepertory/src/utils/utils.cpp index 44ef5f1b..9949ef0b 100644 --- a/repertory/librepertory/src/utils/utils.cpp +++ b/repertory/librepertory/src/utils/utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,6 +19,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "rocksdb/table.h" + #include "utils/utils.hpp" #include "app_config.hpp" @@ -38,12 +40,9 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, return; } - if (file_size > allocation_size) { - allocation_size = file_size; - } - allocation_size = - utils::divide_with_ceiling(allocation_size, WINFSP_ALLOCATION_UNIT) * + utils::divide_with_ceiling(std::max(file_size, allocation_size), + WINFSP_ALLOCATION_UNIT) * WINFSP_ALLOCATION_UNIT; allocation_meta_size = std::to_string(allocation_size); } @@ -51,14 +50,14 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size, auto create_rocksdb( const app_config &cfg, const std::string &name, const std::vector &families, - std::vector &handles, - bool clear) -> std::unique_ptr { + std::vector &handles, bool clear) + -> std::unique_ptr { REPERTORY_USES_FUNCTION_NAME(); auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"}); if (not utils::file::directory{db_dir}.create_directory()) { throw startup_exception( - fmt::format("failed to create db directory|", db_dir)); + fmt::format("failed to create db directory|{}", db_dir)); } auto path = utils::path::combine(db_dir, {name}); @@ -77,8 +76,8 @@ auto create_rocksdb( auto status = rocksdb::TransactionDB::Open( options, rocksdb::TransactionDBOptions{}, path, families, &handles, &ptr); if (not status.ok()) { - throw startup_exception(fmt::format("failed to open rocksdb|path{}|error{}", - path, status.ToString())); + throw startup_exception(fmt::format( + "failed to open rocksdb|path|{}|error{}", path, status.ToString())); } return std::unique_ptr(ptr); diff --git a/repertory/librepertory/src/utils/windows/windows_utils.cpp b/repertory/librepertory/src/utils/windows/windows_utils.cpp index 73888b98..cccde872 100644 --- a/repertory/librepertory/src/utils/windows/windows_utils.cpp +++ b/repertory/librepertory/src/utils/windows/windows_utils.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -65,6 +65,8 @@ auto from_api_error(const api_error &e) -> NTSTATUS { return STATUS_CLIENT_SERVER_PARAMETERS_INVALID; case api_error::item_not_found: return STATUS_OBJECT_NAME_NOT_FOUND; + case api_error::name_too_long: + return STATUS_NAME_TOO_LONG; case api_error::no_disk_space: return STATUS_DEVICE_INSUFFICIENT_RESOURCES; case api_error::os_error: diff --git a/repertory/repertory/include/cli/actions.hpp b/repertory/repertory/include/cli/actions.hpp index ae020202..a5275118 100644 --- a/repertory/repertory/include/cli/actions.hpp +++ b/repertory/repertory/include/cli/actions.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/check_version.hpp b/repertory/repertory/include/cli/check_version.hpp index f8aaaac5..cc2d0ab4 100644 --- a/repertory/repertory/include/cli/check_version.hpp +++ b/repertory/repertory/include/cli/check_version.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/display_config.hpp b/repertory/repertory/include/cli/display_config.hpp index eb8542e1..d41fce29 100644 --- a/repertory/repertory/include/cli/display_config.hpp +++ b/repertory/repertory/include/cli/display_config.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/drive_information.hpp b/repertory/repertory/include/cli/drive_information.hpp index fa6d3fb4..71acb9c0 100644 --- a/repertory/repertory/include/cli/drive_information.hpp +++ b/repertory/repertory/include/cli/drive_information.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/get.hpp b/repertory/repertory/include/cli/get.hpp index 70d43a16..8972f140 100644 --- a/repertory/repertory/include/cli/get.hpp +++ b/repertory/repertory/include/cli/get.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/get_directory_items.hpp b/repertory/repertory/include/cli/get_directory_items.hpp index 0d65138e..aaa6e3a1 100644 --- a/repertory/repertory/include/cli/get_directory_items.hpp +++ b/repertory/repertory/include/cli/get_directory_items.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/get_pinned_files.hpp b/repertory/repertory/include/cli/get_pinned_files.hpp index ecb09e88..35599b2f 100644 --- a/repertory/repertory/include/cli/get_pinned_files.hpp +++ b/repertory/repertory/include/cli/get_pinned_files.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/get_version.hpp b/repertory/repertory/include/cli/get_version.hpp index 7a64944f..5f2427e1 100644 --- a/repertory/repertory/include/cli/get_version.hpp +++ b/repertory/repertory/include/cli/get_version.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,7 @@ namespace repertory::cli::actions { template inline void version(std::vector args) { std::cout << "Repertory core version: " << project_get_version() << std::endl; - std::cout << "Repertory Git revision: " << project_get_git_rev() << std::endl; + std::cout << "Repertory git revision: " << project_get_git_rev() << std::endl; drive::display_version_information(args); } } // namespace repertory::cli::actions diff --git a/repertory/repertory/include/cli/help.hpp b/repertory/repertory/include/cli/help.hpp index a71ef876..86c2cf54 100644 --- a/repertory/repertory/include/cli/help.hpp +++ b/repertory/repertory/include/cli/help.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/mount.hpp b/repertory/repertory/include/cli/mount.hpp index f9de39d1..e4ef7ce5 100644 --- a/repertory/repertory/include/cli/mount.hpp +++ b/repertory/repertory/include/cli/mount.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ using repertory_drive = repertory::winfsp_drive; using remote_client = repertory::remote_winfsp::remote_client; using remote_drive = repertory::remote_winfsp::remote_winfsp_drive; using remote_instance = repertory::remote_winfsp::i_remote_instance; -#else +#else // !defined(_WIN32) #include "drives/fuse/fuse_drive.hpp" #include "drives/fuse/remotefuse/remote_client.hpp" #include "drives/fuse/remotefuse/remote_fuse_drive.hpp" @@ -50,7 +50,7 @@ using repertory_drive = repertory::fuse_drive; using remote_client = repertory::remote_fuse::remote_client; using remote_drive = repertory::remote_fuse::remote_fuse_drive; using remote_instance = repertory::remote_fuse::i_remote_instance; -#endif +#endif // defined(_WIN32) namespace repertory::cli::actions { [[nodiscard]] inline auto @@ -77,7 +77,8 @@ mount(std::vector args, std::string data_directory, config.set_remote_config(cfg); } else if (prov == provider_type::sia && config.get_sia_config().bucket.empty()) { - config.set_value_by_name("SiaConfig.Bucket", unique_id); + [[maybe_unused]] auto bucket = + config.set_value_by_name("SiaConfig.Bucket", unique_id); } std::cout << "Generated " << app_config::get_provider_display_name(prov) @@ -157,7 +158,8 @@ mount(std::vector args, std::string data_directory, } else { if (prov == provider_type::sia && config.get_sia_config().bucket.empty()) { - config.set_value_by_name("SiaConfig.Bucket", unique_id); + [[maybe_unused]] auto bucket = + config.set_value_by_name("SiaConfig.Bucket", unique_id); } try { diff --git a/repertory/repertory/include/cli/open_files.hpp b/repertory/repertory/include/cli/open_files.hpp index f69a18ab..d72179ec 100644 --- a/repertory/repertory/include/cli/open_files.hpp +++ b/repertory/repertory/include/cli/open_files.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/pin_file.hpp b/repertory/repertory/include/cli/pin_file.hpp index f561cc2b..9f049732 100644 --- a/repertory/repertory/include/cli/pin_file.hpp +++ b/repertory/repertory/include/cli/pin_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/pinned_status.hpp b/repertory/repertory/include/cli/pinned_status.hpp index 6eae0db2..ec3346a1 100644 --- a/repertory/repertory/include/cli/pinned_status.hpp +++ b/repertory/repertory/include/cli/pinned_status.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/set.hpp b/repertory/repertory/include/cli/set.hpp index a4c755ca..f328439e 100644 --- a/repertory/repertory/include/cli/set.hpp +++ b/repertory/repertory/include/cli/set.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/status.hpp b/repertory/repertory/include/cli/status.hpp index 26a47b33..dd9651cf 100644 --- a/repertory/repertory/include/cli/status.hpp +++ b/repertory/repertory/include/cli/status.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/unmount.hpp b/repertory/repertory/include/cli/unmount.hpp index f84d3fdc..604b0ec4 100644 --- a/repertory/repertory/include/cli/unmount.hpp +++ b/repertory/repertory/include/cli/unmount.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/include/cli/unpin_file.hpp b/repertory/repertory/include/cli/unpin_file.hpp index 2867ec75..3cd2ce84 100644 --- a/repertory/repertory/include/cli/unpin_file.hpp +++ b/repertory/repertory/include/cli/unpin_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory/main.cpp b/repertory/repertory/main.cpp index f7ce26b6..f31c23fb 100644 --- a/repertory/repertory/main.cpp +++ b/repertory/repertory/main.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/fixtures/file_db_fixture.hpp b/repertory/repertory_test/include/fixtures/file_db_fixture.hpp index f358780c..d18e79f1 100644 --- a/repertory/repertory_test/include/fixtures/file_db_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/file_db_fixture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -42,6 +42,7 @@ protected: static std::uint64_t idx{}; event_system::instance().start(); + auto cfg_directory = utils::path::combine(test::get_test_output_dir(), { "file_db_test", diff --git a/repertory/repertory_test/include/fixtures/file_mgr_db_fixture.hpp b/repertory/repertory_test/include/fixtures/file_mgr_db_fixture.hpp index f7174421..0e70f18b 100644 --- a/repertory/repertory_test/include/fixtures/file_mgr_db_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/file_mgr_db_fixture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -42,6 +42,7 @@ protected: static std::uint64_t idx{}; event_system::instance().start(); + auto cfg_directory = utils::path::combine(test::get_test_output_dir(), { "file_mgr_db_test", diff --git a/repertory/repertory_test/include/fixtures/fuse_fixture.hpp b/repertory/repertory_test/include/fixtures/fuse_fixture.hpp index 5eeb981b..a8298269 100644 --- a/repertory/repertory_test/include/fixtures/fuse_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/fuse_fixture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -45,7 +45,8 @@ #endif namespace { -std::atomic idx{0U}; +std::atomic provider_idx{0U}; + constexpr const auto SLEEP_SECONDS{1.5s}; } // namespace @@ -126,6 +127,7 @@ protected: }); } + config->set_database_type(database_type::sqlite); meta = create_meta_db(*config); execute_mount(drive_args, mount_location); }; @@ -171,6 +173,7 @@ protected: }); } + config->set_database_type(database_type::sqlite); meta = create_meta_db(*config); execute_mount(drive_args, mount_location); }; @@ -197,6 +200,7 @@ protected: std::make_unique(provider_type::remote, cfg_directory); config2->set_enable_drive_events(true); config2->set_event_level(event_level::trace); + config2->set_database_type(database_type::sqlite); drive_args2 = std::vector({ "-dd", @@ -259,14 +263,14 @@ protected: public: static auto create_file_path(std::string &file_name) { - file_name += std::to_string(++idx); + file_name += std::to_string(++provider_idx); auto file_path = utils::path::combine(mount_location, {file_name}); return file_path; } - static auto create_file_and_test(std::string &file_name, mode_t perms) - -> std::string { - file_name += std::to_string(++idx); + static auto create_file_and_test(std::string &file_name, + mode_t perms) -> std::string { + file_name += std::to_string(++provider_idx); auto file_path = utils::path::combine(mount_location, {file_name}); auto handle = open(file_path.c_str(), O_CREAT | O_EXCL | O_RDWR, perms); @@ -283,7 +287,7 @@ public: EXPECT_TRUE(utils::file::file(file_path).exists()); EXPECT_FALSE(utils::file::directory(file_path).exists()); - struct stat64 unix_st{}; + struct stat64 unix_st {}; EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st)); EXPECT_EQ(getgid(), unix_st.st_gid); EXPECT_EQ(getuid(), unix_st.st_uid); @@ -295,9 +299,9 @@ public: return create_file_and_test(file_name, ACCESSPERMS); } - static auto create_directory_and_test(std::string &dir_name, mode_t perms) - -> std::string { - dir_name += std::to_string(++idx); + static auto create_directory_and_test(std::string &dir_name, + mode_t perms) -> std::string { + dir_name += std::to_string(++provider_idx); auto dir_path = utils::path::combine(mount_location, {dir_name}); mkdir(dir_path.c_str(), perms); @@ -305,7 +309,7 @@ public: EXPECT_TRUE(utils::file::directory(dir_path).exists()); EXPECT_FALSE(utils::file::file(dir_path).exists()); - struct stat64 unix_st{}; + struct stat64 unix_st {}; EXPECT_EQ(0, stat64(dir_path.c_str(), &unix_st)); EXPECT_EQ(getgid(), unix_st.st_gid); EXPECT_EQ(getuid(), unix_st.st_uid); diff --git a/repertory/repertory_test/include/fixtures/meta_db_fixture.hpp b/repertory/repertory_test/include/fixtures/meta_db_fixture.hpp index e09e50a7..0ecef279 100644 --- a/repertory/repertory_test/include/fixtures/meta_db_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/meta_db_fixture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -42,6 +42,7 @@ protected: static std::uint64_t idx{}; event_system::instance().start(); + auto cfg_directory = utils::path::combine(test::get_test_output_dir(), { "meta_db_test", diff --git a/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp b/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp index 6a910660..70ab4048 100644 --- a/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp +++ b/repertory/repertory_test/include/fixtures/winfsp_fixture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp index 45d3ed44..d01d1eec 100644 --- a/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_fuse_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/mocks/mock_open_file.hpp b/repertory/repertory_test/include/mocks/mock_open_file.hpp index 305ed853..32e7a40c 100644 --- a/repertory/repertory_test/include/mocks/mock_open_file.hpp +++ b/repertory/repertory_test/include/mocks/mock_open_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/mocks/mock_provider.hpp b/repertory/repertory_test/include/mocks/mock_provider.hpp index e398afda..ca8e28ba 100644 --- a/repertory/repertory_test/include/mocks/mock_provider.hpp +++ b/repertory/repertory_test/include/mocks/mock_provider.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/mocks/mock_upload_manager.hpp b/repertory/repertory_test/include/mocks/mock_upload_manager.hpp index 5c02a58b..4ab7671e 100644 --- a/repertory/repertory_test/include/mocks/mock_upload_manager.hpp +++ b/repertory/repertory_test/include/mocks/mock_upload_manager.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp index 4e14155b..021422fc 100644 --- a/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp +++ b/repertory/repertory_test/include/mocks/mock_winfsp_drive.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -42,9 +42,8 @@ private: std::string mount_location_; public: - [[nodiscard]] auto - get_directory_item_count(const std::string & /*api_path*/) const - -> std::uint64_t override { + [[nodiscard]] auto get_directory_item_count( + const std::string & /*api_path*/) const -> std::uint64_t override { return 1; } @@ -85,10 +84,10 @@ public: return api_error::error; } - auto get_security_by_name(PWSTR /*file_name*/, PUINT32 attributes, - PSECURITY_DESCRIPTOR descriptor, - std::uint64_t *descriptor_size) - -> NTSTATUS override { + auto + get_security_by_name(PWSTR /*file_name*/, PUINT32 attributes, + PSECURITY_DESCRIPTOR descriptor, + std::uint64_t *descriptor_size) -> NTSTATUS override { auto ret = STATUS_SUCCESS; if (attributes != nullptr) { @@ -135,9 +134,9 @@ public: volume_label = "TestVolumeLabel"; } - auto populate_file_info(const std::string &api_path, - remote::file_info &file_info) const - -> api_error override { + auto + populate_file_info(const std::string &api_path, + remote::file_info &file_info) const -> api_error override { auto file_path = utils::path::combine(mount_location_, {api_path}); auto directory = utils::file::directory(file_path).exists(); auto attributes = diff --git a/repertory/repertory_test/include/test_common.hpp b/repertory/repertory_test/include/test_common.hpp index d6b5d584..c792396f 100644 --- a/repertory/repertory_test/include/test_common.hpp +++ b/repertory/repertory_test/include/test_common.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,6 @@ REPERTORY_IGNORE_WARNINGS_DISABLE() #include "events/consumers/console_consumer.hpp" #include "events/event_system.hpp" -#include "events/events.hpp" +#include "events/i_event.hpp" #endif // REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_ diff --git a/repertory/repertory_test/include/utils/event_capture.hpp b/repertory/repertory_test/include/utils/event_capture.hpp index 42d4d55b..7030039f 100644 --- a/repertory/repertory_test/include/utils/event_capture.hpp +++ b/repertory/repertory_test/include/utils/event_capture.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -32,8 +32,9 @@ class event_capture final { E_CONSUMER(); public: - explicit event_capture(std::vector event_names, - std::vector non_fired_event_names = {}) + explicit event_capture( + std::vector event_names, + std::vector non_fired_event_names = {}) : event_names_(std::move(event_names)), non_fired_event_names_(std::move(non_fired_event_names)) { E_SUBSCRIBE_ALL(process_event); @@ -51,56 +52,55 @@ public: } private: - std::vector event_names_; - std::vector fired_event_names_; - std::vector non_fired_event_names_; + std::vector event_names_; + std::vector fired_event_names_; + std::vector non_fired_event_names_; std::mutex mutex_; std::condition_variable notify_; public: - void process_event(const event &event) { - unique_mutex_lock l(mutex_); + void process_event(const i_event &event) { + unique_mutex_lock lock(mutex_); utils::collection::remove_element(event_names_, event.get_name()); fired_event_names_.emplace_back(event.get_name()); notify_.notify_all(); - l.unlock(); + lock.unlock(); for (size_t i = 0; i < non_fired_event_names_.size(); i++) { - const auto it = std::find(non_fired_event_names_.begin(), - non_fired_event_names_.end(), event.get_name()); - EXPECT_EQ(non_fired_event_names_.end(), it); - if (it != non_fired_event_names_.end()) { - std::cerr << '\t' << *it << std::endl; + const auto iter = + std::ranges::find(non_fired_event_names_, event.get_name()); + EXPECT_EQ(non_fired_event_names_.end(), iter); + if (iter != non_fired_event_names_.end()) { + std::cerr << '\t' << *iter << std::endl; } } } void wait_for_empty() { const auto start_time = std::chrono::system_clock::now(); - unique_mutex_lock l(mutex_); + unique_mutex_lock lock(mutex_); while (not event_names_.empty() && (std::chrono::duration_cast( std::chrono::system_clock::now() - start_time) .count() < 10)) { - notify_.wait_for(l, 1s); + notify_.wait_for(lock, 1s); } - l.unlock(); + lock.unlock(); } [[nodiscard]] auto wait_for_event(const std::string &event_name) -> bool { auto missing = true; const auto start_time = std::chrono::system_clock::now(); - unique_mutex_lock l(mutex_); + unique_mutex_lock lock(mutex_); while ((std::chrono::duration_cast( std::chrono::system_clock::now() - start_time) .count() < 10) && - (missing = - (std::find(fired_event_names_.begin(), fired_event_names_.end(), - event_name) == fired_event_names_.end()))) { - notify_.wait_for(l, 1s); + (missing = (std::ranges::find(fired_event_names_, event_name) == + fired_event_names_.end()))) { + notify_.wait_for(lock, 1s); } - l.unlock(); + lock.unlock(); return not missing; } }; diff --git a/repertory/repertory_test/main.cpp b/repertory/repertory_test/main.cpp index 37820cbe..4b07986c 100644 --- a/repertory/repertory_test/main.cpp +++ b/repertory/repertory_test/main.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/atomic_test.cpp b/repertory/repertory_test/src/atomic_test.cpp index ef782f88..58df0484 100644 --- a/repertory/repertory_test/src/atomic_test.cpp +++ b/repertory/repertory_test/src/atomic_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/config_test.cpp b/repertory/repertory_test/src/config_test.cpp index 446dafd5..2cd440a8 100644 --- a/repertory/repertory_test/src/config_test.cpp +++ b/repertory/repertory_test/src/config_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -54,7 +54,9 @@ public: event_system::instance().start(); } - void TearDown() override { event_system::instance().stop(); } + void TearDown() override { + event_system::instance().stop(); + } }; std::atomic config_test::idx{0U}; diff --git a/repertory/repertory_test/src/curl_comm_test.cpp b/repertory/repertory_test/src/curl_comm_test.cpp index 60c86e5b..30bb9be6 100644 --- a/repertory/repertory_test/src/curl_comm_test.cpp +++ b/repertory/repertory_test/src/curl_comm_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/direct_open_file_test.cpp b/repertory/repertory_test/src/direct_open_file_test.cpp index de9ebc53..97dbc5ef 100644 --- a/repertory/repertory_test/src/direct_open_file_test.cpp +++ b/repertory/repertory_test/src/direct_open_file_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -35,9 +35,13 @@ public: mock_provider provider; protected: - void SetUp() override { event_system::instance().start(); } + void SetUp() override { + event_system::instance().start(); + } - void TearDown() override { event_system::instance().stop(); } + void TearDown() override { + event_system::instance().stop(); + } }; TEST_F(direct_open_file_test, read_full_file) { diff --git a/repertory/repertory_test/src/file_db_test.cpp b/repertory/repertory_test/src/file_db_test.cpp index a7026b1f..3f3b6ed3 100644 --- a/repertory/repertory_test/src/file_db_test.cpp +++ b/repertory/repertory_test/src/file_db_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,10 @@ #include "fixtures/file_db_fixture.hpp" +namespace { +const auto get_stop_requested = []() -> bool { return false; }; +} // namespace + namespace repertory { TYPED_TEST_CASE(file_db_test, file_db_types); @@ -30,12 +34,15 @@ TYPED_TEST(file_db_test, can_add_and_remove_directory) { EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); - auto list = this->file_db->get_item_list(); + auto list = this->file_db->get_item_list(get_stop_requested); EXPECT_EQ(1U, list.size()); + EXPECT_STREQ("/", list.at(0U).api_path.c_str()); + EXPECT_TRUE(list.at(0U).directory); + EXPECT_STREQ("c:\\test", list.at(0U).source_path.c_str()); EXPECT_EQ(api_error::success, this->file_db->remove_item("/")); - list = this->file_db->get_item_list(); + list = this->file_db->get_item_list(get_stop_requested); EXPECT_EQ(0U, list.size()); } @@ -49,12 +56,15 @@ TYPED_TEST(file_db_test, can_add_and_remove_file) { "c:\\test\\file.txt", })); - auto list = this->file_db->get_item_list(); + auto list = this->file_db->get_item_list(get_stop_requested); EXPECT_EQ(1U, list.size()); + EXPECT_STREQ("/file", list.at(0U).api_path.c_str()); + EXPECT_FALSE(list.at(0U).directory); + EXPECT_STREQ("c:\\test\\file.txt", list.at(0U).source_path.c_str()); EXPECT_EQ(api_error::success, this->file_db->remove_item("/file")); - list = this->file_db->get_item_list(); + list = this->file_db->get_item_list(get_stop_requested); EXPECT_EQ(0U, list.size()); } @@ -329,4 +339,30 @@ TYPED_TEST(file_db_test, item_not_found_is_returned_for_non_existing_api_path) { this->file_db->get_source_path("/file", source_path)); EXPECT_TRUE(source_path.empty()); } + +TYPED_TEST(file_db_test, can_enumerate_item_list) { + this->file_db->clear(); + + EXPECT_EQ(api_error::success, + this->file_db->add_directory("/", std::filesystem::current_path().string())); + EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ + "/file", + 0U, + {}, + "c:\\test\\file.txt", + })); + + auto call_count{0U}; + const auto get_stop_requested = []() -> bool { return false; }; + + this->file_db->enumerate_item_list( + [&call_count](auto &&list) { + EXPECT_EQ(std::size_t(2U), list.size()); + ++call_count; + }, + get_stop_requested); + + EXPECT_EQ(std::size_t(1U), call_count); +} + } // namespace repertory diff --git a/repertory/repertory_test/src/file_manager_test.cpp b/repertory/repertory_test/src/file_manager_test.cpp index 39c23e73..eb0f7024 100644 --- a/repertory/repertory_test/src/file_manager_test.cpp +++ b/repertory/repertory_test/src/file_manager_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,8 +22,21 @@ #include "test_common.hpp" #include "app_config.hpp" +#include "events/types/download_restored.hpp" +#include "events/types/download_resume_added.hpp" +#include "events/types/download_resume_removed.hpp" +#include "events/types/file_upload_completed.hpp" +#include "events/types/file_upload_queued.hpp" +#include "events/types/filesystem_item_closed.hpp" +#include "events/types/filesystem_item_handle_closed.hpp" +#include "events/types/filesystem_item_handle_opened.hpp" +#include "events/types/filesystem_item_opened.hpp" +#include "events/types/item_timeout.hpp" +#include "events/types/service_start_begin.hpp" +#include "events/types/service_start_end.hpp" +#include "events/types/service_stop_begin.hpp" +#include "events/types/service_stop_end.hpp" #include "file_manager/cache_size_mgr.hpp" -#include "file_manager/events.hpp" #include "file_manager/file_manager.hpp" #include "file_manager/i_open_file.hpp" #include "mocks/mock_open_file.hpp" @@ -80,23 +93,28 @@ std::atomic file_manager_test::inst{0U}; TEST_F(file_manager_test, can_start_and_stop) { EXPECT_CALL(mp, is_read_only()).WillRepeatedly(Return(false)); - event_consumer consumer("service_started", [](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("file_manager", evt2.get_service().get().c_str()); + event_consumer consumer(service_start_begin::name, [](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("file_manager", evt2.service_name.c_str()); }); - event_consumer consumer2("service_shutdown_begin", [](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("file_manager", evt2.get_service().get().c_str()); + event_consumer consumer2(service_start_end::name, [](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("file_manager", evt2.service_name.c_str()); }); - event_consumer consumer3("service_shutdown_end", [](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("file_manager", evt2.get_service().get().c_str()); + event_consumer consumer3(service_stop_begin::name, [](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("file_manager", evt2.service_name.c_str()); + }); + event_consumer consumer4(service_stop_end::name, [](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("file_manager", evt2.service_name.c_str()); }); event_capture capture({ - "service_started", - "service_shutdown_begin", - "service_shutdown_end", + service_start_begin::name, + service_start_end::name, + service_stop_begin::name, + service_stop_end::name, }); file_manager mgr(*cfg, mp); @@ -117,11 +135,11 @@ TEST_F(file_manager_test, can_create_and_close_file) { mgr.start(); event_capture capture({ - "item_timeout", - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", + item_timeout::name, + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, }); auto source_path = utils::path::combine(cfg->get_cache_directory(), @@ -151,25 +169,23 @@ TEST_F(file_manager_test, can_create_and_close_file) { return api_error::success; }); - event_consumer consumer("filesystem_item_opened", [&](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_create.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - }); + event_consumer consumer( + filesystem_item_opened::name, [&](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("/test_create.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + }); - event_consumer ec2("filesystem_item_handle_opened", [&](const event &evt) { - const auto &evt2 = - dynamic_cast(evt); - EXPECT_STREQ("/test_create.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - EXPECT_STREQ("1", evt2.get_handle().get().c_str()); - }); + event_consumer ec2( + filesystem_item_handle_opened::name, [&](const i_event &evt) { + const auto &evt2 = + dynamic_cast(evt); + EXPECT_STREQ("/test_create.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + EXPECT_EQ(std::uint64_t(1U), evt2.handle); + }); #if defined(_WIN32) EXPECT_EQ(api_error::success, @@ -183,24 +199,22 @@ TEST_F(file_manager_test, can_create_and_close_file) { EXPECT_EQ(std::uint64_t(1U), handle); } - event_consumer ec3("filesystem_item_closed", [&](const event &evt) { + event_consumer ec3(filesystem_item_closed::name, [&](const i_event &evt) { const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_create.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); + EXPECT_STREQ("/test_create.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); }); - event_consumer ec4("filesystem_item_handle_closed", [&](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_create.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - EXPECT_STREQ("1", evt2.get_handle().get().c_str()); - }); + event_consumer ec4( + filesystem_item_handle_closed::name, [&](const i_event &evt) { + const auto &evt2 = + dynamic_cast(evt); + EXPECT_STREQ("/test_create.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + EXPECT_EQ(std::uint64_t(1U), evt2.handle); + }); mgr.close(handle); @@ -226,11 +240,11 @@ TEST_F(file_manager_test, can_open_and_close_file) { mgr.start(); event_capture capture({ - "item_timeout", - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", + item_timeout::name, + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, }); auto source_path = utils::path::combine(cfg->get_cache_directory(), {utils::create_uuid_string()}); @@ -258,25 +272,23 @@ TEST_F(file_manager_test, can_open_and_close_file) { return api_error::success; }); - event_consumer consumer("filesystem_item_opened", [&](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_open.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - }); + event_consumer consumer( + filesystem_item_opened::name, [&](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("/test_open.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + }); - event_consumer ec2("filesystem_item_handle_opened", [&](const event &evt) { - const auto &evt2 = - dynamic_cast(evt); - EXPECT_STREQ("/test_open.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - EXPECT_STREQ("1", evt2.get_handle().get().c_str()); - }); + event_consumer ec2( + filesystem_item_handle_opened::name, [&](const i_event &evt) { + const auto &evt2 = + dynamic_cast(evt); + EXPECT_STREQ("/test_open.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + EXPECT_EQ(std::uint64_t(1U), evt2.handle); + }); std::shared_ptr open_file; #if defined(_WIN32) @@ -291,24 +303,22 @@ TEST_F(file_manager_test, can_open_and_close_file) { EXPECT_EQ(std::uint64_t(1U), handle); } - event_consumer ec3("filesystem_item_closed", [&](const event &evt) { + event_consumer ec3(filesystem_item_closed::name, [&](const i_event &evt) { const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_open.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); + EXPECT_STREQ("/test_open.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); }); - event_consumer ec4("filesystem_item_handle_closed", [&](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_open.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - EXPECT_STREQ("0", evt2.get_directory().get().c_str()); - EXPECT_STREQ("1", evt2.get_handle().get().c_str()); - }); + event_consumer ec4( + filesystem_item_handle_closed::name, [&](const i_event &evt) { + const auto &evt2 = + dynamic_cast(evt); + EXPECT_STREQ("/test_open.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + EXPECT_FALSE(evt2.directory); + EXPECT_EQ(std::uint64_t(1U), evt2.handle); + }); mgr.close(handle); @@ -396,18 +406,17 @@ TEST_F(file_manager_test, {utils::create_uuid_string()}); event_consumer consumer( - "download_resume_added", [&source_path](const event &evt) { + download_resume_added::name, [&source_path](const i_event &evt) { const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_write_partial_download.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_dest_path().get().c_str()); + EXPECT_STREQ("/test_write_partial_download.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.dest_path.c_str()); }); - event_capture capture({"download_resume_added"}, { - "file_upload_completed", - "file_upload_queued", - }); + event_capture capture({download_resume_added::name}, + { + file_upload_completed::name, + file_upload_queued::name, + }); auto now = utils::time::get_time_now(); auto meta = create_meta_attributes( @@ -494,10 +503,10 @@ TEST_F(file_manager_test, mgr.stop(); capture.wait_for_empty(); - event_capture ec2({"download_restored", "download_resume_added"}, + event_capture ec2({download_restored::name, download_resume_added::name}, { - "file_upload_completed", - "file_upload_queued", + file_upload_completed::name, + file_upload_queued::name, }); EXPECT_EQ(std::size_t(0u), mgr.get_open_file_count()); EXPECT_EQ(std::size_t(0u), mgr.get_open_handle_count()); @@ -518,13 +527,12 @@ TEST_F(file_manager_test, mgr.start(); - event_consumer es2("download_restored", [&source_path](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_write_partial_download.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_dest_path().get().c_str()); - }); + event_consumer es2( + download_restored::name, [&source_path](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("/test_write_partial_download.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.dest_path.c_str()); + }); EXPECT_EQ(std::size_t(1u), mgr.get_open_file_count()); EXPECT_EQ(std::size_t(0u), mgr.get_open_handle_count()); @@ -551,20 +559,17 @@ TEST_F(file_manager_test, upload_occurs_after_write_if_fully_downloaded) { {utils::create_uuid_string()}); event_consumer consumer( - "file_upload_queued", [&source_path](const event &evt) { + "file_upload_queued", [&source_path](const i_event &evt) { const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_write_full_download.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); + EXPECT_STREQ("/test_write_full_download.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); + }); + event_consumer es2( + file_upload_completed::name, [&source_path](const i_event &evt) { + const auto &evt2 = dynamic_cast(evt); + EXPECT_STREQ("/test_write_full_download.txt", evt2.api_path.c_str()); + EXPECT_STREQ(source_path.c_str(), evt2.source_path.c_str()); }); - event_consumer es2("file_upload_completed", [&source_path](const event &evt) { - const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_write_full_download.txt", - evt2.get_api_path().get().c_str()); - EXPECT_STREQ(source_path.c_str(), - evt2.get_source().get().c_str()); - }); auto now = utils::time::get_time_now(); auto meta = create_meta_attributes( @@ -625,9 +630,9 @@ TEST_F(file_manager_test, upload_occurs_after_write_if_fully_downloaded) { } event_capture capture({ - "item_timeout", - "file_upload_queued", - "file_upload_completed", + item_timeout::name, + file_upload_queued::name, + file_upload_completed::name, }); EXPECT_CALL(mp, upload_file("/test_write_full_download.txt", source_path, _)) @@ -664,11 +669,11 @@ TEST_F(file_manager_test, can_evict_file) { mgr.start(); event_capture capture({ - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", - "file_upload_completed", + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, + file_upload_completed::name, }); auto source_path = utils::path::combine(cfg->get_cache_directory(), @@ -855,11 +860,11 @@ TEST_F(file_manager_test, evict_file_fails_if_file_is_uploading) { mgr.start(); event_capture capture({ - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", - "file_upload_completed", + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, + file_upload_completed::name, }); auto source_path = utils::path::combine(cfg->get_cache_directory(), @@ -1041,11 +1046,15 @@ TEST_F(file_manager_test, can_get_directory_items) { "..", "", true, + 0U, + {}, }); list.insert(list.begin(), directory_item{ ".", "", true, + 0U, + {}, }); return api_error::success; }); @@ -1405,8 +1414,8 @@ TEST_F(file_manager_test, can_remove_file) { TEST_F(file_manager_test, can_queue_and_remove_upload) { event_capture capture({ - "file_upload_queued", - "download_resume_removed", + file_upload_queued::name, + download_resume_removed::name, }); EXPECT_CALL(mp, is_read_only()).WillRepeatedly(Return(false)); @@ -1441,10 +1450,9 @@ TEST_F(file_manager_test, file_is_closed_after_download_timeout) { auto source_path = utils::path::combine(cfg->get_cache_directory(), {utils::create_uuid_string()}); - event_consumer consumer("item_timeout", [](const event &evt) { + event_consumer consumer(item_timeout::name, [](const i_event &evt) { const auto &evt2 = dynamic_cast(evt); - EXPECT_STREQ("/test_download_timeout.txt", - evt2.get_api_path().get().c_str()); + EXPECT_STREQ("/test_download_timeout.txt", evt2.api_path.c_str()); }); auto now = utils::time::get_time_now(); @@ -1467,7 +1475,7 @@ TEST_F(file_manager_test, file_is_closed_after_download_timeout) { return api_error::success; }); - event_capture capture({"item_timeout"}); + event_capture capture({item_timeout::name}); EXPECT_CALL(mp, read_file_bytes) .WillRepeatedly([](const std::string & /* api_path */, std::size_t size, @@ -1568,11 +1576,11 @@ TEST_F(file_manager_test, mgr.start(); event_capture capture({ - "item_timeout", - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", + item_timeout::name, + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, }); std::uint64_t handle{}; diff --git a/repertory/repertory_test/src/file_mgr_db_test.cpp b/repertory/repertory_test/src/file_mgr_db_test.cpp index ef01a805..57e41f58 100644 --- a/repertory/repertory_test/src/file_mgr_db_test.cpp +++ b/repertory/repertory_test/src/file_mgr_db_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,7 +21,7 @@ */ #include "fixtures/file_mgr_db_fixture.hpp" -#include +#include "utils/time.hpp" namespace repertory { TYPED_TEST_CASE(file_mgr_db_test, file_mgr_db_types); diff --git a/repertory/repertory_test/src/fuse_drive_access_test.cpp b/repertory/repertory_test/src/fuse_drive_access_test.cpp index 1bde67d1..c141d5b5 100644 --- a/repertory/repertory_test/src/fuse_drive_access_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_access_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -103,7 +103,7 @@ TYPED_TEST(fuse_test, access_directory_permutations_test) { std::string dir_name{"access_test"}; auto dir_path = this->create_directory_and_test(dir_name); - for (auto &&permutation : access_permutations) { + for (const auto &permutation : access_permutations) { perform_access_test(permutation, dir_path); } @@ -114,7 +114,7 @@ TYPED_TEST(fuse_test, access_file_permutations_test) { std::string file_name{"access_test"}; auto file_path = this->create_file_and_test(file_name); - for (auto &&permutation : access_permutations) { + for (const auto &permutation : access_permutations) { perform_access_test(permutation, file_path); } diff --git a/repertory/repertory_test/src/fuse_drive_chmod_test.cpp b/repertory/repertory_test/src/fuse_drive_chmod_test.cpp index 42811396..bf38ec37 100644 --- a/repertory/repertory_test/src/fuse_drive_chmod_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_chmod_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/fuse_drive_chown_test.cpp b/repertory/repertory_test/src/fuse_drive_chown_test.cpp index c8adaff2..a438819a 100644 --- a/repertory/repertory_test/src/fuse_drive_chown_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_chown_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp b/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp index 93bcc5cd..3c4405fa 100644 --- a/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_create_and_open_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ TYPED_TEST(fuse_test, create_can_create_directory_with_specific_perms) { std::string dir_name{"create_test"}; auto dir_path = this->create_directory_and_test(dir_name, S_IRUSR); - struct stat64 unix_st {}; + struct stat64 unix_st{}; EXPECT_EQ(0, stat64(dir_path.c_str(), &unix_st)); EXPECT_EQ(S_IRUSR, unix_st.st_mode & ACCESSPERMS); @@ -52,7 +52,7 @@ TYPED_TEST(fuse_test, create_can_create_file_with_specific_perms) { std::string file_name{"create_test"}; auto file_path = this->create_file_and_test(file_name, S_IRUSR); - struct stat64 unix_st {}; + struct stat64 unix_st{}; EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st)); EXPECT_EQ(S_IRUSR, unix_st.st_mode & ACCESSPERMS); @@ -376,7 +376,7 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_path_is_directory) { std::string dir_name{"create_test"}; auto dir_path = this->create_directory_and_test(dir_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(dir_path.c_str(), flags, ACCESSPERMS); EXPECT_EQ(-1, handle); @@ -396,7 +396,7 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_file_exists) { std::string file_name{"create_test"}; auto file_path = this->create_file_and_test(file_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(file_path.c_str(), flags, ACCESSPERMS); EXPECT_EQ(-1, handle); @@ -420,7 +420,7 @@ TYPED_TEST(fuse_test, create_fails_if_path_is_directory) { std::string dir_name{"create_test"}; auto dir_path = this->create_directory_and_test(dir_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(dir_path.c_str(), flags, ACCESSPERMS); EXPECT_EQ(-1, handle); @@ -447,7 +447,7 @@ TYPED_TEST(fuse_test, create_fails_if_parent_path_does_not_exist) { std::string file_name{"no_dir/create_test"}; auto file_path = this->create_file_path(file_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(file_path.c_str(), flags, ACCESSPERMS); EXPECT_EQ(-1, handle); @@ -463,7 +463,7 @@ TYPED_TEST(fuse_test, create_fails_if_invalid) { std::string file_name{"create_test"}; auto file_path = this->create_file_path(file_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(file_path.c_str(), flags, ACCESSPERMS); EXPECT_EQ(-1, handle); @@ -481,7 +481,7 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_is_directory) { std::string dir_name{"create_test"}; auto dir_path = this->create_directory_and_test(dir_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(dir_path.c_str(), flags); EXPECT_EQ(-1, handle); if (handle != -1) { @@ -510,7 +510,7 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_does_not_exist) { std::string file_name{"create_test"}; auto file_path = this->create_file_path(file_name); - for (auto &&flags : ops) { + for (const auto &flags : ops) { auto handle = open(file_path.c_str(), flags); EXPECT_EQ(-1, handle); EXPECT_EQ(ENOENT, errno); diff --git a/repertory/repertory_test/src/fuse_drive_rdrw_test.cpp b/repertory/repertory_test/src/fuse_drive_rdrw_test.cpp index 364a4ae4..9b7bbc63 100644 --- a/repertory/repertory_test/src/fuse_drive_rdrw_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_rdrw_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -63,8 +63,8 @@ TYPED_TEST(fuse_test, rdrw_can_read_from_offset) { data_buffer read_buffer(1U); for (std::size_t idx = 0U; idx < write_buffer.size(); ++idx) { - auto bytes_read = - pread64(handle, read_buffer.data(), read_buffer.size(), idx); + auto bytes_read = pread64(handle, read_buffer.data(), read_buffer.size(), + static_cast(idx)); EXPECT_EQ(1U, bytes_read); EXPECT_EQ(write_buffer.at(idx), read_buffer.at(0U)); @@ -89,8 +89,8 @@ TYPED_TEST(fuse_test, rdrw_can_read_from_offset_after_eof) { data_buffer read_buffer(1U); for (std::size_t idx = 0U; idx < write_buffer.size() + 1U; ++idx) { - auto bytes_read = - pread64(handle, read_buffer.data(), read_buffer.size(), idx); + auto bytes_read = pread64(handle, read_buffer.data(), read_buffer.size(), + static_cast(idx)); if (idx == write_buffer.size()) { EXPECT_EQ(0U, bytes_read); } else { @@ -140,8 +140,7 @@ TYPED_TEST(fuse_test, rdrw_can_not_read_from_wo_file) { EXPECT_EQ(write_buffer.size(), bytes_written); data_buffer read_buffer(1U); - auto bytes_read = - pread64(handle, read_buffer.data(), read_buffer.size(), idx); + auto bytes_read = pread64(handle, read_buffer.data(), read_buffer.size(), 0); EXPECT_EQ(-1, bytes_read); EXPECT_EQ(EBADF, errno); @@ -149,6 +148,63 @@ TYPED_TEST(fuse_test, rdrw_can_not_read_from_wo_file) { this->unlink_file_and_test(file_path); } + +TYPED_TEST(fuse_test, rdrw_can_not_read_or_write_to_directory) { + std::string dir_name{"create_test"}; + auto dir_path = this->create_directory_and_test(dir_name); + + auto handle = open(dir_path.c_str(), O_DIRECTORY); + ASSERT_GT(handle, -1); + + auto write_buffer = utils::generate_secure_random(8096U); + auto bytes_written = + pwrite64(handle, write_buffer.data(), write_buffer.size(), 0U); + EXPECT_EQ(-1, bytes_written); + EXPECT_EQ(EBADF, errno); + + data_buffer read_buffer(1U); + auto bytes_read = pread64(handle, read_buffer.data(), read_buffer.size(), 0); + EXPECT_EQ(-1, bytes_read); + EXPECT_EQ(EISDIR, errno); + + close(handle); + + this->rmdir_and_test(dir_path); +} + +TYPED_TEST(fuse_test, rdrw_can_append_to_file) { + std::string file_name{"append_test"}; + auto file_path = this->create_file_and_test(file_name); + + auto handle = open(file_path.c_str(), O_WRONLY); + ASSERT_GT(handle, -1); + auto bytes_written = pwrite64(handle, "test_", 5U, 0); + EXPECT_EQ(5U, bytes_written); + close(handle); + + handle = open(file_path.c_str(), O_WRONLY | O_APPEND); + ASSERT_GT(handle, -1); + bytes_written = write(handle, "cow_", 4U); + EXPECT_EQ(4U, bytes_written); + close(handle); + + handle = open(file_path.c_str(), O_WRONLY | O_APPEND); + ASSERT_GT(handle, -1); + bytes_written = write(handle, "dog", 3U); + EXPECT_EQ(3U, bytes_written); + close(handle); + + handle = open(file_path.c_str(), O_RDONLY); + ASSERT_GT(handle, -1); + std::string read_buffer; + read_buffer.resize(12U); + auto bytes_read = pread64(handle, read_buffer.data(), read_buffer.size(), 0); + EXPECT_EQ(12U, bytes_read); + EXPECT_STREQ("test_cow_dog", read_buffer.c_str()); + close(handle); + + this->unlink_file_and_test(file_path); +} } // namespace repertory #endif // !defined(_WIN32) diff --git a/repertory/repertory_test/src/json_serialize_test.cpp b/repertory/repertory_test/src/json_serialize_test.cpp index 0c577e3f..e9e79105 100644 --- a/repertory/repertory_test/src/json_serialize_test.cpp +++ b/repertory/repertory_test/src/json_serialize_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/lock_data_test.cpp b/repertory/repertory_test/src/lock_data_test.cpp index 08fe4845..87186ef0 100644 --- a/repertory/repertory_test/src/lock_data_test.cpp +++ b/repertory/repertory_test/src/lock_data_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/meta_db_test.cpp b/repertory/repertory_test/src/meta_db_test.cpp index 8076bb21..8e79fee2 100644 --- a/repertory/repertory_test/src/meta_db_test.cpp +++ b/repertory/repertory_test/src/meta_db_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -615,4 +615,35 @@ TYPED_TEST(meta_db_test, check_set_item_meta_file_defaults) { EXPECT_EQ(0U, utils::string::to_uint64(meta[META_SIZE])); EXPECT_TRUE(meta[META_SOURCE].empty()); } + +TYPED_TEST(meta_db_test, can_enumerate_api_path_list) { + this->meta_db->clear(); + + auto test_dir = create_test_file(); + EXPECT_EQ(api_error::success, + this->meta_db->set_item_meta( + test_dir, { + {META_DIRECTORY, utils::string::from_bool(true)}, + })); + + auto test_file = create_test_file(); + EXPECT_EQ( + api_error::success, + this->meta_db->set_item_meta( + test_file, { + {META_DIRECTORY, utils::string::from_bool(false)}, + })); + + auto call_count{0U}; + const auto get_stop_requested = []() -> bool { return false; }; + + this->meta_db->enumerate_api_path_list( + [&call_count](auto &&list) { + EXPECT_EQ(std::size_t(2U), list.size()); + ++call_count; + }, + get_stop_requested); + + EXPECT_EQ(std::size_t(1U), call_count); +} } // namespace repertory diff --git a/repertory/repertory_test/src/open_file_test.cpp b/repertory/repertory_test/src/open_file_test.cpp index 5d2d9e42..3b07488a 100644 --- a/repertory/repertory_test/src/open_file_test.cpp +++ b/repertory/repertory_test/src/open_file_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,10 @@ #include "test_common.hpp" #include "app_config.hpp" +#include "events/types/filesystem_item_closed.hpp" +#include "events/types/filesystem_item_handle_closed.hpp" +#include "events/types/filesystem_item_handle_opened.hpp" +#include "events/types/filesystem_item_opened.hpp" #include "file_manager/cache_size_mgr.hpp" #include "file_manager/open_file.hpp" #include "mocks/mock_provider.hpp" @@ -601,24 +605,21 @@ TEST_F(open_file_test, can_add_handle) { fsi.size = test_chunk_size * 4u; fsi.source_path = source_path; - event_consumer ec("filesystem_item_opened", [&fsi](const event &e) { + event_consumer ec(filesystem_item_opened::name, [&fsi](const i_event &e) { const auto &ee = dynamic_cast(e); - EXPECT_STREQ(fsi.api_path.c_str(), - ee.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - ee.get_source().get().c_str()); - EXPECT_STREQ("0", ee.get_directory().get().c_str()); + EXPECT_STREQ(fsi.api_path.c_str(), ee.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), ee.source_path.c_str()); + EXPECT_FALSE(ee.directory); }); - event_consumer ec2("filesystem_item_handle_opened", [&fsi](const event &e) { - const auto &ee = dynamic_cast(e); - EXPECT_STREQ(fsi.api_path.c_str(), - ee.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - ee.get_source().get().c_str()); - EXPECT_STREQ("0", ee.get_directory().get().c_str()); - EXPECT_STREQ("1", ee.get_handle().get().c_str()); - }); + event_consumer ec2( + filesystem_item_handle_opened::name, [&fsi](const i_event &e) { + const auto &ee = dynamic_cast(e); + EXPECT_STREQ(fsi.api_path.c_str(), ee.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), ee.source_path.c_str()); + EXPECT_FALSE(ee.directory); + EXPECT_EQ(std::uint64_t(1U), ee.handle); + }); EXPECT_CALL(provider, set_item_meta(fsi.api_path, META_SOURCE, _)) .WillOnce(Return(api_error::success)); @@ -629,8 +630,10 @@ TEST_F(open_file_test, can_add_handle) { EXPECT_EQ(fsi.source_path, source_path2); }); - event_capture capture( - {"filesystem_item_opened", "filesystem_item_handle_opened"}); + event_capture capture({ + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + }); open_file o(test_chunk_size, 0U, fsi, provider, upload_mgr); #if defined(_WIN32) @@ -647,9 +650,10 @@ TEST_F(open_file_test, can_add_handle) { } TEST_F(open_file_test, can_remove_handle) { - event_system::instance().start(); console_consumer c; + event_system::instance().start(); + const auto source_path = test::generate_test_file_name("file_manager_open_file_test"); @@ -660,24 +664,21 @@ TEST_F(open_file_test, can_remove_handle) { fsi.size = test_chunk_size * 4u; fsi.source_path = source_path; - event_consumer ec("filesystem_item_closed", [&fsi](const event &e) { + event_consumer ec(filesystem_item_closed::name, [&fsi](const i_event &e) { const auto &ee = dynamic_cast(e); - EXPECT_STREQ(fsi.api_path.c_str(), - ee.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - ee.get_source().get().c_str()); - EXPECT_STREQ("0", ee.get_directory().get().c_str()); + EXPECT_STREQ(fsi.api_path.c_str(), ee.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), ee.source_path.c_str()); + EXPECT_FALSE(ee.directory); }); - event_consumer ec2("filesystem_item_handle_closed", [&fsi](const event &e) { - const auto &ee = dynamic_cast(e); - EXPECT_STREQ(fsi.api_path.c_str(), - ee.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - ee.get_source().get().c_str()); - EXPECT_STREQ("0", ee.get_directory().get().c_str()); - EXPECT_STREQ("1", ee.get_handle().get().c_str()); - }); + event_consumer ec2( + filesystem_item_handle_closed::name, [&fsi](const i_event &e) { + const auto &ee = dynamic_cast(e); + EXPECT_STREQ(fsi.api_path.c_str(), ee.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), ee.source_path.c_str()); + EXPECT_FALSE(ee.directory); + EXPECT_EQ(std::uint64_t(1U), ee.handle); + }); EXPECT_CALL(upload_mgr, remove_resume) .WillOnce( @@ -689,10 +690,10 @@ TEST_F(open_file_test, can_remove_handle) { .WillOnce(Return(api_error::success)); event_capture capture({ - "filesystem_item_opened", - "filesystem_item_handle_opened", - "filesystem_item_handle_closed", - "filesystem_item_closed", + filesystem_item_opened::name, + filesystem_item_handle_opened::name, + filesystem_item_handle_closed::name, + filesystem_item_closed::name, }); open_file o(test_chunk_size, 0U, fsi, provider, upload_mgr); diff --git a/repertory/repertory_test/src/packet_test.cpp b/repertory/repertory_test/src/packet_test.cpp index 3a36400c..0a29dab2 100644 --- a/repertory/repertory_test/src/packet_test.cpp +++ b/repertory/repertory_test/src/packet_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/providers_test.cpp b/repertory/repertory_test/src/providers_test.cpp index bfd7b2c5..0e1752d7 100644 --- a/repertory/repertory_test/src/providers_test.cpp +++ b/repertory/repertory_test/src/providers_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -421,19 +421,19 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { decrypt_parts(cfg, dir_item.api_path); } - auto dir = std::find_if(list_decrypted.begin(), list_decrypted.end(), - [](const directory_item &dir_item) -> bool { - return dir_item.directory; - }); + auto dir = + std::ranges::find_if(list_decrypted, [](auto &&dir_item) -> bool { + return dir_item.directory; + }); EXPECT_LT(dir, list_decrypted.end()); EXPECT_STREQ("/sub10", dir->api_path.c_str()); EXPECT_STREQ("/", dir->api_parent.c_str()); EXPECT_EQ(std::size_t(0U), dir->size); - auto file = std::find_if(list_decrypted.begin(), list_decrypted.end(), - [](const directory_item &dir_item) -> bool { - return not dir_item.directory; - }); + auto file = + std::ranges::find_if(list_decrypted, [](auto &&dir_item) -> bool { + return not dir_item.directory; + }); EXPECT_LT(file, list_decrypted.end()); EXPECT_STREQ("/test.txt", file->api_path.c_str()); EXPECT_STREQ("/", file->api_parent.c_str()); @@ -460,10 +460,10 @@ static void get_directory_items(const app_config &cfg, i_provider &provider) { decrypt_parts(cfg, dir_item.api_path); } - auto file2 = std::find_if(list_decrypted2.begin(), list_decrypted2.end(), - [](const directory_item &dir_item) -> bool { - return not dir_item.directory; - }); + auto file2 = + std::ranges::find_if(list_decrypted2, [](auto &&dir_item) -> bool { + return not dir_item.directory; + }); EXPECT_LT(file2, list_decrypted2.end()); EXPECT_STREQ("/sub10/moose.txt", file2->api_path.c_str()); EXPECT_STREQ("/sub10", file2->api_parent.c_str()); @@ -635,6 +635,7 @@ TEST(providers, encrypt_provider) { console_consumer consumer{}; event_system::instance().start(); + { app_config cfg(provider_type::encrypt, config_path); @@ -668,6 +669,7 @@ TEST(providers, encrypt_provider) { provider.stop(); mgr.stop(); } + event_system::instance().stop(); } @@ -677,6 +679,7 @@ TEST(providers, s3_provider) { console_consumer consumer{}; event_system::instance().start(); + { app_config cfg(provider_type::s3, config_path); { @@ -706,6 +709,7 @@ TEST(providers, s3_provider) { provider.stop(); mgr.stop(); } + event_system::instance().stop(); } @@ -715,6 +719,7 @@ TEST(providers, sia_provider) { console_consumer consumer{}; event_system::instance().start(); + { app_config cfg(provider_type::sia, config_path); { @@ -744,6 +749,7 @@ TEST(providers, sia_provider) { provider.stop(); mgr.stop(); } + event_system::instance().stop(); } } // namespace repertory diff --git a/repertory/repertory_test/src/ring_buffer_open_file_test.cpp b/repertory/repertory_test/src/ring_buffer_open_file_test.cpp index 292cb8fd..c67ba66b 100644 --- a/repertory/repertory_test/src/ring_buffer_open_file_test.cpp +++ b/repertory/repertory_test/src/ring_buffer_open_file_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -45,9 +45,13 @@ public: mock_provider provider; protected: - void SetUp() override { event_system::instance().start(); } + void SetUp() override { + event_system::instance().start(); + } - void TearDown() override { event_system::instance().stop(); } + void TearDown() override { + event_system::instance().stop(); + } }; TEST_F(ring_buffer_open_file_test, can_forward_to_last_chunk) { diff --git a/repertory/repertory_test/src/upload_test.cpp b/repertory/repertory_test/src/upload_test.cpp index 724335a2..8b21fd8e 100644 --- a/repertory/repertory_test/src/upload_test.cpp +++ b/repertory/repertory_test/src/upload_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,7 @@ */ #include "test_common.hpp" +#include "events/types/file_upload_completed.hpp" #include "file_manager/upload.hpp" #include "mocks/mock_provider.hpp" #include "utils/event_capture.hpp" @@ -44,15 +45,14 @@ TEST(upload, can_upload_a_valid_file) { fsi.size = test_chunk_size * 4U; fsi.source_path = source_path; - event_consumer evt_com("file_upload_completed", [&fsi](const event &evt) { - const auto &comp_evt = dynamic_cast(evt); - EXPECT_STREQ(fsi.api_path.c_str(), - comp_evt.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - comp_evt.get_source().get().c_str()); - EXPECT_STREQ("success", comp_evt.get_result().get().c_str()); - EXPECT_STREQ("0", comp_evt.get_cancelled().get().c_str()); - }); + event_consumer evt_com( + file_upload_completed::name, [&fsi](const i_event &evt) { + const auto &comp_evt = dynamic_cast(evt); + EXPECT_STREQ(fsi.api_path.c_str(), comp_evt.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), comp_evt.source_path.c_str()); + EXPECT_EQ(api_error::success, comp_evt.error); + EXPECT_FALSE(comp_evt.cancelled); + }); EXPECT_CALL(mock_prov, upload_file(fsi.api_path, fsi.source_path, _)) .WillOnce([](const std::string &, const std::string &, @@ -62,7 +62,7 @@ TEST(upload, can_upload_a_valid_file) { }); upload upload(fsi, mock_prov); - event_capture evt_cap({"file_upload_completed"}); + event_capture evt_cap({file_upload_completed::name}); evt_cap.wait_for_empty(); EXPECT_EQ(api_error::success, upload.get_api_error()); @@ -87,16 +87,14 @@ TEST(upload, can_cancel_upload) { fsi.size = test_chunk_size * 4U; fsi.source_path = source_path; - event_consumer evt_con("file_upload_completed", [&fsi](const event &evt) { - const auto &comp_evt = dynamic_cast(evt); - EXPECT_STREQ(fsi.api_path.c_str(), - comp_evt.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - comp_evt.get_source().get().c_str()); - EXPECT_STREQ("comm_error", - comp_evt.get_result().get().c_str()); - EXPECT_STREQ("1", comp_evt.get_cancelled().get().c_str()); - }); + event_consumer evt_con( + file_upload_completed::name, [&fsi](const i_event &evt) { + const auto &comp_evt = dynamic_cast(evt); + EXPECT_STREQ(fsi.api_path.c_str(), comp_evt.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), comp_evt.source_path.c_str()); + EXPECT_EQ(api_error::comm_error, comp_evt.error); + EXPECT_TRUE(comp_evt.cancelled); + }); std::mutex mtx; std::condition_variable notify; @@ -128,7 +126,7 @@ TEST(upload, can_cancel_upload) { notify.notify_one(); lock.unlock(); - event_capture evt_cap({"file_upload_completed"}); + event_capture evt_cap({file_upload_completed::name}); evt_cap.wait_for_empty(); EXPECT_EQ(api_error::comm_error, upload.get_api_error()); @@ -153,15 +151,14 @@ TEST(upload, can_stop_upload) { fsi.size = test_chunk_size * 4U; fsi.source_path = source_path; - event_consumer evt_con("file_upload_completed", [&fsi](const event &evt) { - const auto &evt_com = dynamic_cast(evt); - EXPECT_STREQ(fsi.api_path.c_str(), - evt_com.get_api_path().get().c_str()); - EXPECT_STREQ(fsi.source_path.c_str(), - evt_com.get_source().get().c_str()); - EXPECT_STREQ("comm_error", evt_com.get_result().get().c_str()); - EXPECT_STREQ("0", evt_com.get_cancelled().get().c_str()); - }); + event_consumer evt_con( + file_upload_completed::name, [&fsi](const i_event &evt) { + const auto &evt_com = dynamic_cast(evt); + EXPECT_STREQ(fsi.api_path.c_str(), evt_com.api_path.c_str()); + EXPECT_STREQ(fsi.source_path.c_str(), evt_com.source_path.c_str()); + EXPECT_EQ(api_error::comm_error, evt_com.error); + EXPECT_FALSE(evt_com.cancelled); + }); EXPECT_CALL(mock_provider, upload_file(fsi.api_path, fsi.source_path, _)) .WillOnce([](const std::string &, const std::string &, @@ -171,7 +168,7 @@ TEST(upload, can_stop_upload) { return api_error::comm_error; }); - event_capture evt_cap({"file_upload_completed"}); + event_capture evt_cap({file_upload_completed::name}); { upload upload(fsi, mock_provider); diff --git a/repertory/repertory_test/src/utils_test.cpp b/repertory/repertory_test/src/utils_test.cpp index 2d24a548..aeb9b9dc 100644 --- a/repertory/repertory_test/src/utils_test.cpp +++ b/repertory/repertory_test/src/utils_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_create_attr_test.cpp b/repertory/repertory_test/src/winfsp_drive_create_attr_test.cpp index b85f2688..ac59d424 100644 --- a/repertory/repertory_test/src/winfsp_drive_create_attr_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_create_attr_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_create_nl_test.cpp b/repertory/repertory_test/src/winfsp_drive_create_nl_test.cpp index b27a6d4d..09454eb3 100644 --- a/repertory/repertory_test/src/winfsp_drive_create_nl_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_create_nl_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_create_test.cpp b/repertory/repertory_test/src/winfsp_drive_create_test.cpp index fb5e7f7a..0c9befdb 100644 --- a/repertory/repertory_test/src/winfsp_drive_create_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_create_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -97,7 +97,7 @@ TYPED_TEST(winfsp_test, cr8_file_can_delete_file_after_close) { TYPED_TEST(winfsp_test, cr8_file_cannot_create_files_with_invalid_characters_in_path) { - for (auto &&invalid_char : std::array{ + for (const auto &invalid_char : std::array{ {"*", ":", "<", ">", "?", "|", "\""}, }) { auto handle = ::CreateFileA( diff --git a/repertory/repertory_test/src/winfsp_drive_delete_test.cpp b/repertory/repertory_test/src/winfsp_drive_delete_test.cpp index 4a097119..37aec63a 100644 --- a/repertory/repertory_test/src/winfsp_drive_delete_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_delete_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_info_test.cpp b/repertory/repertory_test/src/winfsp_drive_info_test.cpp index cb8d912e..8546391c 100644 --- a/repertory/repertory_test/src/winfsp_drive_info_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_info_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_rdrw_test.cpp b/repertory/repertory_test/src/winfsp_drive_rdrw_test.cpp index 91542e40..aa684990 100644 --- a/repertory/repertory_test/src/winfsp_drive_rdrw_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_rdrw_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_rename_test.cpp b/repertory/repertory_test/src/winfsp_drive_rename_test.cpp index 6b0eb8c6..1bbeb856 100644 --- a/repertory/repertory_test/src/winfsp_drive_rename_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_rename_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_test.cpp b/repertory/repertory_test/src/winfsp_drive_test.cpp index 6ac4f186..49d4a255 100644 --- a/repertory/repertory_test/src/winfsp_drive_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/repertory/repertory_test/src/winfsp_drive_volume_test.cpp b/repertory/repertory_test/src/winfsp_drive_volume_test.cpp index 3a504e04..29dafed5 100644 --- a/repertory/repertory_test/src/winfsp_drive_volume_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_volume_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/scripts/deliver.sh b/scripts/deliver.sh index 844a20de..a9d9e5c5 100755 --- a/scripts/deliver.sh +++ b/scripts/deliver.sh @@ -35,7 +35,7 @@ fi pushd "${PROJECT_SOURCE_DIR}" BRANCH=$(git branch --show-current) -RELEASE=$(grep set\(PROJECT_RELEASE_ITER ./config.sh | sed s/\)//g | awk '{print $2}') +RELEASE=$(grep PROJECT_RELEASE_ITER= ./config.sh | sed s/PROJECT_RELEASE_ITER=//g) popd if [ "${BRANCH}" == "master" ] || [ "${BRANCH}" == "alpha" ] || [ "${BRANCH}" == "beta" ] || [ "${BRANCH}" == "rc" ]; then diff --git a/scripts/env.sh b/scripts/env.sh index 9bf919cf..d43bc1cd 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -26,7 +26,7 @@ pushd "${PROJECT_SOURCE_DIR}" PROJECT_GIT_REV=$(git rev-parse --short HEAD) . "${PROJECT_SCRIPTS_DIR}/versions.sh" -. "${PROJECT_SCRIPTS_DIR}/options.sh" +. "${PROJECT_SCRIPTS_DIR}/libraries.sh" for PROJECT_LIBRARY in "${PROJECT_LIBRARIES[@]}"; do ENABLE_NAME=PROJECT_ENABLE_${PROJECT_LIBRARY} diff --git a/scripts/libraries.sh b/scripts/libraries.sh new file mode 100755 index 00000000..e55d98bd --- /dev/null +++ b/scripts/libraries.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +PROJECT_LIBRARIES=( + BOOST + CPP_HTTPLIB + CURL + FUSE + JSON + LIBSODIUM + OPENSSL + PUGIXML + ROCKSDB + SPDLOG + SQLITE + STDUUID + TESTING + WINFSP +) + +declare -A PROJECT_CLEANUP +PROJECT_CLEANUP[BINUTILS]="3rd_party/mingw64/binutils-*" +PROJECT_CLEANUP[BOOST]="3rd_party/boost_*" +PROJECT_CLEANUP[CPP_HTTPLIB]="3rd_party/cpp-httplib-*" +PROJECT_CLEANUP[CURL]="3rd_party/curl-*" +PROJECT_CLEANUP[EXPAT]="3rd_party/mingw64/expat-*" +PROJECT_CLEANUP[GCC]="3rd_party/mingw64/gcc-*" +PROJECT_CLEANUP[ICU]="3rd_party/mingw64/icu-release-*" +PROJECT_CLEANUP[JSON]="3rd_party/json-*" +PROJECT_CLEANUP[LIBBITCOIN_SYSTEM_ON]="3rd_party/boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_*" +PROJECT_CLEANUP[LIBSODIUM]="3rd_party/libsodium-*:3rd_party/libsodium*" +PROJECT_CLEANUP[MINGW]="3rd_party/mingw64/mingw-w64-*" +PROJECT_CLEANUP[OPENSSL]="3rd_party/openssl-*" +PROJECT_CLEANUP[PKG_CONFIG]="3rd_party/mingw64/pkg-config-*" +PROJECT_CLEANUP[PUGIXML]="3rd_party/pugixml-*" +PROJECT_CLEANUP[ROCKSDB]="3rd_party/rocksdb-*" +PROJECT_CLEANUP[SPDLOG]="3rd_party/spdlog-*" +PROJECT_CLEANUP[SQLITE]="3rd_party/sqlite*" +PROJECT_CLEANUP[STDUUID]="3rd_party/stduuid-*" +PROJECT_CLEANUP[TESTING]="3rd_party/googletest-*" +PROJECT_CLEANUP[WINFSP]="3rd_party/winfsp-*" +PROJECT_CLEANUP[ZLIB]="3rd_party/mingw64/zlib-*" +export PROJECT_CLEANUP + +declare -A PROJECT_DOWNLOADS +PROJECT_DOWNLOADS[BINUTILS]="https://ftp.gnu.org/gnu/binutils/binutils-${PROJECT_VERSIONS[BINUTILS]}.tar.xz;binutils-${PROJECT_VERSIONS[BINUTILS]}.tar.xz;3rd_party/mingw64" +PROJECT_DOWNLOADS[BOOST2]="https://archives.boost.io/release/${PROJECT_VERSIONS[BOOST2_MAJOR]}.${PROJECT_VERSIONS[BOOST2_MINOR]}.${PROJECT_VERSIONS[BOOST2_PATCH]}/source/boost_${PROJECT_VERSIONS[BOOST2_MAJOR]}_${PROJECT_VERSIONS[BOOST2_MINOR]}_${PROJECT_VERSIONS[BOOST2_PATCH]}.tar.gz;boost_${PROJECT_VERSIONS[BOOST2_MAJOR]}_${PROJECT_VERSIONS[BOOST2_MINOR]}_${PROJECT_VERSIONS[BOOST2_PATCH]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[BOOST]="https://archives.boost.io/release/${PROJECT_VERSIONS[BOOST_MAJOR]}.${PROJECT_VERSIONS[BOOST_MINOR]}.${PROJECT_VERSIONS[BOOST_PATCH]}/source/boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_${PROJECT_VERSIONS[BOOST_PATCH]}.tar.gz;boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_${PROJECT_VERSIONS[BOOST_PATCH]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[CPP_HTTPLIB]="https://github.com/yhirose/cpp-httplib/archive/refs/tags/v${PROJECT_VERSIONS[CPP_HTTPLIB]}.tar.gz;cpp-httplib-${PROJECT_VERSIONS[CPP_HTTPLIB]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[CURL]="https://github.com/curl/curl/archive/refs/tags/curl-${PROJECT_VERSIONS[CURL2]}.tar.gz;curl-${PROJECT_VERSIONS[CURL]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[EXPAT]="https://github.com/libexpat/libexpat/archive/refs/tags/R_${PROJECT_VERSIONS[EXPAT2]}.tar.gz;expat-${PROJECT_VERSIONS[EXPAT]}.tar.gz;3rd_party/mingw64" +PROJECT_DOWNLOADS[GCC]="https://ftp.gnu.org/gnu/gcc/gcc-${PROJECT_VERSIONS[GCC]}/gcc-${PROJECT_VERSIONS[GCC]}.tar.gz;gcc-${PROJECT_VERSIONS[GCC]}.tar.gz;3rd_party/mingw64" +PROJECT_DOWNLOADS[GTEST]="https://github.com/google/googletest/archive/refs/tags/v${PROJECT_VERSIONS[GTEST]}.tar.gz;googletest-${PROJECT_VERSIONS[GTEST]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[ICU]="https://github.com/unicode-org/icu/archive/refs/tags/release-${PROJECT_VERSIONS[ICU]}.tar.gz;icu-release-${PROJECT_VERSIONS[ICU]}.tar.gz;3rd_party/mingw64" +PROJECT_DOWNLOADS[JSON]="https://github.com/nlohmann/json/archive/refs/tags/v${PROJECT_VERSIONS[JSON]}.tar.gz;json-${PROJECT_VERSIONS[JSON]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[LIBSODIUM]="https://github.com/jedisct1/libsodium/archive/refs/tags/${PROJECT_VERSIONS[LIBSODIUM]}-RELEASE.tar.gz;libsodium-${PROJECT_VERSIONS[LIBSODIUM]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[MINGW]="https://sourceforge.net/projects/mingw-w64/files/mingw-w64/mingw-w64-release/mingw-w64-v${PROJECT_VERSIONS[MINGW]}.tar.bz2;;mingw-w64-v${PROJECT_VERSIONS[MINGW]}.tar.bz2;3rd_party/mingw64" +PROJECT_DOWNLOADS[OPENSSL]="https://github.com/openssl/openssl/releases/download/openssl-${PROJECT_VERSIONS[OPENSSL]}/openssl-${PROJECT_VERSIONS[OPENSSL]}.tar.gz;openssl-${PROJECT_VERSIONS[OPENSSL]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[PKG_CONFIG]="https://pkgconfig.freedesktop.org/releases/pkg-config-${PROJECT_VERSIONS[PKG_CONFIG]}.tar.gz;pkg-config-${PROJECT_VERSIONS[PKG_CONFIG]}.tar.gz;3rd_party/mingw64" +PROJECT_DOWNLOADS[PUGIXML]="https://github.com/zeux/pugixml/releases/download/v${PROJECT_VERSIONS[PUGIXML]}/pugixml-${PROJECT_VERSIONS[PUGIXML]}.tar.gz;pugixml-${PROJECT_VERSIONS[PUGIXML]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[ROCKSDB]="https://github.com/facebook/rocksdb/archive/refs/tags/v${PROJECT_VERSIONS[ROCKSDB]}.tar.gz;rocksdb-${PROJECT_VERSIONS[ROCKSDB]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[SPDLOG]="https://github.com/gabime/spdlog/archive/refs/tags/v${PROJECT_VERSIONS[SPDLOG]}.tar.gz;spdlog-${PROJECT_VERSIONS[SPDLOG]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[SQLITE]="https://www.sqlite.org/2024/sqlite-amalgamation-${PROJECT_VERSIONS[SQLITE]}.zip;sqlite-amalgamation-${PROJECT_VERSIONS[SQLITE]}.zip;3rd_party" +PROJECT_DOWNLOADS[STDUUID]="https://github.com/mariusbancila/stduuid/archive/refs/tags/v${PROJECT_VERSIONS[STDUUID]}.tar.gz;stduuid-${PROJECT_VERSIONS[STDUUID]}.tar.gz;3rd_party" +PROJECT_DOWNLOADS[ZLIB]="https://github.com/madler/zlib/archive/refs/tags/v${PROJECT_VERSIONS[ZLIB]}.tar.gz;zlib-${PROJECT_VERSIONS[ZLIB]}.tar.gz;3rd_party/mingw64" +export PROJECT_DOWNLOADS diff --git a/scripts/make_common.sh b/scripts/make_common.sh index 1ae6b863..2d432ea0 100755 --- a/scripts/make_common.sh +++ b/scripts/make_common.sh @@ -23,6 +23,7 @@ cmake "${PROJECT_SOURCE_DIR}" \ -DPROJECT_COMPANY_NAME="${PROJECT_COMPANY_NAME}" \ -DPROJECT_COPYRIGHT="${PROJECT_COPYRIGHT}" \ -DPROJECT_DESC="${PROJECT_DESC}" \ + -DPROJECT_INTERFACE=1 \ -DPROJECT_URL="${PROJECT_URL}" \ ${PROJECT_CMAKE_OPTS} || exit 1 diff --git a/scripts/options.sh b/scripts/options.sh deleted file mode 100755 index db9326de..00000000 --- a/scripts/options.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -PROJECT_LIBRARIES=( - BOOST - CPP_HTTPLIB - CURL - FUSE - JSON - LIBSODIUM - OPENSSL - PUGIXML - ROCKSDB - SPDLOG - SQLITE - STDUUID - TESTING - WINFSP -) - -declare -A PROJECT_CLEANUP -PROJECT_CLEANUP[BOOST]="3rd_party/boost_*" -PROJECT_CLEANUP[CPP_HTTPLIB]="3rd_party/cpp-httplib-*" -PROJECT_CLEANUP[CURL]="3rd_party/curl-*" -PROJECT_CLEANUP[JSON]="3rd_party/json-*" -PROJECT_CLEANUP[LIBBITCOIN_SYSTEM_ON]="3rd_party/boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_*" -PROJECT_CLEANUP[LIBSODIUM]="3rd_party/libsodium-*:3rd_party/libsodium*" -PROJECT_CLEANUP[OPENSSL]="3rd_party/openssl-*" -PROJECT_CLEANUP[PUGIXML]="3rd_party/pugixml-*" -PROJECT_CLEANUP[ROCKSDB]="3rd_party/rocksdb-*" -PROJECT_CLEANUP[SPDLOG]="3rd_party/spdlog-*" -PROJECT_CLEANUP[SQLITE]="3rd_party/sqlite*" -PROJECT_CLEANUP[STDUUID]="3rd_party/stduuid-*" -PROJECT_CLEANUP[TESTING]="3rd_party/googletest-*" -PROJECT_CLEANUP[WINFSP]="3rd_party/winfsp-*" diff --git a/scripts/versions.sh b/scripts/versions.sh index c323096a..af8982ab 100755 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -1,7 +1,7 @@ #!/bin/bash declare -A PROJECT_VERSIONS -PROJECT_VERSIONS[BINUTILS]="2.41" +PROJECT_VERSIONS[BINUTILS]="2.43" PROJECT_VERSIONS[BOOST2_MAJOR]="1" PROJECT_VERSIONS[BOOST2_MINOR]="76" PROJECT_VERSIONS[BOOST2_PATCH]="0" @@ -15,11 +15,11 @@ PROJECT_VERSIONS[EXPAT]="2.6.4" PROJECT_VERSIONS[EXPAT2]="2_6_4" PROJECT_VERSIONS[GCC]="14.2.0" PROJECT_VERSIONS[GTEST]="1.15.2" -PROJECT_VERSIONS[ICU]="75-1" +PROJECT_VERSIONS[ICU]="76-1" PROJECT_VERSIONS[JSON]="3.11.3" PROJECT_VERSIONS[LIBSODIUM]="1.0.20" PROJECT_VERSIONS[MESA]="23.3.3" -PROJECT_VERSIONS[MINGW]="11.0.1" +PROJECT_VERSIONS[MINGW]="12.0.0" PROJECT_VERSIONS[OPENSSL]="3.4.0" PROJECT_VERSIONS[PKG_CONFIG]="0.29.2" PROJECT_VERSIONS[PUGIXML]="1.14" @@ -30,26 +30,3 @@ PROJECT_VERSIONS[SQLITE2]="3.46.1" PROJECT_VERSIONS[STDUUID]="1.2.3" PROJECT_VERSIONS[ZLIB]="1.3.1" export PROJECT_VERSIONS - -declare -A PROJECT_DOWNLOADS -PROJECT_DOWNLOADS[BINUTILS]="https://ftp.gnu.org/gnu/binutils/binutils-${PROJECT_VERSIONS[BINUTILS]}.tar.xz;binutils-${PROJECT_VERSIONS[BINUTILS]}.tar.xz;3rd_party/mingw64" -PROJECT_DOWNLOADS[BOOST2]="https://archives.boost.io/release/${PROJECT_VERSIONS[BOOST2_MAJOR]}.${PROJECT_VERSIONS[BOOST2_MINOR]}.${PROJECT_VERSIONS[BOOST2_PATCH]}/source/boost_${PROJECT_VERSIONS[BOOST2_MAJOR]}_${PROJECT_VERSIONS[BOOST2_MINOR]}_${PROJECT_VERSIONS[BOOST2_PATCH]}.tar.gz;boost_${PROJECT_VERSIONS[BOOST2_MAJOR]}_${PROJECT_VERSIONS[BOOST2_MINOR]}_${PROJECT_VERSIONS[BOOST2_PATCH]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[BOOST]="https://archives.boost.io/release/${PROJECT_VERSIONS[BOOST_MAJOR]}.${PROJECT_VERSIONS[BOOST_MINOR]}.${PROJECT_VERSIONS[BOOST_PATCH]}/source/boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_${PROJECT_VERSIONS[BOOST_PATCH]}.tar.gz;boost_${PROJECT_VERSIONS[BOOST_MAJOR]}_${PROJECT_VERSIONS[BOOST_MINOR]}_${PROJECT_VERSIONS[BOOST_PATCH]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[CPP_HTTPLIB]="https://github.com/yhirose/cpp-httplib/archive/refs/tags/v${PROJECT_VERSIONS[CPP_HTTPLIB]}.tar.gz;cpp-httplib-${PROJECT_VERSIONS[CPP_HTTPLIB]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[CURL]="https://github.com/curl/curl/archive/refs/tags/curl-${PROJECT_VERSIONS[CURL2]}.tar.gz;curl-${PROJECT_VERSIONS[CURL]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[EXPAT]="https://github.com/libexpat/libexpat/archive/refs/tags/R_${PROJECT_VERSIONS[EXPAT2]}.tar.gz;expat-${PROJECT_VERSIONS[EXPAT]}.tar.gz;3rd_party/mingw64" -PROJECT_DOWNLOADS[GCC]="https://ftp.gnu.org/gnu/gcc/gcc-${PROJECT_VERSIONS[GCC]}/gcc-${PROJECT_VERSIONS[GCC]}.tar.gz;gcc-${PROJECT_VERSIONS[GCC]}.tar.gz;3rd_party/mingw64" -PROJECT_DOWNLOADS[GTEST]="https://github.com/google/googletest/archive/refs/tags/v${PROJECT_VERSIONS[GTEST]}.tar.gz;googletest-${PROJECT_VERSIONS[GTEST]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[ICU]="https://github.com/unicode-org/icu/archive/refs/tags/release-${PROJECT_VERSIONS[ICU]}.tar.gz;icu-release-${PROJECT_VERSIONS[ICU]}.tar.gz;3rd_party/mingw64" -PROJECT_DOWNLOADS[JSON]="https://github.com/nlohmann/json/archive/refs/tags/v${PROJECT_VERSIONS[JSON]}.tar.gz;json-${PROJECT_VERSIONS[JSON]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[LIBSODIUM]="https://github.com/jedisct1/libsodium/archive/refs/tags/${PROJECT_VERSIONS[LIBSODIUM]}-RELEASE.tar.gz;libsodium-${PROJECT_VERSIONS[LIBSODIUM]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[MINGW]="https://phoenixnap.dl.sourceforge.net/project/mingw-w64/mingw-w64/mingw-w64-release/mingw-w64-v${PROJECT_VERSIONS[MINGW]}.tar.bz2;mingw-w64-v${PROJECT_VERSIONS[MINGW]}.tar.bz2;3rd_party/mingw64" -PROJECT_DOWNLOADS[OPENSSL]="https://github.com/openssl/openssl/releases/download/openssl-${PROJECT_VERSIONS[OPENSSL]}/openssl-${PROJECT_VERSIONS[OPENSSL]}.tar.gz;openssl-${PROJECT_VERSIONS[OPENSSL]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[PKG_CONFIG]="https://pkgconfig.freedesktop.org/releases/pkg-config-${PROJECT_VERSIONS[PKG_CONFIG]}.tar.gz;pkg-config-${PROJECT_VERSIONS[PKG_CONFIG]}.tar.gz;3rd_party/mingw64" -PROJECT_DOWNLOADS[PUGIXML]="https://github.com/zeux/pugixml/releases/download/v${PROJECT_VERSIONS[PUGIXML]}/pugixml-${PROJECT_VERSIONS[PUGIXML]}.tar.gz;pugixml-${PROJECT_VERSIONS[PUGIXML]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[ROCKSDB]="https://github.com/facebook/rocksdb/archive/refs/tags/v${PROJECT_VERSIONS[ROCKSDB]}.tar.gz;rocksdb-${PROJECT_VERSIONS[ROCKSDB]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[SPDLOG]="https://github.com/gabime/spdlog/archive/refs/tags/v${PROJECT_VERSIONS[SPDLOG]}.tar.gz;spdlog-${PROJECT_VERSIONS[SPDLOG]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[SQLITE]="https://www.sqlite.org/2024/sqlite-amalgamation-${PROJECT_VERSIONS[SQLITE]}.zip;sqlite-amalgamation-${PROJECT_VERSIONS[SQLITE]}.zip;3rd_party" -PROJECT_DOWNLOADS[STDUUID]="https://github.com/mariusbancila/stduuid/archive/refs/tags/v${PROJECT_VERSIONS[STDUUID]}.tar.gz;stduuid-${PROJECT_VERSIONS[STDUUID]}.tar.gz;3rd_party" -PROJECT_DOWNLOADS[ZLIB]="https://github.com/madler/zlib/archive/refs/tags/v${PROJECT_VERSIONS[ZLIB]}.tar.gz;zlib-${PROJECT_VERSIONS[ZLIB]}.tar.gz;3rd_party/mingw64" -export PROJECT_DOWNLOADS diff --git a/support/3rd_party/mingw64/binutils-2.41.tar.xz.sha256 b/support/3rd_party/mingw64/binutils-2.41.tar.xz.sha256 deleted file mode 100644 index 09a6ce51..00000000 --- a/support/3rd_party/mingw64/binutils-2.41.tar.xz.sha256 +++ /dev/null @@ -1 +0,0 @@ -ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450 binutils-2.41.tar.xz diff --git a/support/3rd_party/mingw64/binutils-2.41.tar.xz b/support/3rd_party/mingw64/binutils-2.43.tar.xz similarity index 70% rename from support/3rd_party/mingw64/binutils-2.41.tar.xz rename to support/3rd_party/mingw64/binutils-2.43.tar.xz index 17cfb0ce..42f8fd3f 100644 Binary files a/support/3rd_party/mingw64/binutils-2.41.tar.xz and b/support/3rd_party/mingw64/binutils-2.43.tar.xz differ diff --git a/support/3rd_party/mingw64/binutils-2.43.tar.xz.sha256 b/support/3rd_party/mingw64/binutils-2.43.tar.xz.sha256 new file mode 100644 index 00000000..b432576e --- /dev/null +++ b/support/3rd_party/mingw64/binutils-2.43.tar.xz.sha256 @@ -0,0 +1 @@ +b53606f443ac8f01d1d5fc9c39497f2af322d99e14cea5c0b4b124d630379365 binutils-2.43.tar.xz diff --git a/support/3rd_party/mingw64/expat-2.6.2.tar.gz b/support/3rd_party/mingw64/expat-2.6.2.tar.gz deleted file mode 100644 index 4edd900c..00000000 Binary files a/support/3rd_party/mingw64/expat-2.6.2.tar.gz and /dev/null differ diff --git a/support/3rd_party/mingw64/expat-2.6.2.tar.gz.sha256 b/support/3rd_party/mingw64/expat-2.6.2.tar.gz.sha256 deleted file mode 100644 index 14662b3e..00000000 --- a/support/3rd_party/mingw64/expat-2.6.2.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -fbd032683370d761ba68dba2566d3280a154f5290634172d60a79b24d366d9dc expat-2.6.2.tar.gz diff --git a/support/3rd_party/mingw64/icu-release-75-1.tar.gz.sha256 b/support/3rd_party/mingw64/icu-release-75-1.tar.gz.sha256 deleted file mode 100644 index 7928b77b..00000000 --- a/support/3rd_party/mingw64/icu-release-75-1.tar.gz.sha256 +++ /dev/null @@ -1 +0,0 @@ -925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e icu-release-75-1.tar.gz diff --git a/support/3rd_party/mingw64/icu-release-75-1.tar.gz b/support/3rd_party/mingw64/icu-release-76-1.tar.gz similarity index 81% rename from support/3rd_party/mingw64/icu-release-75-1.tar.gz rename to support/3rd_party/mingw64/icu-release-76-1.tar.gz index 4046e5e9..b22aff5b 100644 Binary files a/support/3rd_party/mingw64/icu-release-75-1.tar.gz and b/support/3rd_party/mingw64/icu-release-76-1.tar.gz differ diff --git a/support/3rd_party/mingw64/icu-release-76-1.tar.gz.sha256 b/support/3rd_party/mingw64/icu-release-76-1.tar.gz.sha256 new file mode 100644 index 00000000..0dc16503 --- /dev/null +++ b/support/3rd_party/mingw64/icu-release-76-1.tar.gz.sha256 @@ -0,0 +1 @@ +a2c443404f00098e9e90acf29dc318e049d2dc78d9ae5f46efb261934a730ce2 icu-release-76-1.tar.gz diff --git a/support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2.sha256 b/support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2.sha256 deleted file mode 100644 index 15f920f1..00000000 --- a/support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2.sha256 +++ /dev/null @@ -1 +0,0 @@ -3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10 mingw-w64-v11.0.1.tar.bz2 diff --git a/support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2 b/support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2 similarity index 54% rename from support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2 rename to support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2 index 403fddb4..814bb6f2 100644 Binary files a/support/3rd_party/mingw64/mingw-w64-v11.0.1.tar.bz2 and b/support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2 differ diff --git a/support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2.sha256 b/support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2.sha256 new file mode 100644 index 00000000..75dfa687 --- /dev/null +++ b/support/3rd_party/mingw64/mingw-w64-v12.0.0.tar.bz2.sha256 @@ -0,0 +1 @@ +cc41898aac4b6e8dd5cffd7331b9d9515b912df4420a3a612b5ea2955bbeed2f mingw-w64-v12.0.0.tar.bz2 diff --git a/support/include/utils/all.hpp b/support/include/utils/all.hpp index 68942580..17db24f7 100644 --- a/support/include/utils/all.hpp +++ b/support/include/utils/all.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/collection.hpp b/support/include/utils/collection.hpp index 2da36e0c..d6a4f0e4 100644 --- a/support/include/utils/collection.hpp +++ b/support/include/utils/collection.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/com_init_wrapper.hpp b/support/include/utils/com_init_wrapper.hpp index a9d6349f..2195eaf3 100644 --- a/support/include/utils/com_init_wrapper.hpp +++ b/support/include/utils/com_init_wrapper.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/common.hpp b/support/include/utils/common.hpp index d305fb54..4ccda495 100644 --- a/support/include/utils/common.hpp +++ b/support/include/utils/common.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/config.hpp b/support/include/utils/config.hpp index d1985250..cedba8cd 100644 --- a/support/include/utils/config.hpp +++ b/support/include/utils/config.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -416,6 +416,7 @@ using data_buffer = std::vector; using mutex_lock = std::lock_guard; using recur_mutex_lock = std::lock_guard; using stop_type = std::atomic_bool; +using stop_type_callback = std::function; using unique_mutex_lock = std::unique_lock; using unique_recur_mutex_lock = std::unique_lock; @@ -462,16 +463,14 @@ struct file_deleter final { }; using file_t = std::unique_ptr; -#if defined(PROJECT_ENABLE_CURL) struct http_range final { std::uint64_t begin{}; std::uint64_t end{}; }; -using http_headers = std::unordered_map; +using http_headers = std::map; using http_query_parameters = std::map; using http_ranges = std::vector; -#endif // defined(PROJECT_ENABLE_CURL) } // namespace repertory #endif // defined(__cplusplus) diff --git a/support/include/utils/db/sqlite/db_common.hpp b/support/include/utils/db/sqlite/db_common.hpp index de69300e..a8d14c75 100644 --- a/support/include/utils/db/sqlite/db_common.hpp +++ b/support/include/utils/db/sqlite/db_common.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/db/sqlite/db_delete.hpp b/support/include/utils/db/sqlite/db_delete.hpp index 3c350973..c23432e0 100644 --- a/support/include/utils/db/sqlite/db_delete.hpp +++ b/support/include/utils/db/sqlite/db_delete.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/db/sqlite/db_insert.hpp b/support/include/utils/db/sqlite/db_insert.hpp index fdf5d25e..581f1119 100644 --- a/support/include/utils/db/sqlite/db_insert.hpp +++ b/support/include/utils/db/sqlite/db_insert.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/db/sqlite/db_select.hpp b/support/include/utils/db/sqlite/db_select.hpp index a80ae2aa..9fc62002 100644 --- a/support/include/utils/db/sqlite/db_select.hpp +++ b/support/include/utils/db/sqlite/db_select.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/db/sqlite/db_update.hpp b/support/include/utils/db/sqlite/db_update.hpp index 335d0ec1..88a3f404 100644 --- a/support/include/utils/db/sqlite/db_update.hpp +++ b/support/include/utils/db/sqlite/db_update.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/db/sqlite/db_where_t.hpp b/support/include/utils/db/sqlite/db_where_t.hpp index 5178eee2..2830c900 100644 --- a/support/include/utils/db/sqlite/db_where_t.hpp +++ b/support/include/utils/db/sqlite/db_where_t.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/encrypting_reader.hpp b/support/include/utils/encrypting_reader.hpp index ead01442..d505e031 100644 --- a/support/include/utils/encrypting_reader.hpp +++ b/support/include/utils/encrypting_reader.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -32,17 +32,19 @@ namespace repertory::utils::encryption { class encrypting_reader final { public: encrypting_reader(std::string_view file_name, std::string_view source_path, - stop_type &stop_requested, std::string_view token, + stop_type_callback stop_requested_cb, + std::string_view token, std::optional relative_parent_path, std::size_t error_return = 0U); encrypting_reader(std::string_view encrypted_file_path, - std::string_view source_path, stop_type &stop_requested, + std::string_view source_path, + stop_type_callback stop_requested_cb, std::string_view token, std::size_t error_return = 0U); encrypting_reader( std::string_view encrypted_file_path, std::string_view source_path, - stop_type &stop_requested, std::string_view token, + stop_type_callback stop_requested_cb, std::string_view token, std::vector> iv_list, @@ -62,7 +64,7 @@ public: private: utils::encryption::hash_256_t key_; - stop_type &stop_requested_; + stop_type_callback stop_requested_cb_; size_t error_return_; std::unique_ptr source_file_; @@ -87,16 +89,16 @@ private: auto reader_function(char *buffer, size_t size, size_t nitems) -> size_t; public: - [[nodiscard]] static auto - calculate_decrypted_size(std::uint64_t total_size) -> std::uint64_t; + [[nodiscard]] static auto calculate_decrypted_size(std::uint64_t total_size) + -> std::uint64_t; [[nodiscard]] static auto calculate_encrypted_size(std::string_view source_path) -> std::uint64_t; [[nodiscard]] auto create_iostream() const -> std::shared_ptr; - [[nodiscard]] static constexpr auto - get_encrypted_chunk_size() -> std::size_t { + [[nodiscard]] static constexpr auto get_encrypted_chunk_size() + -> std::size_t { return encrypted_chunk_size_; } @@ -116,14 +118,17 @@ public: return error_return_; } - [[nodiscard]] auto get_iv_list() - -> std::vector> { + [[nodiscard]] static constexpr auto get_header_size() -> std::size_t { + return header_size_; + } + + [[nodiscard]] auto get_iv_list() -> std::vector< + std::array> { return iv_list_; } [[nodiscard]] auto get_stop_requested() const -> bool { - return stop_requested_; + return stop_requested_cb_(); } [[nodiscard]] auto get_total_size() const -> std::uint64_t { @@ -131,8 +136,8 @@ public: } [[nodiscard]] static auto reader_function(char *buffer, size_t size, - size_t nitems, - void *instream) -> size_t { + size_t nitems, void *instream) + -> size_t { return reinterpret_cast(instream)->reader_function( buffer, size, nitems); } diff --git a/support/include/utils/encryption.hpp b/support/include/utils/encryption.hpp index 08729280..fd440c0a 100644 --- a/support/include/utils/encryption.hpp +++ b/support/include/utils/encryption.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -185,7 +185,6 @@ encrypt_data(const std::array; @@ -195,7 +194,11 @@ read_encrypted_range(const http_range &range, const utils::encryption::hash_256_t &key, reader_func_t reader_func, std::uint64_t total_size, data_buffer &data) -> bool; -#endif // defined(PROJECT_ENABLE_CURL) + +[[nodiscard]] auto read_encrypted_range( + const http_range &range, const utils::encryption::hash_256_t &key, + reader_func_t reader_func, std::uint64_t total_size, unsigned char *data, + std::size_t size, std::size_t &bytes_read) -> bool; #endif // defined(PROJECT_ENABLE_BOOST) template diff --git a/support/include/utils/error.hpp b/support/include/utils/error.hpp index 6aa5c613..83e153d1 100644 --- a/support/include/utils/error.hpp +++ b/support/include/utils/error.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file.hpp b/support/include/utils/file.hpp index 9dd62bea..c3afca3a 100644 --- a/support/include/utils/file.hpp +++ b/support/include/utils/file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file_directory.hpp b/support/include/utils/file_directory.hpp index 56980686..b47ac0e3 100644 --- a/support/include/utils/file_directory.hpp +++ b/support/include/utils/file_directory.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file_enc_file.hpp b/support/include/utils/file_enc_file.hpp index 1598bc84..7734781f 100644 --- a/support/include/utils/file_enc_file.hpp +++ b/support/include/utils/file_enc_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -45,12 +45,13 @@ public: private: fs_file_t file_; + std::string encryption_token_; public: void close() override; - [[nodiscard]] auto copy_to(std::string_view new_path, - bool overwrite) const -> bool override; + [[nodiscard]] auto copy_to(std::string_view new_path, bool overwrite) const + -> bool override; [[nodiscard]] auto exists() const -> bool override { return file_->exists(); } @@ -68,8 +69,8 @@ public: return file_->get_read_buffer_size(); } - [[nodiscard]] auto - get_time(time_type type) const -> std::optional override { + [[nodiscard]] auto get_time(time_type type) const + -> std::optional override { return file_->get_time(type); } @@ -97,9 +98,10 @@ public: [[nodiscard]] auto truncate(std::size_t size) -> bool override; - [[nodiscard]] auto - write(const unsigned char *data, std::size_t to_write, std::size_t offset, - std::size_t *total_written = nullptr) -> bool override; + [[nodiscard]] auto write(const unsigned char *data, std::size_t to_write, + std::size_t offset, + std::size_t *total_written = nullptr) + -> bool override; public: [[nodiscard]] operator bool() const override { diff --git a/support/include/utils/file_file.hpp b/support/include/utils/file_file.hpp index 265279cc..989678c3 100644 --- a/support/include/utils/file_file.hpp +++ b/support/include/utils/file_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file_smb_directory.hpp b/support/include/utils/file_smb_directory.hpp index a418de12..c371d8b7 100644 --- a/support/include/utils/file_smb_directory.hpp +++ b/support/include/utils/file_smb_directory.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file_smb_file.hpp b/support/include/utils/file_smb_file.hpp index 0b3e7c41..df5792a0 100644 --- a/support/include/utils/file_smb_file.hpp +++ b/support/include/utils/file_smb_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/file_thread_file.hpp b/support/include/utils/file_thread_file.hpp index 0d1fac5f..3fc0f52b 100644 --- a/support/include/utils/file_thread_file.hpp +++ b/support/include/utils/file_thread_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -67,11 +67,44 @@ public: thread_file(thread_file &&move_file) noexcept : file_(std::move(move_file.file_)) {} - ~thread_file() override { close(); } + ~thread_file() override; + +private: + using action_t = std::function; + + struct io_item final { + action_t action; + bool complete{false}; + std::unique_ptr mtx{ + std::make_unique(), + }; + mutable std::unique_ptr notify{ + std::make_unique(), + }; + bool success{false}; + + void done(bool result); + + void wait() const; + }; private: fs_file_t file_; +private: + mutable std::vector> actions_; + mutable std::unique_ptr io_thread_; + mutable std::unique_ptr mtx_{std::make_unique()}; + mutable std::unique_ptr notify_{ + std::make_unique(), + }; + stop_type stop_requested_{false}; + +private: + auto do_io(action_t action) const -> bool; + + void thread_func() const; + public: void close() override; diff --git a/support/include/utils/hash.hpp b/support/include/utils/hash.hpp index 9e4a7626..9b41d3b4 100644 --- a/support/include/utils/hash.hpp +++ b/support/include/utils/hash.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/path.hpp b/support/include/utils/path.hpp index f833061a..a32bac2a 100644 --- a/support/include/utils/path.hpp +++ b/support/include/utils/path.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/string.hpp b/support/include/utils/string.hpp index b119c376..764e0985 100644 --- a/support/include/utils/string.hpp +++ b/support/include/utils/string.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/time.hpp b/support/include/utils/time.hpp index c790d840..27b9de90 100644 --- a/support/include/utils/time.hpp +++ b/support/include/utils/time.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/types/file/i_directory.hpp b/support/include/utils/types/file/i_directory.hpp index 9746467e..15cc2680 100644 --- a/support/include/utils/types/file/i_directory.hpp +++ b/support/include/utils/types/file/i_directory.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/types/file/i_file.hpp b/support/include/utils/types/file/i_file.hpp index f870d693..3a9c8d9d 100644 --- a/support/include/utils/types/file/i_file.hpp +++ b/support/include/utils/types/file/i_file.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/types/file/i_fs_item.hpp b/support/include/utils/types/file/i_fs_item.hpp index f4a3c027..37724463 100644 --- a/support/include/utils/types/file/i_fs_item.hpp +++ b/support/include/utils/types/file/i_fs_item.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/unix.hpp b/support/include/utils/unix.hpp index 424cf9b1..6f0ca8a4 100644 --- a/support/include/utils/unix.hpp +++ b/support/include/utils/unix.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/include/utils/windows.hpp b/support/include/utils/windows.hpp index 5050e14d..b380f4b8 100644 --- a/support/include/utils/windows.hpp +++ b/support/include/utils/windows.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/common.cpp b/support/src/utils/common.cpp index e99a418d..92382f6f 100644 --- a/support/src/utils/common.cpp +++ b/support/src/utils/common.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/db/sqlite/db_common.cpp b/support/src/utils/db/sqlite/db_common.cpp index 15e6301a..e863f5d6 100644 --- a/support/src/utils/db/sqlite/db_common.cpp +++ b/support/src/utils/db/sqlite/db_common.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/db/sqlite/db_delete.cpp b/support/src/utils/db/sqlite/db_delete.cpp index de928e16..1ea81d89 100644 --- a/support/src/utils/db/sqlite/db_delete.cpp +++ b/support/src/utils/db/sqlite/db_delete.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/db/sqlite/db_insert.cpp b/support/src/utils/db/sqlite/db_insert.cpp index a82de4f2..2e5ead3d 100644 --- a/support/src/utils/db/sqlite/db_insert.cpp +++ b/support/src/utils/db/sqlite/db_insert.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/db/sqlite/db_select.cpp b/support/src/utils/db/sqlite/db_select.cpp index 54c9f3a2..ccdefd24 100644 --- a/support/src/utils/db/sqlite/db_select.cpp +++ b/support/src/utils/db/sqlite/db_select.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/db/sqlite/db_update.cpp b/support/src/utils/db/sqlite/db_update.cpp index 4000e9be..5e550fc1 100644 --- a/support/src/utils/db/sqlite/db_update.cpp +++ b/support/src/utils/db/sqlite/db_update.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/encrypting_reader.cpp b/support/src/utils/encrypting_reader.cpp index b24b8fe3..a9c44eb3 100644 --- a/support/src/utils/encrypting_reader.cpp +++ b/support/src/utils/encrypting_reader.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -40,8 +40,8 @@ class encrypting_streambuf final : public encrypting_reader::streambuf { public: encrypting_streambuf(const encrypting_streambuf &) = default; encrypting_streambuf(encrypting_streambuf &&) = delete; - auto - operator=(const encrypting_streambuf &) -> encrypting_streambuf & = delete; + auto operator=(const encrypting_streambuf &) + -> encrypting_streambuf & = delete; auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete; explicit encrypting_streambuf(const encrypting_reader &reader) @@ -93,9 +93,10 @@ protected: return encrypting_reader::streambuf::seekoff(off, dir, which); } - auto seekpos(pos_type pos, std::ios_base::openmode which = - std::ios_base::out | - std::ios_base::in) -> pos_type override { + auto seekpos(pos_type pos, + std::ios_base::openmode which = std::ios_base::out | + std::ios_base::in) + -> pos_type override { return seekoff(pos, std::ios_base::beg, which); } @@ -177,16 +178,16 @@ const std::size_t encrypting_reader::encrypted_chunk_size_ = encrypting_reader::encrypting_reader( std::string_view file_name, std::string_view source_path, - stop_type &stop_requested, std::string_view token, + stop_type_callback stop_requested_cb, std::string_view token, std::optional relative_parent_path, std::size_t error_return) : key_(utils::encryption::generate_key( token)), - stop_requested_(stop_requested), + stop_requested_cb_(std::move(stop_requested_cb)), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { REPERTORY_USES_FUNCTION_NAME(); - if (not *source_file_) { + if (not*source_file_) { throw utils::error::create_exception(function_name, { "file open failed", source_path, @@ -237,17 +238,17 @@ encrypting_reader::encrypting_reader( encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, std::string_view source_path, - stop_type &stop_requested, + stop_type_callback stop_requested_cb, std::string_view token, std::size_t error_return) : key_(utils::encryption::generate_key( token)), - stop_requested_(stop_requested), + stop_requested_cb_(std::move(stop_requested_cb)), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { REPERTORY_USES_FUNCTION_NAME(); - if (not *source_file_) { + if (not*source_file_) { throw utils::error::create_exception(function_name, { "file open failed", source_path, @@ -283,19 +284,19 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path, encrypting_reader::encrypting_reader( std::string_view encrypted_file_path, std::string_view source_path, - stop_type &stop_requested, std::string_view token, + stop_type_callback stop_requested_cb, std::string_view token, std::vector< std::array> iv_list, std::size_t error_return) : key_(utils::encryption::generate_key( token)), - stop_requested_(stop_requested), + stop_requested_cb_(std::move(stop_requested_cb)), error_return_(error_return), source_file_(utils::file::file::open_or_create_file(source_path, true)) { REPERTORY_USES_FUNCTION_NAME(); - if (not *source_file_) { + if (not*source_file_) { throw utils::error::create_exception(function_name, { "file open failed", source_path, @@ -329,7 +330,7 @@ encrypting_reader::encrypting_reader( encrypting_reader::encrypting_reader(const encrypting_reader &reader) : key_(reader.key_), - stop_requested_(reader.stop_requested_), + stop_requested_cb_(reader.stop_requested_cb_), error_return_(reader.error_return_), source_file_( utils::file::file::open_file(reader.source_file_->get_path(), true)), @@ -343,7 +344,7 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader) total_size_(reader.total_size_) { REPERTORY_USES_FUNCTION_NAME(); - if (not *source_file_) { + if (not*source_file_) { throw utils::error::create_exception( function_name, { "file open failed", @@ -403,7 +404,7 @@ auto encrypting_reader::reader_function(char *buffer, size_t size, try { ret = true; auto remain = read_size; - while (not stop_requested_ && ret && (remain != 0U)) { + while (not get_stop_requested() && ret && (remain != 0U)) { if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) { auto &chunk_buffer = chunk_buffers_[chunk]; data_buffer file_data(chunk == last_data_chunk_ @@ -441,9 +442,9 @@ auto encrypting_reader::reader_function(char *buffer, size_t size, } } - return stop_requested_ ? static_cast(CURL_READFUNC_ABORT) - : ret ? total_read - : error_return_; + return get_stop_requested() ? static_cast(CURL_READFUNC_ABORT) + : ret ? total_read + : error_return_; } } // namespace repertory::utils::encryption diff --git a/support/src/utils/encryption.cpp b/support/src/utils/encryption.cpp index cbac39ac..70a9c83b 100644 --- a/support/src/utils/encryption.cpp +++ b/support/src/utils/encryption.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,26 +25,27 @@ #include "utils/collection.hpp" #include "utils/encrypting_reader.hpp" +#include "utils/path.hpp" namespace repertory::utils::encryption { auto decrypt_file_path(std::string_view encryption_token, std::string &file_path) -> bool { - std::string decrypted_file_path{}; + std::vector decrypted_parts; for (const auto &part : std::filesystem::path(file_path)) { auto file_name = part.string(); if (file_name == "/") { continue; } - auto res = decrypt_file_name(encryption_token, file_name); - if (not res) { - return res; + if (not decrypt_file_name(encryption_token, file_name)) { + return false; } - decrypted_file_path += '/' + file_name; + decrypted_parts.push_back(file_name); } - file_path = decrypted_file_path; + file_path = + utils::path::create_api_path(utils::string::join(decrypted_parts, '/')); return true; } @@ -56,34 +57,27 @@ auto decrypt_file_name(std::string_view encryption_token, } file_name.clear(); - if (not utils::encryption::decrypt_data(encryption_token, buffer, - file_name)) { - return false; - } - - return true; + return utils::encryption::decrypt_data(encryption_token, buffer, file_name); } -#if defined(PROJECT_ENABLE_CURL) auto read_encrypted_range(const http_range &range, const utils::encryption::hash_256_t &key, reader_func_t reader_func, std::uint64_t total_size, data_buffer &data) -> bool { - const auto encrypted_chunk_size = + auto encrypted_chunk_size = utils::encryption::encrypting_reader::get_encrypted_chunk_size(); - const auto data_chunk_size = + auto data_chunk_size = utils::encryption::encrypting_reader::get_data_chunk_size(); - const auto start_chunk = - static_cast(range.begin / data_chunk_size); - const auto end_chunk = static_cast(range.end / data_chunk_size); + auto start_chunk = static_cast(range.begin / data_chunk_size); + auto end_chunk = static_cast(range.end / data_chunk_size); auto remain = range.end - range.begin + 1U; auto source_offset = static_cast(range.begin % data_chunk_size); for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) { data_buffer cypher; - const auto start_offset = chunk * encrypted_chunk_size; - const auto end_offset = std::min( + auto start_offset = chunk * encrypted_chunk_size; + auto end_offset = std::min( start_offset + (total_size - (chunk * data_chunk_size)) + encryption_header_size - 1U, static_cast(start_offset + encrypted_chunk_size - 1U)); @@ -98,7 +92,7 @@ auto read_encrypted_range(const http_range &range, } cypher.clear(); - const auto data_size = static_cast(std::min( + auto data_size = static_cast(std::min( remain, static_cast(data_chunk_size - source_offset))); std::copy(std::next(source_buffer.begin(), static_cast(source_offset)), @@ -111,7 +105,58 @@ auto read_encrypted_range(const http_range &range, return true; } -#endif // defined(PROJECT_ENABLE_CURL) + +auto read_encrypted_range(const http_range &range, + const utils::encryption::hash_256_t &key, + reader_func_t reader_func, std::uint64_t total_size, + unsigned char *data, std::size_t size, + std::size_t &bytes_read) -> bool { + bytes_read = 0U; + + auto encrypted_chunk_size = + utils::encryption::encrypting_reader::get_encrypted_chunk_size(); + auto data_chunk_size = + utils::encryption::encrypting_reader::get_data_chunk_size(); + + auto start_chunk = static_cast(range.begin / data_chunk_size); + auto end_chunk = static_cast(range.end / data_chunk_size); + auto remain = range.end - range.begin + 1U; + auto source_offset = static_cast(range.begin % data_chunk_size); + + std::span dest_buffer(data, size); + for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) { + data_buffer cypher; + auto start_offset = chunk * encrypted_chunk_size; + auto end_offset = std::min( + start_offset + (total_size - (chunk * data_chunk_size)) + + encryption_header_size - 1U, + static_cast(start_offset + encrypted_chunk_size - 1U)); + + if (not reader_func(cypher, start_offset, end_offset)) { + return false; + } + + data_buffer source_buffer; + if (not utils::encryption::decrypt_data(key, cypher, source_buffer)) { + return false; + } + cypher.clear(); + + auto data_size = static_cast(std::min( + remain, static_cast(data_chunk_size - source_offset))); + std::copy( + std::next(source_buffer.begin(), + static_cast(source_offset)), + std::next(source_buffer.begin(), + static_cast(source_offset + data_size)), + std::next(dest_buffer.begin(), static_cast(bytes_read))); + remain -= data_size; + bytes_read += data_size; + source_offset = 0U; + } + + return true; +} } // namespace repertory::utils::encryption #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined (PROJECT_ENABLE_BOOST) diff --git a/support/src/utils/error.cpp b/support/src/utils/error.cpp index 53fbf2e9..73d573e2 100644 --- a/support/src/utils/error.cpp +++ b/support/src/utils/error.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/file.cpp b/support/src/utils/file.cpp index f7368b84..1d747156 100644 --- a/support/src/utils/file.cpp +++ b/support/src/utils/file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/file_directory.cpp b/support/src/utils/file_directory.cpp index 95c3732e..86342ec8 100644 --- a/support/src/utils/file_directory.cpp +++ b/support/src/utils/file_directory.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/file_enc_file.cpp b/support/src/utils/file_enc_file.cpp index 54dc3b27..de015e94 100644 --- a/support/src/utils/file_enc_file.cpp +++ b/support/src/utils/file_enc_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,31 +23,166 @@ #include "utils/file_enc_file.hpp" +#include "utils/common.hpp" +#include "utils/encrypting_reader.hpp" +#include "utils/encryption.hpp" + namespace repertory::utils::file { -auto enc_file::attach_file(fs_file_t file) -> fs_file_t {} +auto enc_file::attach_file(fs_file_t file) -> fs_file_t { + return fs_file_t{ + new enc_file(std::move(file)), + }; +} enc_file::enc_file(fs_file_t file) : file_(std::move(file)) {} -void enc_file::close() {} +void enc_file::close() { file_->close(); } -auto enc_file::copy_to(std::string_view new_path, - bool overwrite) const -> bool {} +auto enc_file::copy_to(std::string_view new_path, bool overwrite) const + -> bool { + return file_->copy_to(new_path, overwrite); +} -void enc_file::flush() const {} +void enc_file::flush() const { return file_->flush(); } -auto enc_file::move_to(std::string_view path) -> bool {} +auto enc_file::move_to(std::string_view path) -> bool { + return file_->move_to(path); +} auto enc_file::read(unsigned char *data, std::size_t to_read, - std::uint64_t offset, std::size_t *total_read) -> bool {} + std::uint64_t offset, std::size_t *total_read) -> bool { + if (total_read != nullptr) { + *total_read = 0U; + } -auto enc_file::remove() -> bool {} + auto file_size{size()}; + if (not file_size.has_value()) { + return false; + } -auto enc_file::truncate(std::size_t size) -> bool {} + to_read = utils::calculate_read_size(file_size.value(), to_read, offset); + if (to_read == 0U) { + return true; + } + + std::size_t bytes_read{}; + auto ret{ + utils::encryption::read_encrypted_range( + {offset, offset + to_read - 1U}, + utils::encryption::generate_key( + encryption_token_), + [&](auto &&ct_buffer, auto &&start_offset, + auto &&end_offset) -> bool { + ct_buffer.resize(end_offset - start_offset + 1U); + return file_->read(ct_buffer, start_offset); + }, + file_size.value(), data, to_read, bytes_read), + }; + if (ret && total_read != nullptr) { + *total_read = bytes_read; + } + + return ret; +} + +auto enc_file::remove() -> bool { return file_->remove(); } + +auto enc_file::truncate(std::size_t size) -> bool { + if (size == 0U) { + return file_->truncate(size); + } + + auto file_size{this->size()}; + if (not file_size.has_value()) { + return false; + } + + if (size == file_size.value()) { + return true; + } + + auto chunks{ + size / utils::encryption::encrypting_reader::get_data_chunk_size(), + }; + auto real_size{ + (chunks * utils::encryption::encrypting_reader::get_data_chunk_size()) + + (chunks * utils::encryption::encrypting_reader::get_header_size()), + }; + auto remain{ + size % utils::encryption::encrypting_reader::get_data_chunk_size(), + }; + if (remain > 0U) { + real_size += + (remain + utils::encryption::encrypting_reader::get_header_size()); + } + + if (size < file_size.value()) { + if (remain == 0U) { + return file_->truncate(real_size); + } + + auto begin_chunk{ + size / utils::encryption::encrypting_reader::get_data_chunk_size(), + }; + + auto offset{ + begin_chunk * + utils::encryption::encrypting_reader::get_data_chunk_size(), + }; + + std::size_t total_read{}; + data_buffer data( + utils::encryption::encrypting_reader::get_data_chunk_size()); + if (not i_file::read(data, offset, &total_read)) { + return false; + } + data.resize(remain); + + if (not file_->truncate(real_size)) { + return false; + } + + return i_file::write(data, offset); + } + + auto begin_chunk{ + file_size.value() / + utils::encryption::encrypting_reader::get_data_chunk_size(), + }; + auto end_chunk{ + utils::divide_with_ceiling( + file_size.value(), + utils::encryption::encrypting_reader::get_data_chunk_size()), + }; + + return false; +} auto enc_file::write(const unsigned char *data, std::size_t to_write, - std::size_t offset, std::size_t *total_written) -> bool {} + std::size_t offset, std::size_t *total_written) -> bool { + auto file_size{size()}; + if (not file_size.has_value()) { + return false; + } -auto enc_file::size() const -> std::optional {} + if ((offset + to_write) > file_size.value()) { + if (not truncate((offset + to_write) - file_size.value())) { + return false; + } + } + + return false; +} + +auto enc_file::size() const -> std::optional { + auto file_size = file_->size(); + if (not file_size.has_value()) { + return std::nullopt; + } + + return utils::encryption::encrypting_reader::calculate_decrypted_size( + file_size.value()); +} } // namespace repertory::utils::file #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) diff --git a/support/src/utils/file_file.cpp b/support/src/utils/file_file.cpp index ba54ad42..be18225d 100644 --- a/support/src/utils/file_file.cpp +++ b/support/src/utils/file_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/file_smb_directory.cpp b/support/src/utils/file_smb_directory.cpp index 13171039..190366f5 100644 --- a/support/src/utils/file_smb_directory.cpp +++ b/support/src/utils/file_smb_directory.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -127,7 +127,7 @@ auto smb_directory::open(std::wstring_view host, std::wstring_view user, } auto smb_directory::copy_to(std::string_view new_path, - bool overwrite) const -> bool { + bool /* overwrite */) const -> bool { REPERTORY_USES_FUNCTION_NAME(); try { diff --git a/support/src/utils/file_smb_file.cpp b/support/src/utils/file_smb_file.cpp index c789315e..eca3d955 100644 --- a/support/src/utils/file_smb_file.cpp +++ b/support/src/utils/file_smb_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/file_thread_file.cpp b/support/src/utils/file_thread_file.cpp index 6dce1b7f..30d569ca 100644 --- a/support/src/utils/file_thread_file.cpp +++ b/support/src/utils/file_thread_file.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,41 +25,174 @@ namespace repertory::utils::file { // auto thread_file::attach_file(native_handle handle, // bool read_only) -> fs_file_t {} -thread_file::thread_file(std::string_view path) - : file_(new repertory::utils::file::file(path)) {} - -thread_file::thread_file(std::wstring_view path) - : file_(new repertory::utils::file::file(utils::string::to_utf8(path))) {} - -auto thread_file::attach_file(fs_file_t file) -> fs_file_t {} +auto thread_file::attach_file(fs_file_t file) -> fs_file_t { + return fs_file_t{ + new thread_file(std::move(file)), + }; +} auto thread_file::open_file(std::string_view path, - bool read_only) -> fs_file_t {} + bool read_only) -> fs_file_t { + return fs_file_t{ + new thread_file(file::open_file(path, read_only)), + }; +} auto thread_file::open_or_create_file(std::string_view path, - bool read_only) -> fs_file_t {} + bool read_only) -> fs_file_t { + return fs_file_t{ + new thread_file(file::open_or_create_file(path, read_only)), + }; +} + +void thread_file::io_item::done(bool result) { + unique_mutex_lock lock(*mtx); + complete = true; + success = result; + notify->notify_all(); +} + +void thread_file::io_item::wait() const { + if (complete) { + return; + } + + unique_mutex_lock lock(*mtx); + while (not complete) { + notify->wait(lock); + } + notify->notify_all(); +} + +thread_file::thread_file(std::string_view path) : file_(new file(path)) {} + +thread_file::thread_file(std::wstring_view path) + : file_(new file(utils::string::to_utf8(path))) {} thread_file::thread_file(fs_file_t file) : file_(std::move(file)) {} -void thread_file::close() {} +thread_file::~thread_file() { + close(); + + if (io_thread_) { + io_thread_->join(); + } +} + +void thread_file::close() { + do_io([this]() -> bool { + file_->close(); + stop_requested_ = true; + return true; + }); +} auto thread_file::copy_to(std::string_view new_path, - bool overwrite) const -> bool {} + bool overwrite) const -> bool { + return do_io([this, &new_path, &overwrite]() -> bool { + return file_->copy_to(new_path, overwrite); + }); +} -void thread_file::flush() const {} +auto thread_file::do_io(action_t action) const -> bool { + unique_mutex_lock lock(*mtx_); + if (stop_requested_) { + return false; + } -auto thread_file::move_to(std::string_view path) -> bool {} + if (not io_thread_) { + io_thread_ = std::make_unique([this]() { thread_func(); }); + } + + auto item = std::make_shared(action); + actions_.emplace_back(item); + notify_->notify_all(); + lock.unlock(); + + item->wait(); + + return item->success; +} + +void thread_file::flush() const { + do_io([this]() -> bool { + file_->flush(); + return true; + }); +} + +auto thread_file::move_to(std::string_view path) -> bool { + return do_io([this, &path]() -> bool { return file_->move_to(path); }); +} auto thread_file::read(unsigned char *data, std::size_t to_read, - std::uint64_t offset, std::size_t *total_read) -> bool {} + std::uint64_t offset, std::size_t *total_read) -> bool { + return do_io([this, &data, &to_read, &offset, &total_read]() -> bool { + return file_->read(data, to_read, offset, total_read); + }); +} -auto thread_file::remove() -> bool {} +auto thread_file::remove() -> bool { + return do_io([this]() -> bool { return file_->remove(); }); +} -auto thread_file::truncate(std::size_t size) -> bool {} +void thread_file::thread_func() const { + unique_mutex_lock lock(*mtx_); + notify_->notify_all(); + lock.unlock(); + + const auto run_actions = [this, &lock]() { + auto actions = actions_; + actions_.clear(); + notify_->notify_all(); + lock.unlock(); + + for (auto &&action : actions) { + action->done(action->action()); + } + }; + + while (not stop_requested_) { + lock.lock(); + if (stop_requested_) { + lock.unlock(); + break; + } + + while (not stop_requested_ && actions_.empty()) { + notify_->wait(lock); + } + + if (stop_requested_) { + lock.unlock(); + break; + } + + run_actions(); + } + + lock.lock(); + run_actions(); +} + +auto thread_file::truncate(std::size_t size) -> bool { + return do_io([this, &size]() -> bool { return file_->truncate(size); }); +} auto thread_file::write(const unsigned char *data, std::size_t to_write, std::size_t offset, - std::size_t *total_written) -> bool {} + std::size_t *total_written) -> bool { + return do_io([this, &data, &to_write, &offset, &total_written]() -> bool { + return file_->write(data, to_write, offset, total_written); + }); +} -auto thread_file::size() const -> std::optional {} +auto thread_file::size() const -> std::optional { + std::optional size; + do_io([this, &size]() -> bool { + size = file_->size(); + return size.has_value(); + }); + return size; +} } // namespace repertory::utils::file diff --git a/support/src/utils/hash.cpp b/support/src/utils/hash.cpp index 01798a52..4395d9f4 100644 --- a/support/src/utils/hash.cpp +++ b/support/src/utils/hash.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/path.cpp b/support/src/utils/path.cpp index a7726130..3e730496 100644 --- a/support/src/utils/path.cpp +++ b/support/src/utils/path.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/string.cpp b/support/src/utils/string.cpp index cfaa6968..543b10dd 100644 --- a/support/src/utils/string.cpp +++ b/support/src/utils/string.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/time.cpp b/support/src/utils/time.cpp index 968936b6..944c4a18 100644 --- a/support/src/utils/time.cpp +++ b/support/src/utils/time.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/unix.cpp b/support/src/utils/unix.cpp index ff5f0509..90b55f11 100644 --- a/support/src/utils/unix.cpp +++ b/support/src/utils/unix.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/src/utils/windows.cpp b/support/src/utils/windows.cpp index 4261a2cb..e7dd8a98 100644 --- a/support/src/utils/windows.cpp +++ b/support/src/utils/windows.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/include/test.hpp b/support/test/include/test.hpp index 7aea9c00..52e63a04 100644 --- a/support/test/include/test.hpp +++ b/support/test/include/test.hpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/test.cpp b/support/test/src/test.cpp index a43b1398..f9d78280 100644 --- a/support/test/src/test.cpp +++ b/support/test/src/test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -57,8 +57,10 @@ auto create_random_file(std::size_t size) -> utils::file::i_file & { #if defined(PROJECT_ENABLE_LIBSODIUM) randombytes_buf(buf.data(), buf.size()); #else // !defined(PROJECT_ENABLE_LIBSODIUM) - thread_local std::mt19937 gen(static_cast( - std::time(nullptr) ^ std::random_device{}())); + thread_local std::mt19937 gen{ + static_cast(std::time(nullptr)) ^ + static_cast(std::random_device{}()), + }; std::uniform_int_distribution dis(0U, 255U); std::generate(buf.begin(), buf.end(), [&]() -> auto { return dis(gen); }); #endif // defined(PROJECT_ENABLE_LIBSODIUM) diff --git a/support/test/src/utils/collection_test.cpp b/support/test/src/utils/collection_test.cpp index 39d85bb5..0639e9c1 100644 --- a/support/test/src/utils/collection_test.cpp +++ b/support/test/src/utils/collection_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/common_test.cpp b/support/test/src/utils/common_test.cpp index 5317ce8f..27cf7700 100644 --- a/support/test/src/utils/common_test.cpp +++ b/support/test/src/utils/common_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/db_sqlite_test.cpp b/support/test/src/utils/db_sqlite_test.cpp index d5f964ad..962499a1 100644 --- a/support/test/src/utils/db_sqlite_test.cpp +++ b/support/test/src/utils/db_sqlite_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/encrypting_reader_test.cpp b/support/test/src/utils/encrypting_reader_test.cpp index 078dba8a..3cbaeb42 100644 --- a/support/test/src/utils/encrypting_reader_test.cpp +++ b/support/test/src/utils/encrypting_reader_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +namespace { +const auto get_stop_requested = []() -> bool { return false; }; +} // namespace + namespace repertory { TEST(utils_encrypting_reader, read_file_data) { const auto token = std::string("moose"); @@ -30,9 +34,8 @@ TEST(utils_encrypting_reader, read_file_data) { 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token); + "test.dat", source_file.get_path(), get_stop_requested, token); for (std::uint8_t i = 0U; i < 8U; i++) { data_buffer buffer( @@ -70,9 +73,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks) { 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token); + "test.dat", source_file.get_path(), get_stop_requested, token); for (std::uint8_t i = 0U; i < 8U; i += 2U) { data_buffer buffer( @@ -118,9 +120,8 @@ TEST(utils_encrypting_reader, read_file_data_as_stream) { 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token); + "test.dat", source_file.get_path(), get_stop_requested, token); auto io_stream = reader.create_iostream(); EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); EXPECT_TRUE(io_stream->good()); @@ -171,9 +172,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks_as_stream) { 8u * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token); + "test.dat", source_file.get_path(), get_stop_requested, token); auto io_stream = reader.create_iostream(); EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail()); EXPECT_TRUE(io_stream->good()); diff --git a/support/test/src/utils/encryption_test.cpp b/support/test/src/utils/encryption_test.cpp index 6a0e1913..a07b60f4 100644 --- a/support/test/src/utils/encryption_test.cpp +++ b/support/test/src/utils/encryption_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ #if defined(PROJECT_ENABLE_LIBSODIUM) +namespace { +const auto get_stop_requested = []() -> bool { return false; }; +} // namespace + namespace repertory { static constexpr const std::string_view token{"moose"}; static constexpr const std::wstring_view token_w{L"moose"}; @@ -250,9 +254,8 @@ TEST(utils_encryption, decrypt_file_name) { 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token, + "test.dat", source_file.get_path(), get_stop_requested, token, std::nullopt); auto file_name = reader.get_encrypted_file_name(); @@ -267,9 +270,9 @@ TEST(utils_encryption, decrypt_file_path) { 8U * utils::encryption::encrypting_reader::get_data_chunk_size()); EXPECT_TRUE(source_file); if (source_file) { - stop_type stop_requested{false}; utils::encryption::encrypting_reader reader( - "test.dat", source_file.get_path(), stop_requested, token, "moose/cow"); + "test.dat", source_file.get_path(), get_stop_requested, token, + "moose/cow"); auto file_path = reader.get_encrypted_file_path(); diff --git a/support/test/src/utils/error_test.cpp b/support/test/src/utils/error_test.cpp index 1ca56d25..1b345693 100644 --- a/support/test/src/utils/error_test.cpp +++ b/support/test/src/utils/error_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/file_test.cpp b/support/test/src/utils/file_test.cpp index a24847b0..d31c6b70 100644 --- a/support/test/src/utils/file_test.cpp +++ b/support/test/src/utils/file_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,9 +22,49 @@ #include "test.hpp" namespace { -static constexpr const auto file_type_count{1U}; +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) +#include "utils/file_enc_file.hpp" +constexpr const auto file_type_count{3U}; +#else +constexpr const auto file_type_count{2U}; +#endif + +[[nodiscard]] auto create_file(auto idx, auto path, + bool read_only = false) -> auto { + switch (idx) { + case 0U: + return repertory::utils::file::file::open_or_create_file(path, read_only); + case 1U: + return repertory::utils::file::thread_file::open_or_create_file(path, + read_only); +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + case 2U: + return repertory::utils::file::enc_file::attach_file( + repertory::utils::file::file::open_or_create_file(path, read_only)); +#endif + default: + throw std::runtime_error("not supported"); + } } +[[nodiscard]] auto open_file(auto idx, auto path, + bool read_only = false) -> auto { + switch (idx) { + case 0U: + return repertory::utils::file::file::open_file(path, read_only); + case 1U: + return repertory::utils::file::thread_file::open_file(path, read_only); +#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) + case 2U: + return repertory::utils::file::enc_file::attach_file( + repertory::utils::file::file::open_file(path, read_only)); +#endif + default: + throw std::runtime_error("not supported"); + } +} +} // namespace + namespace repertory { TEST(utils_file, can_create_and_remove_file) { for (auto idx = 0U; idx < file_type_count; ++idx) { @@ -32,8 +72,7 @@ TEST(utils_file, can_create_and_remove_file) { EXPECT_FALSE(utils::file::file(path).exists() || utils::file::directory(path).exists()); - auto file = idx == 0U ? utils::file::file::open_or_create_file(path) - : utils::file::thread_file::open_or_create_file(path); + auto file{create_file(idx, path)}; EXPECT_TRUE(*file); EXPECT_TRUE(utils::file::file(path).exists()); @@ -51,15 +90,12 @@ TEST(utils_file, can_open_file) { auto path = test::generate_test_file_name("utils_file"); { - auto file = idx == 0U - ? utils::file::file::open_or_create_file(path) - : utils::file::thread_file::open_or_create_file(path); + auto file{create_file(idx, path)}; EXPECT_TRUE(*file); } { - auto file = idx == 0U ? utils::file::file::open_file(path) - : utils::file::thread_file::open_file(path); + auto file{create_file(idx, path)}; EXPECT_TRUE(*file); } } @@ -69,8 +105,7 @@ TEST(utils_file, open_file_fails_if_not_found) { for (auto idx = 0U; idx < file_type_count; ++idx) { auto path = test::generate_test_file_name("utils_file"); - auto file = idx == 0U ? utils::file::file::open_file(path) - : utils::file::thread_file::open_file(path); + auto file{open_file(idx, path)}; EXPECT_FALSE(*file); } } @@ -79,9 +114,7 @@ TEST(utils_file, write_fails_for_read_only_file) { for (auto idx = 0U; idx < file_type_count; ++idx) { auto path = test::generate_test_file_name("utils_file"); - auto file = idx == 0U - ? utils::file::file::open_or_create_file(path, true) - : utils::file::thread_file::open_or_create_file(path, true); + auto file{create_file(idx, path, true)}; EXPECT_TRUE(utils::file::file(path).exists()); EXPECT_TRUE(*file); std::size_t bytes_written{}; @@ -188,8 +221,8 @@ TEST(utils_file, read_and_write_json_file_encrypted) { #if defined(PROJECT_ENABLE_LIBDSM) TEST(utils_file, smb_create_smb_path) { - auto path = "//server/share"; - auto rel_path = "test/test.txt"; + const auto *path = "//server/share"; + const auto *rel_path = "test/test.txt"; auto smb_path = utils::file::smb_create_smb_path(path, rel_path); EXPECT_STREQ("//server/share/test/test.txt", smb_path.c_str()); @@ -207,7 +240,7 @@ TEST(utils_file, smb_create_smb_path) { } TEST(utils_file, smb_create_relative_path) { - auto path = "//server/share/test.txt"; + const auto *path = "//server/share/test.txt"; auto rel_path = utils::file::smb_create_relative_path(path); EXPECT_STREQ("\\test.txt", rel_path.c_str()); @@ -225,7 +258,7 @@ TEST(utils_file, smb_create_relative_path) { } TEST(utils_file, smb_create_search_path) { - auto path = "//server/share"; + const auto *path = "//server/share"; auto search_path = utils::file::smb_create_search_path(path); EXPECT_STREQ("\\*", search_path.c_str()); @@ -251,8 +284,8 @@ TEST(utils_file, smb_create_search_path) { } TEST(utils_file, smb_parent_is_same) { - auto path1 = "//server/share"; - auto path2 = "//server/share"; + const auto *path1 = "//server/share"; + const auto *path2 = "//server/share"; EXPECT_TRUE(utils::file::smb_parent_is_same(path1, path2)); path1 = "//server/share/"; @@ -269,8 +302,8 @@ TEST(utils_file, smb_parent_is_same) { } TEST(utils_file, smb_parent_is_not_same) { - auto path1 = "server/share"; - auto path2 = "//server/share"; + const auto *path1 = "server/share"; + const auto *path2 = "//server/share"; EXPECT_FALSE(utils::file::smb_parent_is_same(path1, path2)); path1 = "server/share/"; diff --git a/support/test/src/utils/hash_test.cpp b/support/test/src/utils/hash_test.cpp index 13287bbd..5380d085 100644 --- a/support/test/src/utils/hash_test.cpp +++ b/support/test/src/utils/hash_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/path_test.cpp b/support/test/src/utils/path_test.cpp index 7cd1d336..1194790a 100644 --- a/support/test/src/utils/path_test.cpp +++ b/support/test/src/utils/path_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/support/test/src/utils/string_test.cpp b/support/test/src/utils/string_test.cpp index f25bc9d6..08d64f92 100644 --- a/support/test/src/utils/string_test.cpp +++ b/support/test/src/utils/string_test.cpp @@ -1,5 +1,5 @@ /* - Copyright <2018-2024> + Copyright <2018-2025> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal